《真·簡單》Golang 輕量級桌面程式 wails 庫(聖誕節限定)

anyanfei發表於2021-12-23

Golang 輕量級桌面程式 wails2 教學

推薦理由

不依賴 cgo! 不依賴 cgo! 不依賴 cgo!(參考文獻:https://wails.io/blog#no-cgo-dependency)真的不依賴 cgo,且跨平臺,原生渲染 無嵌入式瀏覽器,輕量級,生成的檔案很小,而且只有一個可執行檔案就可執行。

功能介紹

  1. 後端使用標準 Go
  2. 使用任意前端技術構建 UI 介面
  3. 快速為您的 Go 應用生成 Vue、Vuetify、React 前端程式碼
  4. 通過簡單的繫結命令將 Go 方法暴露到前端
  5. 使用原生渲染引擎 - 無嵌入式瀏覽器
  6. 共享事件系統
  7. 原生檔案系統對話方塊
  8. 強大的命令列工具
  9. 跨多個平臺

使用指南

本次教學在 windows 下進行。

安裝

1、首先要安裝三個必要的東西:
npm: https://nodejs.org/en/download/
webviews2: https://developer.microsoft.com/zh-cn/microsoft-edge/webview2/#download-section (下載常青版載入程式
,記得安裝是一定用管理員安裝)
*upx: https://github.com/upx/upx/releases/tag/v3.96 (下載後:upx-3.96-win64.zip,然後放入環境變數)

2、golang版本必須是1.17及其以上,安裝wails工具:
go install github.com/wailsapp/wails/v2/cmd/wails@latest
3、wails doctor (用此命令檢視是否已安裝完整必要依賴) 如下圖:

1

目錄結構概要:

/main.go - 主應用
/frontend/ - 前端專案檔案
/build/ - 專案構建目錄
    /build/appicon.png - 應用程式圖示
    /build/darwin/ - Mac 特定的專案檔案
    /build/windows/ - Windows 特定的專案檔案
/wails.json - 專案配置
/go.mod - Go 模組檔案
/go.sum - Go 模組校驗檔案

frontend目錄沒有特定於 Wails 的內容,可以是您選擇的任何前端專案。
build目錄在構建過程中使用。這些檔案可以修改以自定義您的構建。如果檔案從構建目錄中刪除,將重新生成預設版本。
go.mod中的預設模組名稱是“changeme”。您應該將其更改為更合適的內容。

開始做我們的聖誕樹

1、首先,利用 wails 工具建立一個專案:

wails init -n 專案名稱

2、然後,我們開始寫我們們的 main:(看到 go:embed 註解就知道為什麼要用 go1.17 及其以上的版本了吧)

package main

import (
    "embed"
    "log"

    "github.com/wailsapp/wails/v2/pkg/options/mac"

    "github.com/wailsapp/wails/v2"
    "github.com/wailsapp/wails/v2/pkg/logger"
    "github.com/wailsapp/wails/v2/pkg/options"
    "github.com/wailsapp/wails/v2/pkg/options/windows"
)

//go:embed frontend/src
var assets embed.FS

//go:embed build/appicon.png
var icon []byte

func main() {
    // 建立一個APP結構體例項
    app := NewApp()

    // 給這個APP設定引數
    err := wails.Run(&options.App{
        Title:             "GoCN祝天下所有的Gopher聖誕節快樂",
        Width:             720,
        Height:            570,
        MinWidth:          720,
        MinHeight:         570,
        MaxWidth:          1280,
        MaxHeight:         740,
        DisableResize:     false,
        Fullscreen:        false,
        Frameless:         false,
        StartHidden:       false,
        HideWindowOnClose: false,
        RGBA:              &options.RGBA{R: 33, G: 37, B: 43, A: 255},
        Assets:            assets,
        LogLevel:          logger.DEBUG,
        OnStartup:         app.startup,
        OnDomReady:        app.domReady,
        OnShutdown:        app.shutdown,
        Bind: []interface{}{
            app,
        },
        // Windows平臺特定選項
        Windows: &windows.Options{
            WebviewIsTransparent: false, // 背景是否半透明
            WindowIsTranslucent:  false, // 導航條是否半透明
            DisableWindowIcon:    false, // 是否關閉視窗上的圖示
        },
        Mac: &mac.Options{
            TitleBar:             mac.TitleBarHiddenInset(),
            WebviewIsTransparent: true,
            WindowIsTranslucent:  true,
            About: &mac.AboutInfo{
                Title:   "Vanilla Template",
                Message: "Part of the Wails projects",
                Icon:    icon,
            },
        },
    })

    if err != nil {
        log.Fatal(err)
    }
}

