「GoCN酷Go推薦」Golang輕量級桌面程序wails2教學
01
不依賴cgo!不依賴cgo!不依賴cgo!真的不依賴cgo,且跨平臺,原生渲染 無嵌入式瀏覽器,輕量級,生成的文件很小,而且只有一個可執(zhí)行文件就可運行。
02
功能介紹
后端使用標準 Go
使用任意前端技術構建 UI 界面
快速為您的 Go 應用生成 Vue、Vuetify、React 前端代碼
通過簡單的綁定命令將 Go 方法暴露到前端
使用原生渲染引擎 - 無嵌入式瀏覽器
共享事件系統(tǒng)
原生文件系統(tǒng)對話框
強大的命令行工具
跨多個平臺
03
使用指南
本次教學在windows下進行。
04
安裝
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,然后放入環(huán)境變量)
2、golang版本必須是1.17及其以上,安裝wails工具:
go?install?github.com/wailsapp/wails/v2/cmd/wails@latest
3、wails doctor (用此命令查看是否已安裝完整必要依賴)?如下圖:

目錄結構概要:
/main.go?-?主應用
/frontend/?-?前端項目文件
/build/?-?項目構建目錄
????/build/appicon.png?-?應用程序圖標
????/build/darwin/?-?Mac?特定的項目文件
????/build/windows/?-?Windows?特定的項目文件
/wails.json?-?項目配置
/go.mod?-?Go?模塊文件
/go.sum?-?Go?模塊校驗文件
frontend目錄沒有特定于 Wails 的內(nèi)容,可以是您選擇的任何前端項目。
build目錄在構建過程中使用。這些文件可以修改以自定義您的構建。如果文件從構建目錄中刪除,將重新生成默認版本。
go.mod中的默認模塊名稱是“changeme”。您應該將其更改為更合適的內(nèi)容。
開始做我們的圣誕樹
1、首先,利用wails工具創(chuàng)建一個項目:
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()?{
?//?創(chuàng)建一個APP結構體實例
?app?:=?NewApp()
?//?給這個APP設置參數(shù)
?err?:=?wails.Run(&options.App{
??Title:?????????????"GoCN祝天下所有的Gopher圣誕節(jié)快樂",
??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(huán)阿泉的):
HTML?PUBLIC?"-//W3C//DTD?HTML?4.01?Frameset//EN"?"http://www.w3.org/TR/html4/frameset.dtd">
<html>
<head>
????<title>圣誕節(jié)快樂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++?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?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、在當前目錄下用命令行開啟開發(fā)者熱加載工具查看效果:
wails?dev
效果圖來啦,提前祝各位2021圣誕節(jié)快樂~:
https://cdn.xinchao.com/goods/202112/6082eea0f69486dc233fecde834dd8911920x1080.gif
5、當然我們也可以打包成自己的可執(zhí)行二進制文件喲:
wails?build
生成的文件放在了build/bin下。
05
總結
其實之前我也知道有不少的go桌面應用庫,可要么就是效率低,要么就是生產(chǎn)的二進制文件太大,但wails似乎讓我看到了新希望,很多簡單的桌面級小應用可能會因此而誕生更多。
06
參考資料
wails中文文檔(https://wails.io/zh-Hans/docs/reference/options)
源碼倉庫((https://github.com/wailsapp/wails)
《酷Go推薦》招募:
各位Gopher同學,最近我們社區(qū)打算推出一個類似GoCN每日新聞的新欄目《酷Go推薦》,主要是每周推薦一個庫或者好的項目,然后寫一點這個庫使用方法或者優(yōu)點之類的,這樣可以真正的幫助到大家能夠?qū)W習到
新的庫,并且知道怎么用。
大概規(guī)則和每日新聞類似,如果報名人多的話每個人一個月輪到一次,歡迎大家報名!戳「閱讀原文」,即可報名
掃碼也可以加入 GoCN 的大家族喲~
