开发人员可以使用几种方法制作桌面应用程序:特定平台的API、本地小部件工具包、混合桌面应用程序开发框架。如果我们计划使用特定平台的API,我们通常要么需要为每个操作系统维护多个代码库,要么使用本地widget工具包,如Qt或GTK,它们是典型的跨平台库。后一种选择在开发者中很受欢迎,因为它们在跨平台的桌面应用开发中很容易使用。
然而,本地widget工具箱是有限的,开发者在使用它们时很难快速制作自定义GUI元素。这就是为什么混合桌面应用框架和库如今如此受欢迎--它们允许开发者使用JavaScript制作跨平台桌面应用。
本教程将解释如何用JavaScript前端和Go后端开发跨平台的桌面应用程序。
用Go进行GUI编程
Go编程语言是一种速度极快、内存安全、并发优先、静态类型的语言。Go语法与C语言相似,但带有垃圾收集器和许多我们在现代编程语言中看到的改进,这使得它在为桌面应用程序的GUI元素编程时成为一个不错的选择。如果我们选择混合方式,就有可能使用任何前端框架来创建GUI,但开发者可以用Go做一些不同的方式。
- 用Go直接调用特定平台的GUI APIs,使用
[syscall](https://golang.org/pkg/syscall/)
模块和C - 使用具有 Go 绑定功能的本地 GUI 工具包,例如Qt 绑定 Go
- 使用Go库/框架构建桌面应用程序,如支持网络前端的Lorca和Go webview。
在本教程中,我们将重点讨论第三种选择。Lorca和Go webview是两个最受欢迎的Go库,用于构建轻量级的、基于JavaScript的跨平台桌面应用程序,因为它们允许我们实际使用我们的Web开发知识。
用Lorca库创建桌面应用程序
Lorca是一个Go库,它帮助开发者用Go后端和JavaScript前端创建轻量级的跨平台桌面应用程序。
Lorca并不像Electron那样将应用程序与网络浏览器捆绑在一起--它使用已安装的谷歌Chrome浏览器来渲染应用程序的网络前端,并通过WebSocket协议在JavaScript和Go之间实现了一个消息传递通道。(如果你的机器上没有安装Chrome,它会提示你下载它;用户也是如此)。
这种双向的信息传递通道有助于Lorca从网络前端调用本地代码。这个概念最初是由谷歌通过他们的Carlo库实现的,只不过Carlo的后端使用的是Node,而不是Go。(Carlo项目已不再被积极维护)。
现在,让我们创建一个简单的Lorca应用程序。我们的示例程序将在启动时显示 "你好,[用户名]",使用一个本地调用来获取你操作系统的当前用户名。
设置Go和Lorca开发者环境
Lorca没有特殊的依赖性,所以你只需要在你的电脑上安装Go语言工具就可以制作Lorca应用程序。你可以直接从官方网站上下载并安装Go语言工具。
安装过程结束后,运行以下命令以确保Go CLI的工作。
$ go version
创建一个Lorca窗口
让我们来熟悉一下Lorca。创建一个新的目录,然后在新创建的目录内创建一个main.go
文件。之后,在main.go
文件中添加以下代码。
package main
import (
"log"
"net/url"
"github.com/zserge/lorca"
)
func main() {
// Pass HTML from data URI.
ui, err := lorca.New("data:text/html,"+url.PathEscape(`
<html>
<head>
<title>Lorca App</title>
</head>
<body>
<h1 style="padding-top: 40vh; text-align: center;">Hello, Lorca!</h1>
</body>
</html>
`), "", 600, 400)
if err != nil {
log.Fatal(err)
}
defer ui.Close()
<-ui.Done()
}
lorca.New
方法通过将所需的配置,如窗口大小和URL,作为命令行参数发送给谷歌浏览器的二进制文件,从而创建一个最小的谷歌浏览器窗口。例如,宽度和高度值被作为--window-size=600,400
发送给谷歌浏览器二进制。
运行以下命令来执行你的应用程序。注意,你只需要在第一次使用Lorca时运行$ go get
,因为Go语言编译器需要从GitHub下载Lorca代码。之后,Go会从硬盘上读取它。
$ go get
$ go run main.go
使用Lorca构建的一个简单的桌面应用程序
这个应用程序从一个HTML数据URI加载前端,但网络前端通常包含几个资源。在下一部分,我们将通过实现一个静态文件服务器来服务我们的网络资源,来扩展这个应用程序,以支持常见的网络前端。
实现后端
现在,我们要实现一个静态文件服务器来为我们的网络前端服务。我们还将向Web前端暴露一个新的Go函数,以获得操作系统的当前用户名。修改你的main.go
文件,加入以下代码。
package main
import (
"log"
"net"
"net/http"
"fmt"
"runtime"
"os"
"github.com/zserge/lorca"
)
func getUserName() string {
var envKey string
if runtime.GOOS == "windows" {
envKey = "USERNAME"
} else {
envKey = "USER"
}
return os.Getenv(envKey)
}
func main() {
// Pass HTML from data URI.
ui, err := lorca.New("", "", 600, 400)
ui.Bind("getUserName", getUserName)
if err != nil {
log.Fatal(err)
}
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
log.Fatal(err)
}
defer ln.Close()
go http.Serve(ln, http.FileServer(http.Dir("./www")))
ui.Load(fmt.Sprintf("http://%s", ln.Addr()))
defer ui.Close()
<-ui.Done()
}
实现前台
上面的Go代码有一个静态文件服务器,为www
目录内的所有资源提供服务,这意味着可以在www
目录内放置任何网络资源。在www
目录内放置一个名为index.html
的文件,代码如下。
<!doctype html>
<html>
<head>
<title>Lorca App</title>
<link rel="shortcut icon" href="favicon.png">
<style>
#textField {
padding-top: 40vh;
text-align: center;
}
</style>
</head>
<body>
<h1 id="textField"></h1>
<script>
(async () => {
try {
let userName = await getUserName();
document.getElementById("textField").innerText = `Hello, ${userName}`;
}
catch (e) {
console.error(e);
}
})();
</script>
</body>
</html>
Lorca将getUserName
Go函数作为一个异步函数暴露给前端。同样地,你可以在Lorca中向前端暴露任何Go方法。运行main.go
文件来测试你的应用程序。
你也可以从你执行go run
命令的终端看到web控制台的输出。
使用ChromeDevTools和终端调试Lorca应用程序
构建和发布你的应用程序
你可以编译Go源文件以获得Lorca应用程序的可执行版本。下面的命令将为你当前的操作系统制作一个优化的可执行文件。
$ go build -ldflags "-s -w" main.go
运行上述命令后,你会发现在你的项目目录内有一个新的二进制文件,名为main
。双击并打开二进制文件以打开你的Lorca应用程序。二进制文件的大小约为7MB--明显小于Electron和NW.js产生的捆绑大小。
请随意使用UPX压缩来进一步减少二进制文件的大小。如果你想把你的JavaScript源文件隐藏起来,可以像第一个例子中描述的那样把你的资源嵌入Go源文件中。
你可以通过使用你的二进制文件为你的应用程序制作安装程序或软件包。例如,可以为Linux用户制作一个AppImage,为Windows用户制作一个MSIX包,为MacOS用户制作一个DMG安装包。
用Go webview库创建桌面应用程序
Lorca使用已安装的Google Chrome浏览器作为UI层。谷歌浏览器是在一个单独的进程中执行的,所以我们不能定制本地窗口。换句话说,Lorca应用程序不能有自定义的窗口图标、窗口样式等。
使用Lorca,你需要谷歌浏览器来运行应用程序,但Go webview库使用操作系统的内置浏览器组件来完成,并使用平台特定的API创建一个本地窗口。
如果你打算为多个操作系统建立一个类似原生的混合桌面应用程序,Go webview库是Lorca库的一个很好的替代品。Go webview库使用同一开发者制作的webview C++库。Tauri和Neutralinojs框架都是用webview C++库开发的。
创建一个简单的Go webview应用程序
Go webview库提供了与Lorca类似的API,开发者环境的设置也是一样的。让我们继续前进,用Go webview库建立一个小应用。
在main.go
文件中加入以下代码,与我们在第一个例子中的做法类似。
package main
import (
"net/url"
"github.com/webview/webview"
)
func main() {
debug := true
w := webview.New(debug)
defer w.Destroy()
w.SetTitle("Go webview app")
w.SetSize(600, 400, webview.HintNone)
w.Navigate("data:text/html," + url.PathEscape(`
<html>
<body>
<h1 style="padding-top: 40vh; text-align: center;">Hello, Go webview!</h1>
</body>
</html>
`))
w.Run()
}
下面的终端命令将运行你的应用程序;关于$ go get
的说明也适用于此。
$ go get
$ go run main.go
使用Go webview构建的一个简单的桌面应用程序
构建和发布的过程与我在Lorca教程中描述的相同。Go webview例子的二进制文件大小应该在2MB左右,但要注意,它可能会根据你使用的Go库而有所不同。
Lorca和Go webview与其他Go框架的比较
Lorca和Go webview都是库,而不是框架。换句话说,这两个库只为基于JavaScript的跨平台桌面应用开发提供了一个最小的解决方案。还有一些用于构建基于JavaScript的桌面应用的Go框架,例如Wails,这是一个基于Go webview的框架,用于用JavaScript构建跨平台的桌面应用。选择库而不是框架将有助于你制作轻量级和非常可定制的桌面应用。
总结
虽然没有像Electron那样的全功能的本地API,但这里最大的优势是你可以有更多的选择,在最终的应用包中只包括你需要的东西。正如我们所讨论的,Lorca的本地窗口定制是有限的,因为它直接使用谷歌浏览器的进程,而Go webview暴露了窗口实例的处理程序,用于本地窗口定制。尽管有这些限制,当你想避免用多余的未使用的代码加载你的应用程序,并且需要你的最终应用程序比Electron能产生的要小得多时,这种方法确实有效。
The postHow to develop cross-platform desktop apps with JavaScript and Goappeared first onLogRocket Blog.