3、寫我們們的前端,在 frontend/src/index.html 下寫入下面的程式碼(我也是抄h 阿泉的):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
<html>
<head>
    <title>聖誕節快樂</title>
    <meta charset="utf-8">
    <style>
        html, body {
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
            border: 0;
        }

        canvas {
            width: 100%;
            height: 100%;
        }

        div {
            margin: 0;
            padding: 0;
            border: 0;
        }

        .nav {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 27px;
            background-color: white;
            color: black;
            text-align: center;
            line-height: 25px;
        }

        a {
            color: black;
            text-decoration: none;
            border-bottom: 1px dashed black;
        }

        a:hover {
            border-bottom: 1px solid red;
        }

        .previous {
            float: left;
            margin-left: 10px;
        }

        .next {
            float: right;
            margin-right: 10px;
        }

        .green {
            color: green;
        }

        .red {
            color: red;
        }

        textarea {
            width: 100%;
            height: 100%;
            border: 0;
            padding: 0;
            margin: 0;
            padding-bottom: 20px;
        }

        .block-outer {
            float: left;
            width: 22%;
            height: 100%;
            padding: 5px;
            border-left: 1px solid black;
            margin: 30px 3px 3px 3px;
        }

        .block-inner {
            height: 68%;
        }

        .one {
            border: 0;
        }
    </style>
</head>
<body marginwidth="0" marginheight="0">
<canvas id="c" height="800" width="300">
    <script>
        var collapsed = true;

        function toggle() {
            var fs = top.document.getElementsByTagName('frameset')[0];
            var f = fs.getElementsByTagName('frame');
            if (collapsed) {
                fs.rows = '250px,*';
                // enable resizing of frames in firefox/opera
                fs.noResize = false;
                f[0].noResize = false;
                f[1].noResize = false;
            } else {
                fs.rows = '30px,*';
                // disable resizing of frames in firefox/opera
                fs.noResize = true;
                f[0].noResize = true;
                f[1].noResize = true;
            }
            collapsed = !collapsed;
        }

    </script>
    <script>
        var b = document.body;
        var c = document.getElementsByTagName('canvas')[0];
        var a = c.getContext('2d');
        document.body.clientWidth; // fix bug in chrome.
    </script>

    <script>
        // start of submission //
        M = Math;
        Q = M.random;
        J = [];
        U = 16;
        T = M.sin;
        E = M.sqrt;
        for (O = k = 0; x = z = j = i = k < 200;) with (M[k] = k ? c.cloneNode(0) : c) {
            width = height = k ? 32 : W = 446;
            with (getContext('2d')) if (k > 10 | !k) for (font = '60px Impact', V = 'rgba('; I = i * U, fillStyle = k ? k == 13 ? V + '205,205,215,.15)' : V + (147 + I) + ',' + (k % 2 ? 128 + I : 0) + ',' + I + ',.5)' : '#cca', i < 7;) beginPath(fill(arc(U - i / 3, 24 - i / 2, k == 13 ? 4 - (i++) / 2 : 8 - i++, 0, M.PI * 2, 1))); else for (; x = T(i), y = Q() * 2 - 1, D = x * x + y * y, B = E(D - x / .9 - 1.5 * y + 1), R = 67 * (B + 1) * (L = k / 9 + .8) >> 1, i++ < W;) if (D < 1) beginPath(strokeStyle = V + R + ',' + (R + B * L >> 0) + ',40,.1)'), moveTo(U + x * 8, U + y * 8), lineTo(U + x * U, U + y * U), stroke();
            for (y = H = k + E(k++) * 25, R = Q() * W; P = 3, j < H;) J[O++] = [x += T(R) * P + Q() * 6 - 3, y += Q() * U - 8, z += T(R - 11) * P + Q() * 6 - 3, j / H * 20 + ((j += U) > H & Q() > .8 ? Q(P = 9) * 4 : 0) >> 1]
        }
        setInterval(function G(m, l) {
            A = T(D - 11);
            if (l) return (m[2] - l[2]) * A + (l[0] - m[0]) * T(D);
            a.clearRect(0, 0, W, W);
            J.sort(G);
            for (i = 0; L = J[i++]; a.drawImage(M[L[3] + 1], 207 + L[0] * A + L[2] * T(D) >> 0, L[1] >> 1)) {
                if (i == 2e3) a.fillText('Merry Christmas!', U, 412);
                if (!(i % 7)) a.drawImage(M[13], ((157 * (i * i) + T(D * 5 + i * i) * 5) % W) >> 0, ((113 * i + (D * i) / 60) % (290 + i / 99)) >> 0);
            }
            D += .02
        }, 1)
        // end of submission //
    </script>
</body>
</html>

4、在當前目錄下用命令列開啟開發者熱載入工具檢視效果:

wails dev

效果圖來啦,提前祝各位 2021 聖誕節快樂~:

1

5、當然我們也可以打包成自己的可執行二進位制檔案喲:

wails build

生成的檔案放在了 build/bin 下。

總結

其實之前我也知道有不少的 go 桌面應用庫,可要麼就是效率低,要麼就是生產的二進位制檔案太大,但 wails 似乎讓我看到了新希望,很多簡單的桌面級小應用可能會因此而誕生更多。

參考資料

  1. wails 中文文件

  2. 原始碼倉庫

更多原創文章乾貨分享,請關注公眾號
  • 《真·簡單》Golang 輕量級桌面程式 wails 庫(聖誕節限定)
  • 加微信實戰群請加微信(註明:實戰群):gocnio

相關文章