アプリケーション開発
Wailsでアプリケーションを作成する際に、厳格なルールはありませんが、基本的なガイドラインがいくつかあります。
アプリケーションセットアップ
デフォルトのテンプレートを使用した場合、main.goにはアプリケーションの構成および起動コードが記述され、app.goにはアプリケーションのロジック定義が記述されています。
app.goファイルには、メインアプリケーションのフックとして機能する2つのメソッドを持った構造体を定義します。
type App struct {
ctx context.Context
}
func NewApp() *App {
return &App{}
}
func (a *App) startup(ctx context.Context) {
a.ctx = ctx
}
func (a *App) shutdown(ctx context.Context) {
}
-
startupメソッドは、Wailsが起動時に、必要リソースの割り当てが完了した際にすぐに呼び出されます。このメソッド内は、リソースの作成、イベントリスナーの設定、その他アプリケーションに 必要な初期処理を実施するのに適しています。 メソッド呼び出し時に与えられる
context.Contextは、通常は、構造体のフィールドに格納するようにしてください。 なぜならば、このcontextはruntimeを呼び出す際に必要なためです。 このstartupメソッドがエラーを返却した場合、アプリケーションは終了します。 開発モードの場合、コンソールにエラーが出力されます。 -
shutdownメソッドは、シャットダウンプロセスの最後に、Wailsによって呼び出されます。 このメソッド内は、メモリを解放し、任意のシャットダウンタスクを実施するのに適しています。
通常、main.goファイルでは、アプリケーション構成を受け取るwails.Run()メソッドを1回だけ呼び出すようにします。 テンプレートでは、wails.Run()を呼び出す前に、app.goで定義した構造体のインスタンスを作成して、appに格納しています。 アプリケーション構成では、コールバックを追加できます:
func main() {
app := NewApp()
err := wails.Run(&options.App{
Title: "My App",
Width: 800,
Height: 600,
OnStartup: app.startup,
OnShutdown: app.shutdown,
})
if err != nil {
log.Fatal(err)
}
}
アプリケーションのライフサイクルフックについて詳しくは、こちらをご覧ください。
メソッドのバインディング
フロントエンドからGoのメソッドを呼び出したいことがありますよね。 そのようなときは、app.goですでに定義している構造体に、パブリックメソッドを追加しましょう:
type App struct {
ctx context.Context
}
func NewApp() *App {
return &App{}
}
func (a *App) startup(ctx context.Context) {
a.ctx = ctx
}
func (a *App) shutdown(ctx context.Context) {
}
func (a *App) Greet(name string) string {
return fmt.Sprintf("Hello %s!", name)
}
アプリケーション構成のBindキーで、Wailsに何をバインドさせたいかを指定できます:
func main() {
app := NewApp()
err := wails.Run(&options.App{
Title: "My App",
Width: 800,
Height: 600,
OnStartup: app.startup,
OnShutdown: app.shutdown,
Bind: []interface{}{
app,
},
})
if err != nil {
log.Fatal(err)
}
}
これにより、App構造体のすべてのパブリックメソッドがバインドされます(startupメソッド・shutdownメソッドはバインドされません)。
複数の構造体をバインドするときのcontextの扱い
もし、複数の構造体のメソッドをバインドしたくて、かつ、各構造体でランタイム関数を呼び出せるようにcontextを共有したい場合は、OnStartupのコールバック内で、各構造体にcontextを渡してあげるのが良いでしょう:
func main() {
app := NewApp()
otherStruct := NewOtherStruct()
err := wails.Run(&options.App{
Title: "My App",
Width: 800,
Height: 600,
OnStartup: func(ctx context.Context){
app.SetContext(ctx)
otherStruct.SetContext(ctx)
},
OnShutdown: app.shutdown,
Bind: []interface{}{
app,
otherStruct
},
})
if err != nil {
log.Fatal(err)
}
}
Also you might want to use Enums in your structs and have models for them on frontend. In that case you should create array that will contain all possible enum values, instrument enum type and bind it to the app:
type Weekday string
const (
Sunday Weekday = "Sunday"
Monday Weekday = "Monday"
Tuesday Weekday = "Tuesday"
Wednesday Weekday = "Wednesday"
Thursday Weekday = "Thursday"
Friday Weekday = "Friday"
Saturday Weekday = "Saturday"
)
var AllWeekdays = []struct {
Value Weekday
TSName string
}{
{Sunday, "SUNDAY"},
{Monday, "MONDAY"},
{Tuesday, "TUESDAY"},
{Wednesday, "WEDNESDAY"},
{Thursday, "THURSDAY"},
{Friday, "FRIDAY"},
{Saturday, "SATURDAY"},
}
In the main application configuration, the EnumBind key is where we can tell Wails what we want to bind enums as well:
func main() {
app := NewApp()
err := wails.Run(&options.App{
Title: "My App",
Width: 800,
Height: 600,
OnStartup: app.startup,
OnShutdown: app.shutdown,
Bind: []interface{}{
app,
},
EnumBind: []interface{}{
AllWeekdays,
},
})
if err != nil {
log.Fatal(err)
}
}
This will add missing enums to your model.ts file.
バインディングの詳細については、こちらをご覧ください。
アプリケーションメニュー
Wailsでは、アプリケーションにメニューを追加することができます。 追加したい場合は、アプリケーション構成にMenu構造体を渡してください。 通常は、Menuを返すようなメソッドを使用するようにします。ライフサイクルフックに使用されるApp構造体のメソッドとして用意するのが良いでしょう。
func main() {
app := NewApp()
err := wails.Run(&options.App{
Title: "My App",
Width: 800,
Height: 600,
OnStartup: app.startup,
OnShutdown: app.shutdown,
Menu: app.menu(),
Bind: []interface{}{
app,
},
})
if err != nil {
log.Fatal(err)
}
}