Goは、apiやwebのバックエンド開発、CLIツールの開発でよく利用されます。Goを利用してDesktopアプリを開発する方法の一つにWailsというフレームワークを利用して開発する方法について、紹介したいと思います。
目次
Wailsとは?
Go言語とWebテクノロジー(HTML/Javascript/CSS)を利用したフレームワークとのことです。フロントエンドには、WebViewを利用することでWebテクノロジーを利用することを可能にしているとのことです。公式サイトは、こちらです。
まず触ってみる
下記コマンドでwailsをインストールします。
$ go get github.com/wailsapp/wails/cmd/wails
プロジェクトの雛形を作成します。
$ wails init
メールアドレス、フロントエンドのフレームワーク等の入力を行うと自動で雛形が生成されます。Vue3にも対応しています。作成されるものは、下記のようなものが作成されます。
$ ls
build/ frontend/ go.mod go.sum main.go project.json
ビルド方法は、下記のコマンドを利用します。
$ wails build
ビルドが完了するとbuild
フォルダの配下にバイナリが格納されます。
アーキテクチャーは?
フロントエンド、バックエンドとの通信は、IPC通信を利用しています。下記画像は、Conceptsにあったものを利用しています。
これ以降は、フロントエンドにVueを利用している想定でgo, webフロントとの間でのやりとりの仕組みであるBindingとEventについて簡単に紹介したいと思います。
Binding
GOが提供するインターフェスは、Bindingという機構を使って提供します。提供方法としては、method、struct methodです。先程作成したテンプレートでは、basic()というメソッドがクライントに提供されています。
package main
import (
"github.com/leaanthony/mewn"
"github.com/wailsapp/wails"
)
func basic() string {
return "Hello World!"
}
func main() {
js := mewn.String("./frontend/dist/app.js")
css := mewn.String("./frontend/dist/app.css")
app := wails.CreateApp(&wails.AppConfig{
Width: 1024,
Height: 768,
Title: "cpu",
JS: js,
CSS: css,
Colour: "#131313",
})
app.Bind(basic)
app.Run()
}
利用するフロントエンドでは、下記のようになっています。
import { ref, defineComponent } from "vue";
interface Backend {
basic(): Promise;
}
declare global {
interface Window {
backend: Backend;
}
}
export default defineComponent({
name: "Home",
components: {
HelloWorld,
},
setup() {
const message = ref("Click the Icon");
const getMessage = () => {
window.backend.basic().then(result => {
message.value = result;
});
}
return { message: message, getMessage: getMessage };
},
})
Events
こちらは、nodeJSに詳しい方は、EventEmitterという言えばピンとくるかもしれないですね。
イベントを送信する場合には、runtime.Events.Emit()を利用します。下記コードは、1秒ごとにcountアップした内容を”count”というイベントで送信しています。
type Sample struct {
runtime *wails.Runtime
}
func (p *Sample) WailsInit(runtime *wails.Runtime) error {
p.runtime = runtime
count := 0
go func () {
for {
p.runtime.Events.Emit("count", count)
time.Sleep(time.Second)
count = count + 1
}
}()
return nil
}
フロント側でこのメッセージを受け取るには、mount時にイベントを監視します。
interface Wails {
Events: {
Emit(eventName: string, ...optionalData: any[]): void
On(eventName: string, callback: (...optionalData: any[]) => void): void
}
}
・・・
declare global {
interface Window {
wails: Wails
}
}
・・・
onMounted(() => {
window.wails.Events.On("count", (count: number) => {
console.log(count)
})
上の例では、バックエンドがイベントを発行する側としていますが、javascript側からEventsを発行することもできます。
まとめ
駆け足でさっと見てみきましたが、普段golang、vueでアプリケーションを開発している方は、さっと触りだすことができる印象があります。画面遷移などは、vue-routerを使えば、フロントエンドだけ完結します。ビジネスロジック関連の構築は、golangで行い、必要なタイミングで更新用のデータをイベントで発行するようにすればフロントエンドは、シンプルな開発ができそうです。個人的には、意外と使えるかもしれないという印象でした。お疲れ様でした。