用 Go 開發(fā)桌面應用程序(GUI)的幾種方法對比(使用go開發(fā)桌面gui程序)

我想構(gòu)建一個本地 Go 桌面應用程序,有幾種方法可以做到:

  1. Electron[1]:將 Node.js[2]Chromium[3] 瀏覽器綁定在一起,以創(chuàng)建一個打包的本地 Web 應用程序。可與 Go 框架(例如 go-app[4]go-astilectron[5])一起使用。
  2. Lorca[6]:使用本地安裝的 Chrome 瀏覽器,通過 dev-tools communication protocol[7] 實現(xiàn)。
  3. Webview[8]:使用 webview[9] 創(chuàng)建一個本地窗口,并使用 CGo 綁定在其中渲染應用程序。

我已經(jīng)寫過有關構(gòu)建一個簡單的 electron 應用程序的文章[10],因此本文將探討如何使用 Lorca 和 Webview 構(gòu)建應用程序,然后比較這三種的不同。

Lorca

Go 中一個簡單的 Lorca[11] 應用:

func main() { // Create UI with data URI ui, _ := lorca.New("data:text/html," url.PathEscape(` <html>  <head><title>Hello</title></head>  <body><h1>Hello, world!</h1></body> </html> `), "", 600, 200) defer ui.Close() // Create a GoLang function callable from JS ui.Bind("hello", func() string { return "World!" }) // Call above `hello` function then log to the JS console ui.Eval("hello().then( (x) => { console.log(x) })") // Wait until UI window is closed <-ui.Done()}

因為復雜性被隱藏了,所以看起來非常簡單!上面的代碼打開一個 Chome 窗口,通過 websocket 連接到其 dev-tools[12] 端點,發(fā)送要加載的 HTML,并提供 Go 和 JS 之間的通信:

用 Go 開發(fā)桌面應用程序(GUI)的幾種方法對比(使用go開發(fā)桌面gui程序)

更酷的是,您可以在 Chrome 中調(diào)用 JS 函數(shù)并在 Go 中獲取輸出

n := ui.Eval(`Math.random()`).Float()fmt.Println(n)

使用這個庫是如此容易,如此直觀,如此實用,以至于我剛使用它時感到困惑。我以為一定有陷阱,不會這么簡單。但是沒有,它就是這么簡單。

另外一個好處是您可以使用 Chrome 開發(fā)工具來幫助調(diào)試任何問題或調(diào)整布局。另外,鑒于我自 2014 年以來[13]一直在寫 Promise,我喜歡使用 JS Promise 在 Go 和 JS 之間實現(xiàn)異步調(diào)用。

Lorca 的最大缺點是,由于它使用 Chrome,因此某些應用程序詳細信息(如系統(tǒng)菜單,圖標,標題)無法自定義。然后,需要在應用程序優(yōu)化和簡單應用程序之間進行權衡。根據(jù)您構(gòu)建內(nèi)容的不同,有好有弊,例如,如果您正在構(gòu)建內(nèi)部工具,那會很好,但是對于企業(yè)應用程序,這可能看起來并不好。

Webview

Webview[14] 是一個庫,可幫助直接在本地組件之上構(gòu)建 Web 應用程序。執(zhí)行此操作的代碼如下:

func main() { w := webview.New(true) defer w.Destroy() w.SetSize(600, 200, webview.HintNone) // Create a GoLang function callable from JS w.Bind("hello", func() string { return "World!" }) // Create UI with data URI w.Navigate(`data:text/html,  <!doctype html>  <html>   <head><title>Hello</title></head>   <body><h1>Hello, world!</h1></body>   <script> hello().then((x) => { console.log(x) }) </script>  </html>`) w.Run()}

這與 Lorca 非常相似,我認為 Lorca 也是基于 Webview 的。盡管與 Lorca 相似,但輸出還是有些不同:

用 Go 開發(fā)桌面應用程序(GUI)的幾種方法對比(使用go開發(fā)桌面gui程序)

從上圖可以看到 Webview 應用程序窗口沒有陰影,沒有邊框,并且在屏幕的左下角進行了初始化??梢酝ㄟ^將Window返回一個 unsafe.Pointer到 OS 依賴的窗口對象的方法(在 macOS 中是 NSWindow)進行定制。這是開始難的地方。

要使用該 Window 對象,我們必須將 Go 的綁定寫入本地組件。舉例來說,如果我們希望我們的窗口居中啟動,我們會調(diào)用 NSWindow 的 Center 方法。因此,我們需要在三個文件中寫綁定(改編自 gogoa[15]):

ns_window.go

package main// #cgo CFLAGS: -x objective-c// #cgo LDFLAGS: -framework Cocoa//#include "ns_window.h"import "C"import "unsafe"type NSWindow struct { ptr unsafe.Pointer}func (self *NSWindow) Center() { C.Center(self.ptr)}

ns_window.h

#include <Cocoa/Cocoa.h>void Center(void *);

ns_window.m

#include "ns_window.h"void Center(void *self) {  NSWindow *window = self;  [window center];}

然后在main()函數(shù)中,我們可以將窗口居中:

window := NSWindow {w.Window()}window.Center()

與 Lorca 不同,Webview 可以針對我們的應用程序進行完全自定義。問題在于它需要一些工作。

Webview 的一些其他部分使得用它變得有些困難:

  1. 如果使用 Bazel 和 gazelle,則webview生成的Build.bazel文件不正確,clinkopts = ["-framework WebKit"] 必須對其進行修補。
  2. 調(diào)用 w.Init 僅在w.Navigate被調(diào)用時有效,但隨后w.Eval調(diào)用將停止工作。
  3. 要設置標題,您可以如上所述編寫綁定,或者您必須使用Dispatch方法w.Dispatch(func() { w.SetTitle("Title") })。

我不確定有多少是Webview,有多少是 NSWindow。我需要進行更多的調(diào)查和學習,才能更清楚地說明這些發(fā)生的原因。

Electron

之前的文章[16]是關于構(gòu)建一個簡單的 Electron 應用程序的,該應用程序如下所示:

用 Go 開發(fā)桌面應用程序(GUI)的幾種方法對比(使用go開發(fā)桌面gui程序)

Electron 用于許多大型產(chǎn)品,例如 VSCode。這可能是因為將所有內(nèi)容捆綁到一個應用程序中使可移植性變得更加簡單,并且可以廣泛地定制應用程序。將應用程序與瀏覽器和 Node.js 捆綁在一起的不利之處在于,它導致程序 非常龐大。

讓 Go 與 Electron 一起工作也有些困難。但有一些框架可以簡化[17]此過程,例如 go-astilectron[18],不過這些框架很復雜,并且大多數(shù)功能不完整。另一種方法可能是使用我之前寫過的[19] Go 編譯為 WASM ,但這也不是簡單的解決方案。

Electron 的優(yōu)勢在于它是便攜式的,可定制的,并且經(jīng)過了應用程序分發(fā)的嚴格測試。只是和 Go 結(jié)合有點復雜。

三者比較

我認為要進行的主要比較是可定制性與簡單性。到目前為止,Lorca 是最簡單的,其可定制性非常有限,Webview 可以完全自定義,但有些困難,而 Electron 則可以完全自定義,但很難與 Go 一起使用。

同樣,框架之間的捆綁包大小也有很大差異。Lorca 的二進制文件大小為 8.7 MB,Webview 的大小為 3.7Mb,Electron 的大小為 157Mb

調(diào)試工具也有所不同:Lorca 和 Electron 使用 Chrome 開發(fā)工具,而 Webview 使用 Safari 開發(fā)工具。

結(jié)論

Lorca 和 Webview 都可以與 Go 一起很好地使用,最終二進制較小,并且具有類似的 API。主要區(qū)別在于基礎渲染器(本機)和調(diào)試工具。

我認為 Electron 與 Go 一起使用可能太復雜了,但沒有太多困難。

一個潛在的工作流程是在開發(fā)和 Webview 分發(fā)期間使用 Lorca。Lorca 提供了用于調(diào)試和開發(fā)的熟悉工具,其中 Webview 提供了可分發(fā)的可定制性。Lorca 也是很好的備份,可以交叉編譯到 Webview 不支持的其他操作系統(tǒng)。

注意:還有更多類似的選項,wails[20]gotk[21] 可以提供其他方式來構(gòu)建/分發(fā)應用程序。

作者:Graham Jenson

原文鏈接:https://maori.geek.nz/golang-desktop-app-webview-vs-lorca-vs-electron-a5e6b2869391

譯者:polaris

參考資料

[1]

Electron: https://www.electronjs.org/

[2]

Node.js: https://nodejs.org/

[3]

Chromium: https://www.chromium.org/

[4]

go-app: https://github.com/maxence-charriere/go-app

[5]

go-astilectron: https://github.com/asticode/go-astilectron

[6]

Lorca: https://github.com/zserge/lorca

[7]

dev-tools communication protocol: https://chromedevtools.github.io/devtools-protocol/

[8]

Webview: https://github.com/webview/webview

[9]

webview: https://developer.apple.com/documentation/webkit/webview

[10]

構(gòu)建一個簡單的 electron 應用程序的文章: https://maori.geek.nz/building-an-electron-app-with-bazel-d124ed550957

[11]

Lorca: https://github.com/zserge/lorca

[12]

dev-tools: https://chromedevtools.github.io/devtools-protocol/

[13]

自 2014 年以來: https://maori.geek.nz/jquery-promises-and-deferreds-i-promise-this-will-be-short-d10275f82717

[14]

Webview: https://github.com/webview/webview

[15]

gogoa: https://github.com/alediaferia/gogoa

[16]

之前的文章: https://maori.geek.nz/building-an-electron-app-with-bazel-d124ed550957

[17]

簡化: https://github.com/asticode/go-astilectron

[18]

go-astilectron: https://github.com/asticode/go-astilectron

[19]

之前寫過的: https://maori.geek.nz/a-web-app-using-bazel-golang-wasm-and-proto-c020914f4341

[20]

wails: https://github.com/wailsapp/wails

[21]

gotk: https://github.com/gotk3/gotk3

相關新聞

聯(lián)系我們
聯(lián)系我們
公眾號
公眾號
在線咨詢
分享本頁
返回頂部