
前言
Go語言(也稱為Golang)是 google 在 2009 年推出的一種編譯型程式設計語言。相對于其他程式設計語言,golang 具有編寫并發程式或網絡互動簡單、資料類型豐富、編譯速度快等特點,比較适合于高性能、高并發場景。Go 語言一直在網絡程式設計、雲平台開發、分布式系統等領域占據着重要的地位,尤其在雲原生領域,殺手級項目 Docker 和 Kubernetes 都是采用 Go 語言開發的。而在其他領域,比如桌面應用開發,也有一些架構可以使用,本篇文章就來介紹如何使用 Go 語言 和 HTML5 來開發一個 MacOS App。
架構選擇
這裡我選用了
echo作為 web 架構,當然也可以選擇其他的 web 架構,選擇 echo 隻不過因為其比較輕量。要做桌面應用,還需要一個 GUI 架構來建構應用,這裡我選擇的是
Lorca,使用 Lorca 可以用 Go 編寫 HTML5 桌面程式,依賴 Chrome 進行 UI 渲染,但卻不需要把 Chrome 打包到應用中,也就是說使用應用的電腦,需要安裝 Chrome。
lorca
echo 的使用方式中規中矩,沒有什麼需要介紹的。這裡簡要介紹一下 lorca,其的使用方法和原理都很簡單,可以将其看做是一個浏覽器,可在其上運作 web 應用,lorca 可直接将 web 應用包裝成桌面應用。這裡提供一個簡單的示例:
ui, _ := lorca.New("", "", 480, 320)
defer ui.Close()
// Bind Go function to be available in JS. Go function may be long-running and
// blocking - in JS it's represented with a Promise.
ui.Bind("add", func(a, b int) int { return a + b })
// Call JS function from Go. Functions may be asynchronous, i.e. return promises
n := ui.Eval(`Math.random()`).Float()
fmt.Println(n)
// Call JS that calls Go and so on and so on...
m := ui.Eval(`add(2, 3)`).Int()
fmt.Println(m)
// Wait for the browser window to be closed
<-ui.Done()
制作 MacOS App
在完成基本的編碼後,接下來的工作才是重點:将應用包裝成一個 MacOS APP。
制作圖示
一個 MacOS APP 首先需要一個圖示,這裡請選擇一個 1024 X 1024 分辨率,背景透明的 PNG 圖檔。這裡假設該圖檔名為
logo.png
:
- 建立一個名為
的臨時目錄,用于存放不同大小的臨時圖檔tmp.iconset
- 執行如下指令,将原圖轉為不同大小的圖檔并放入臨時目錄
$ sips -z 16 16 logo.png --out tmp.iconset/icon_16x16.png
$ sips -z 32 32 logo.png --out tmp.iconset/[email protected]
$ sips -z 32 32 logo.png --out tmp.iconset/icon_32x32.png
$ sips -z 64 64 logo.png --out tmp.iconset/[email protected]
$ sips -z 128 128 logo.png --out tmp.iconset/icon_128x128.png
$ sips -z 256 256 logo.png --out tmp.iconset/[email protected]
$ sips -z 256 256 logo.png --out tmp.iconset/icon_256x256.png
$ sips -z 512 512 logo.png --out tmp.iconset/[email protected]
$ sips -z 512 512 logo.png --out tmp.iconset/icon_512x512.png
$ sips -z 1024 1024 logo.png --out tmp.iconset/[email protected]
- 使用 iconutil 生成圖示
$ iconutil -c icns tmp.iconset -o icon.icns
icon.icns
就是制作好的 MacOS App 圖示。
制作 .app bundle
macOS 上安裝的可運作程式是一個
.app
的目錄,裡面包含了應用的二進制檔案、資源檔案以及清單檔案。其的目錄結構為(也可以通過”右鍵-顯示包内容“來檢視
.app
檔案内容):
$ tree Kustomize.app
Kustomize.app
└── Contents
├── Info.plist
├── MacOS
│ └── kustomize
└── Resources
├── assets
│ ├── css
│ │ ├── page.css
│ │ ├── prism.css
│ │ └── weui.min.css
│ ├── images
│ │ └── favicon.ico
│ └── js
│ ├── jquery.min.js
│ ├── prism.js
│ └── weui.min.js
├── icon.icns
└── views
├── copyreght.html
├── footer.html
├── header.html
├── index.html
└── yaml.html
可以看到:
-
為清單檔案,存儲應用資訊Info.plist
-
中存放二進制可執行檔案MacOS
-
存放靜态資源檔案和圖示Resources
Info.plist 檔案
這是一個清單檔案,根據自己應用的内容對齊進行修改,更多内容可以參考
trayhost項目的說明。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>kustomize</string>
<key>CFBundleIconFile</key>
<string>icon.icns</string>
<key>CFBundleIdentifier</key>
<string>io.guoxudong.kustomize-remote-observer</string>
<key>NSHighResolutionCapable</key>
<true/>
<key>LSUIElement</key>
<string>1</string>
</dict>
</plist>
使用腳本建構 App
上面的這些隻不過是介紹一下原理及手動修改方式,實際應用中可以使用腳本來完成這些工作。使用如下腳本,可以一鍵完成:
-
應用的建構.app
- go 應用的打包
- 清單檔案的生成
- 靜态資源的拷貝
#!/bin/sh
APP="Kustomize.app"
mkdir -p $APP/Contents/{MacOS,Resources}
go build -o $APP/Contents/MacOS/kustomize
cat > $APP/Contents/Info.plist << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>kustomize</string>
<key>CFBundleIconFile</key>
<string>icon.icns</string>
<key>CFBundleIdentifier</key>
<string>io.guoxudong.kustomize-remote-observer</string>
<key>NSHighResolutionCapable</key>
<true/>
<key>LSUIElement</key>
<string>1</string>
</dict>
</plist>
EOF
cp icons/icon.icns $APP/Contents/Resources/icon.icns
cp -r assets $APP/Contents/Resources/assets
cp -r views $APP/Contents/Resources/views
find $APP
注意
在 MacOS 中,當您運作 App bundle 時,程序的工作目錄是根目錄(
/
),而不是
Contents/Resources
目錄。如果需要從
Resources
加載資源,則需要進行如下更改:
ep, err := os.Executable()
if err != nil {
log.Fatalln("os.Executable:", err)
}
err = os.Chdir(filepath.Join(filepath.Dir(ep), "..", "Resources"))
if err != nil {
log.Fatalln("os.Chdir:", err)
}
制作 DMG 檔案
DMG 檔案用于分發應用程式,将
.app
檔案壓縮制成鏡像,可以很友善的通過拖拽的形式完成安裝。
制作模闆
制作 DMG 檔案首先需要制作模闆。打開
磁盤工具 - 檔案 - 建立映象 - 空白映象
(或直接按
⌘N
)建立一個新的磁盤鏡像。給它取個名字,設定足夠的空間空間,分區選擇
CD/DVD
。
制作好後,打開該鏡像,進行檔案夾視圖定制(按
⌘J
),選擇展示圖示的大小及背景圖檔,這裡可以隐藏工具欄
右鍵
應用程式
選擇制作替身,将替身移動到鏡像中
将打包好的 app 加入到 DMG 鏡像中就完成了 DMG 模闆的定制
轉換 DMG 檔案
目前的 DMG 模闆檔案還沒有經過壓縮并且是可寫的狀态,這樣是不能作為程式釋出的,是以這裡需要對模闆進行轉換。
打開
磁盤工具 - 映象 - 轉換
,然後選擇壓縮後存儲的目錄就完成了最後一步 DMG 檔案的轉換。
現在點開 DMG 檔案,将應用拖動到應用程式中,就可以在啟動台中看到我們的應用程式了!
自動化
上面隻是展示了如何手動制作 DMG 鏡像,實際使用當然是要将這些步驟自動化的。我将這部分内容做成了一個 go 腳本,原理其實就是使用
hdiutil
這個指令行工具,有興趣的同學可以文末找到項目位址,
Makefile
中有詳細建構的指令。
項目展示
我使用 Go + HTML5 制作了一個
Kustomize Remote
的項目,可以從遠端 kustomize 項目中擷取配置,并 build 成 yaml 檔案,UI樣式為微信風格,支援 public 和 private 項目。
項目位址:
https://github.com/sunny0826/kustomize-remote-observer也可以直接在
release 頁面下載下傳 DMG 檔案安裝試用,隻需 Mac 上有 Chrome 即可。
結語
Go 語言一直在網絡程式設計、雲平台開發、分布式系統等領域占據着重要的地位,但是像桌面應用或者機器學習這樣的領域,同樣也能做出不錯的效果。作為一門受歡迎的程式設計語言 Golang 已經有十多年的曆史了,相信它在将來還能在更多的領域煥發生機,創造輝煌。