Go 言語の Fyne UI フレームワークの基礎編、シンプルな Markdown エディタを作成します。
- 参考コース:Go 言語 + Fyne 迅速入門チュートリアル
- 参考文書:Fyne.io
- コース著者のノートリポジトリ:InkkaPlum チャンネルの Golang および Fyne フレームワークチュートリアルのコードとテキスト版チュートリアル。
前言#
言及すべきは、Go 言語 + Fyne 迅速入門チュートリアルの動画作者が高校生の Up 主であり、スキル範囲はアルゴリズムとデータ構造の問題解決、フロントエンドとバックエンドの Node 開発、Go Web / 総合開発、Unity PHP をカバーしており、英語、日本語、ロシア語を習得しています。若くして優秀で、準研究生の私も恥じ入るばかりで、敬服しています。
彼の多くの動画を見たことで、私にとって非常に有益でした。今回の Fyne シリーズの動画チュートリアルも同様です。
私のように Go の基本文法を学んだばかりの人にとって、小さなプロジェクトを通じて知識を強化し、新しい UI フレームワークに迅速に入門することができます。
Go 言語を学ぶ準備をしている人にとって、これは素晴らしい入門動画です。理解できないことを心配する必要はありません。Up 主は非常に詳細に説明しており、Go 言語のポインタと参照型、構造体とインターフェース、さらには Go 言語の goroutine に至るまで、すべてが説明されています。この動画を見た後に基本文法を学ぶのも良い道で、Go により良く入門できます。
Fyne フレームワーク#
Go 言語と Fyne フレームワークに触れる前、私が作成したすべてのデスクトッププログラムは Python とFletフレームワークを使用していました。
Python を使用する理由は、Python が簡単で扱いやすいためで、今でも Python は私が普段プログラムを書く際の第一選択言語です。大学の授業で C や Java も学び、成績も良かったのですが、やはり Python の方が書きやすいと感じています。
Flet フレームワークを使用するのも、簡単で扱いやすいからです。Flet は Python を使用してウェブ、デスクトップ、モバイルアプリケーションを構築でき、フロントエンド開発の経験がなくても利用できます。私はその文書を読むだけで、簡単にいくつかのデスクトッププログラムを開発でき、非常に良い開発体験を得ました。
例えば、私が以前作成したいくつかの小さなプロジェクトは、すべて Python + Flet フレームワークで作成されています:
最近まで Go 言語を学び始め、Fyne フレームワークに触れるようになりました。Fyne は Flet と実際には同じタイプのクロスプラットフォームフレームワークですが、Go 言語は Python ほど簡潔ではなく、Go 言語の構造体とインターフェースの特性も相まって、書くのがそれほど便利ではありません。しかし、その API 関数インターフェースは非常に直感的でシンプルに設計されており、関数名を見れば何の機能かがわかります。
Fyne も同様にクロスプラットフォームのフレームワークで、Windows、macOS、Linux、Android、iOS をサポートしており、開発者は一度書けばどこでも実行できます。
Fyne はボタン、リスト、入力ボックスなど、豊富な現代的 UI コンポーネントを提供し、開発者が美しいアプリケーションインターフェースを迅速に構築するのを助けます。
Flet と比較して、私は Fyne の API 設計がよりシンプルで直感的であり、初心者や経験豊富な開発者に適していると感じています。また、Fyne はより多くの機能をラップしており、Markdown の表示レンダリングさえも含まれています。
さらに、Go で書かれているため、Fyne は Go の並行性の特性を利用して良好なパフォーマンスを提供し、特に高い同時処理タスクを処理する際に優れたパフォーマンスを発揮します。これは Python には比べられません。
ただし、Fyne にはホットリロードがないのが残念で、Flet はホットリロードをサポートしています。
要するに、Fyne と Flet には多くの類似点があり、私にとっては非常に扱いやすいです。Fyne はその軽量性、パフォーマンス、リソース消費の少なさで知られています。一方、Flet は Python をバックに持ち、シンプルな構文で開発を容易にします。
環境設定#
Go 言語の設定については多くを語る必要はありません。Go 言語入門 1:Go の概要を参考にしてください。
Fyne には MinGW-w 64 のような C コンパイラが必要です。これは、システムのグラフィックドライバや他の低レベルのシステムコンポーネントとの必要な相互作用を処理するために C コンパイラを必要とします。ダウンロードリンク
x86_64-win32-sjlj
を見つけてダウンロードし、解凍します。最後に、その中のbin
フォルダを環境変数に追加します。
新しいプロジェクトフォルダを作成し、モジュールを初期化します。名前は任意または省略できます。
go mod init fyneTest01
プロジェクトフォルダ内で、Fyne モジュールとヘルパーツールをダウンロードします。
go get fyne.io/fyne/v2@latest
go install fyne.io/fyne/v2/cmd/fyne@latest
最初の Fyne プログラム#
新しいmain.go
ファイルを作成し、以下のコードを記述します。
package main
import (
"fmt" // fmtパッケージをインポートし、I/Oのフォーマットに使用
"fyne.io/fyne/v2/app" // Fyneのappパッケージをインポートし、アプリケーションを作成
"fyne.io/fyne/v2/widget" // Fyneのwidgetパッケージをインポートし、UIコンポーネントを作成
)
func main() {
// 新しいFyneアプリケーションを作成
a := app.New()
// 新しいウィンドウを作成し、タイトルを"test app"に設定
w := a.NewWindow("test app")
// ウィンドウの内容をラベルに設定し、ラベルには"Hello Fyne!"を表示
w.SetContent(widget.NewLabel("Hello Fyne!"))
// ウィンドウを表示し、アプリケーションを実行
w.ShowAndRun()
// アプリケーションが実行された後、"Hello, World!"をコンソールに出力
fmt.Println("Hello, World!")
}
注意:w.ShowAndRun()
はw.Show()
とw.Run()
の 2 つに分けることができ、w.Run()
はイベントループを開始し、メインプログラムをブロックします。そのため、最後のHello, World!
はウィンドウが閉じられたときにのみ出力されます。
次に、現在のフォルダのターミナルを開き、次のコマンドを入力します。
go mod tidy
このコマンドは既存の依存関係を整理し、go.mod
を更新し、go.sum
を生成します。これにより、インポートパッケージのエラーを解消できます。go.mod
とgo.sum
はパッケージ管理用のファイルです。
go run .
実際には、go run main.go
を直接実行することはできません。なぜなら、プロジェクト全体には多くの Go プログラムファイルがあり、それらを結合してコンパイルして実行する必要があるため、go run .
を使用するのが非常に便利で、すべての Go プログラムファイルを手動で指定する必要がありません。
これほど多くのプログラムファイルが存在する理由は、Go 言語では同じパッケージ(例えばpackage main
)であれば、どのファイルにあっても相互に呼び出すことができるからです(大文字で始まるものは他のパッケージからアクセス可能)。
注意が必要:プログラムを初めて実行する際、ウィンドウが表示されるまでに時間がかかることがあります。最初は設定ミスかと思いましたので、忍耐強く待つ必要があります。
Fyne のデフォルトフォントは中国語をサポートしていません(新しいバージョンではサポートされています)。中国語が正しく表示されない場合、main()
関数内に以下のコードを追加して、テーマスタイルを変更して中国語フォントを設定できます。NotoSansHans-Regular.ttf
はお好みのフォントに置き換えることができます。
customFont := fyne.NewStaticResource("NotoSansHans.ttf", loadFont("NotoSansHans-Regular.ttf"))
a.Settings().SetTheme(&myTheme{font: customFont})
プロジェクト内にtheme.go
とutil.go
ファイルを作成し、以下のコードを記述します。
theme.go
package main
import (
"fyne.io/fyne/v2" // Fyne GUIツールキットをインポート
"fyne.io/fyne/v2/theme" // デフォルトテーマパッケージをインポート
"image/color" // 色を処理するための画像/色パッケージをインポート
)
// myTheme構造体はカスタムテーマ設定を保存します
type myTheme struct {
font fyne.Resource // カスタムフォントリソース
}
// Fontメソッドは提供されたテキストスタイルに基づいてフォントリソースを返します
func (m *myTheme) Font(s fyne.TextStyle) fyne.Resource {
return m.font // myThemeで定義されたカスタムフォントを返します
}
// Colorメソッドは指定されたテーマカラー名とバリアントに基づいて色を返します
func (m *myTheme) Color(n fyne.ThemeColorName, v fyne.ThemeVariant) color.Color {
// デフォルトテーマに委任して色を取得します
return theme.DefaultTheme().Color(n, v)
}
// Iconメソッドは指定されたテーマアイコン名に基づいてアイコンリソースを返します
func (m *myTheme) Icon(n fyne.ThemeIconName) fyne.Resource {
// デフォルトテーマに委任してアイコンリソースを取得します
return theme.DefaultTheme().Icon(n)
}
// Sizeメソッドは指定されたテーマサイズ名に基づいてサイズを返します
func (m *myTheme) Size(n fyne.ThemeSizeName) float32 {
// デフォルトテーマに委任してサイズを取得します
return theme.DefaultTheme().Size(n)
}
util.go
package main
import (
"os" // osパッケージをインポートし、オペレーティングシステムと対話します
"log" // logパッケージをインポートし、ログを記録します
)
// loadFont関数は指定されたパスのフォントファイルをロードします
// パラメータfontPath:フォントファイルのパス
// 戻り値:フォントファイルのバイトスライス
func loadFont(fontPath string) []byte {
// os.ReadFile関数を使用してフォントファイルを読み取ります
fontData, err := os.ReadFile(fontPath)
if err != nil {
// 読み取り中にエラーが発生した場合、log.Fatalfを使用してエラーメッセージを記録し、プログラムを終了します
log.Fatalf("フォントファイルを読み込めませんでした: %v", err)
}
// 読み取ったフォントデータを返します
return fontData
}
Markdown エディタの実装#
main.go#
まず、main.go
に大まかなエディタのフレームワークを記述します。vscode の Markdown 編集ページを模倣し、左側が入力エリア、右側が表示エリアです。
package main
import (
"fyne.io/fyne/v2" // Fyne GUIツールキットをインポート
"fyne.io/fyne/v2/app" // Fyneアプリケーションモジュールをインポート
"fyne.io/fyne/v2/container" // Fyneコンテナモジュールをインポートし、レイアウト管理に使用
"fyne.io/fyne/v2/widget" // Fyneウィジェットモジュールをインポートし、さまざまなユーザーインターフェースウィジェットを作成
)
// main関数はアプリケーションのエントリーポイントです
func main() {
// 新しいFyneアプリケーションインスタンスを作成
a := app.New()
// 新しいウィンドウを作成し、タイトルを"Markdownエディタ"に設定
w := a.NewWindow("Markdownエディタ")
// Markdownテキストを編集するためのマルチライン入力ボックスを作成
edit := widget.NewMultiLineEntry()
// Markdownプレビューを表示するためのリッチテキストウィジェットを作成
preview := widget.NewRichText()
// 編集ボックスとプレビューを水平分割コンテナに配置
w.SetContent(container.NewHSplit(edit, preview))
// ウィンドウの初期サイズを800x600ピクセルに設定
w.Resize(fyne.NewSize(800, 600))
// ウィンドウを画面の中央に表示
w.CenterOnScreen()
// ウィンドウを表示し、アプリケーションのメインイベントループを実行
w.ShowAndRun()
}
もちろん、これはレイアウトページだけで、機能は何もありません。次に、現在開いているファイルの設定オプションを保存するための構造体を使用して、現在のファイルパス、ファイル名、左右の編集エリアと表示エリアなどの情報を格納します。コードをリファクタリングして次のようにします:
package main
import (
"fyne.io/fyne/v2" // Fyneフレームワークのメインパッケージをインポート
"fyne.io/fyne/v2/app" // Fyneフレームワークのアプリケーションパッケージをインポート
"fyne.io/fyne/v2/container"// Fyneのコンテナパッケージをインポート
"fyne.io/fyne/v2/storage" // Fyneのストレージパッケージをインポート
"fyne.io/fyne/v2/widget" // Fyneのウィジェットパッケージをインポート
)
// config構造体はアプリケーションの設定情報を保存します
type config struct {
EditWidget *widget.Entry // 編集エリア、Entryウィジェットを使用
PreviewWidget *widget.RichText // プレビューエリア、RichTextウィジェットを使用
CurrentFile fyne.URI // 現在開いているファイルのURI
MenuItem *fyne.MenuItem // メニュー項目
BaseTitle string // ウィンドウタイトルの基本文字列
}
var cfg config // config型のグローバル変数cfgを宣言
func main() {
a := app.New() // 新しいFyneアプリケーションインスタンスを作成
// 新しいウィンドウを作成し、タイトルを"Markdownエディタ"に設定
w := a.NewWindow("Markdownエディタ")
cfg.BaseTitle = "Markdownエディタ" // 基本タイトルを設定
// 編集エリアとプレビューエリアのUIを作成
edit, preview := cfg.makeUI()
// メニューを作成
cfg.createMenu(w)
// ウィンドウの内容を水平分割の編集エリアとプレビューエリアに設定
w.SetContent(container.NewHSplit(edit, preview))
// ウィンドウの初期サイズを設定
w.Resize(fyne.Size{Width: 800, Height: 600})
// ウィンドウを画面の中央に表示
w.CenterOnScreen()
// ウィンドウを表示し、アプリケーションを実行
w.ShowAndRun()
}
ここでcfg.makeUI()
とcfg.createMenu(w)
メソッドはまだ実装されていません。コード構造をより規範的にするために、main.go
プログラム内ではソフトウェア全体のグローバルレイアウト設定のみを実装します。
具体的な UI レイアウトの配置、例えば編集エリアとプレビューエリアの作成やメニューの作成機能はui.go
ファイルに配置します。
メニュー内のファイルを開く、ファイルを保存する、名前を付けて保存などの機能は、config.go
内で実装します。
ui.go#
次に、新しいui.go
ファイルを作成し、具体的な UI レイアウトを記述します。
package main
import (
"fyne.io/fyne/v2" // Fyneフレームワークのコアパッケージをインポート
"fyne.io/fyne/v2/widget" // Fyneのウィジェットパッケージをインポート
)
// makeUIメソッドは編集とプレビューエリアのユーザーインターフェースを作成します
func (cfg *config) makeUI() (*widget.Entry, *widget.RichText) {
// 編集用のマルチラインテキスト入力ボックスを作成
edit := widget.NewMultiLineEntry()
// Markdownプレビュー用のリッチテキストウィジェットを作成
preview := widget.NewRichTextFromMarkdown("")
// 作成した編集とプレビューウィジェットをconfig構造体に保存
cfg.EditWidget = edit
cfg.PreviewWidget = preview
// 編集内容が変更されたときにMarkdownを解析し、プレビューを更新
edit.OnChanged = preview.ParseMarkdown
// 編集とプレビューウィジェットを返す
return edit, preview
}
// createMenuメソッドはウィンドウのメニューを作成します
func (cfg *config) createMenu(win fyne.Window) {
// "開く..."メニュー項目を作成し、クリック時に呼び出す関数を指定
open := fyne.NewMenuItem("ファイルを開く", func() {})
// "保存"メニュー項目を作成し、クリック時に呼び出す関数を指定
save := fyne.NewMenuItem("保存", func() {})
// 保存メニュー項目をconfig構造体に保存し、無効にする
cfg.MenuItem = save
cfg.MenuItem.Disabled = true // 空のファイルは保存できない
// "名前を付けて保存..."メニュー項目を作成し、クリック時に呼び出す関数を指定
saveAs := fyne.NewMenuItem("名前を付けて保存", func() {})
// ファイルメニューを作成し、上記のメニュー項目を追加
fileMenu := fyne.NewMenu("ファイル", open, save, saveAs)
// メインメニューを作成し、ファイルメニューをその内容として追加
menu := fyne.NewMainMenu(fileMenu)
// 作成したメインメニューをウィンドウのメニューとして設定
win.SetMainMenu(menu)
}
makeUI
メソッド:
- ユーザーが Markdown テキストを入力するためのマルチラインテキスト入力ボックス
edit
を作成します。 - Fyne が提供する
NewRichTextFromMarkdown("")
メソッドを利用して Markdown のレンダリング結果を表示するためのリッチテキストウィジェットpreview
を作成します。 - 作成した入力ボックスとプレビューウィジェットを
cfg
構造体に保存し、他のメソッドがアクセスできるようにします。 edit
のOnChanged
イベントを設定し、ユーザーが入力を変更するたびにプレビューエリアが再解析されて更新されるようにします。- 編集とプレビューウィジェットを返します。
createMenu
メソッド:
- "ファイルを開く" メニュー項目を作成し、ファイルを開く関数にバインドします。
- "保存" メニュー項目を作成し、ファイルを保存する関数にバインドします。
- "保存" メニュー項目を
cfg
構造体に保存し、その初期状態を無効に設定します。これにより、ファイルが読み込まれていない状態で保存操作を実行できないようにします。 - "名前を付けて保存" メニュー項目を作成し、名前を付けて保存する関数にバインドします。
- "ファイル" メニューを作成し、上記のメニュー項目をまとめます。
- メインメニューを作成し、ファイルメニューをその内容として設定します。
- 作成したメインメニューを指定されたウィンドウに適用し、アプリケーション内で利用できるようにします。
テストプログラム:
go mod tidy
go run .
ファイルを開くcfg.openFunc(win))
、保存cfg.saveFunc(win))
、名前を付けて保存cfg.saveAsFunc(win))
メソッドはまだ実装されておらず、空の匿名関数で代用しています。これらはconfig.go
内で実装します。
config.go#
必要なパッケージをインポートします:
package main
import (
"io" // ファイル内容を読み取るためにioをインポート
"strings" // 文字列操作のためにstringsをインポート
"fyne.io/fyne/v2" // Fyneフレームワークのコアパッケージをインポート
"fyne.io/fyne/v2/dialog" // Fyneのダイアログパッケージをインポート
"fyne.io/fyne/v2/storage" // Fyneのストレージパッケージをインポート
)
メニュー項目はコールバック関数を返す必要があるため、これらの 3 つの機能はすべて関数を返します。
ファイルを開くopenFunc()
機能を実装します。
// openFuncメソッドはファイルを開く関数を返します
func (cfg *config) openFunc(win fyne.Window) func() {
return func() {
// ファイルを開くダイアログを作成
openDialog := dialog.NewFileOpen(func(read fyne.URIReadCloser, err error) {
// エラーハンドリング:エラーが発生した場合、エラーダイアログを表示
if err != nil {
dialog.ShowError(err, win)
return
}
// ファイルが選択されていない場合、直接戻る
if read == nil {
return
}
// ファイル内容を読み取る
data, err := io.ReadAll(read)
if err != nil {
dialog.ShowError(err, win)
return
}
// 読み取った後、ファイルを閉じることを確認
defer read.Close()
// 読み取った内容をエディタに設定
cfg.EditWidget.SetText(string(data))
// 現在のファイルのURIを更新
cfg.CurrentFile = read.URI()
// ウィンドウタイトルを更新し、現在のファイル名を含める
win.SetTitle(cfg.BaseTitle + "-" + read.URI().Name())
cfg.MenuItem.Disabled = false // 保存メニュー項目を有効にする
}, win)
// ファイルフィルタを設定
openDialog.SetFilter(filter)
openDialog.Show() // 開くダイアログを表示
}
}
- 新しいファイルを開くダイアログを作成します。
- ユーザーがファイルを選択したときのロジックを処理し、エラーハンドリングを行います。
- 選択されたファイルの内容を読み取り、エディタに設定します。
- 現在のファイルの URI とウィンドウタイトルを更新し、保存メニュー項目を有効にします。
openDialog.SetFilter(filter)
はファイルフィルタを設定します。.md
または.MD
の拡張子を持つファイルのみを開くことができるようにするため、グローバルフィルタをmain.go
に追加します。
// filterはファイル拡張子をフィルタリングし、.mdおよび.MDファイルのみを許可します
var filter = storage.NewExtensionFileFilter([]string{".md", ".MD"})
次に、保存saveFunc()
機能を実装します。これは、エディタ内のテキストをバイトに変換してファイルに書き込むだけです。
// saveFuncメソッドは現在のファイルを保存する関数を返します
func (cfg *config) saveFunc(win fyne.Window) func() {
return func() {
// 現在開いているファイルがあるか確認
if cfg.CurrentFile != nil {
// 現在のファイルのライターを取得
write, err := storage.Writer(cfg.CurrentFile)
if err != nil {
dialog.ShowError(err, win)
return
}
// エディタ内のテキストをファイルに書き込む
write.Write([]byte(cfg.EditWidget.Text))
// 書き込み後、ファイルを閉じることを確認
defer write.Close()
}
}
}
- 現在開いているファイルがあるか確認し、あればエディタの内容をそのファイルに書き込みます。
- ファイル書き込みのロジックを処理し、エラーハンドリングとファイルの正しいクローズを確認します。
最後に、名前を付けて保存saveAsFunc()
機能を実装します。
// saveAsFuncメソッドはファイルを保存する関数を返します
func (cfg *config) saveAsFunc(win fyne.Window) func() {
return func() {
// ファイル保存ダイアログを作成
saveDialog := dialog.NewFileSave(func(write fyne.URIWriteCloser, err error) {
// エラーハンドリング:エラーが発生した場合、エラーダイアログを表示
if err != nil {
dialog.ShowError(err, win)
return
}
// ファイルが選択されていない場合、直接戻る
if write == nil {
return
}
// ファイル拡張子が.mdであるか確認
if !strings.HasSuffix(strings.ToLower(write.URI().String()), ".md") {
dialog.ShowInformation("エラー", ".md拡張子でなければなりません", win)
return
}
// エディタ内のテキストをファイルに書き込む
write.Write([]uint8(cfg.EditWidget.Text))
// 現在のファイルのURIを更新
cfg.CurrentFile = write.URI()
// 書き込み後、ファイルを閉じることを確認
defer write.Close()
// ウィンドウタイトルを更新し、現在のファイル名を含める
win.SetTitle(cfg.BaseTitle + "-" + write.URI().Name())
cfg.MenuItem.Disabled = false // 保存メニュー項目を有効にする
}, win)
// デフォルトファイル名とフィルタを設定
saveDialog.SetFileName("未命名.md")
saveDialog.SetFilter(filter)
saveDialog.Show() // 保存ダイアログを表示
}
}
- 新しいファイル保存ダイアログを作成します。
- ユーザーがファイルを選択したときのロジックを処理し、エラーハンドリングとファイル拡張子のチェックを行います。
- エディタ内のテキストをユーザーが選択した
.md
ファイルに書き込みます。 - 現在のファイルの URI とウィンドウタイトルを更新し、保存メニュー項目を有効にします。
ui.go
内でこれらの 3 つの機能関数を使用します:
open := fyne.NewMenuItem("ファイルを開く", cfg.openFunc(win))
save := fyne.NewMenuItem("ファイルを保存", cfg.saveFunc(win))
saveAs := fyne.NewMenuItem("名前を付けて保存", cfg.saveAsFunc(win))
テストプログラム#
テストプログラム:
go mod tidy
go run .
Markdown テキストを入力し、名前を付けて保存 test.md
:
ファイルを修正し、新しい段落を追加してファイルを保存:
プログラムを閉じ、新しい空のウィンドウを開き、ファイルを開くを使用して、先ほど保存したファイルを選択して開きます。
保存に成功しました。
テスト中にコンソールにエラーが表示されることがありますが、実行には影響しません:
Fyne error: Preferences API requires a unique ID, use app.NewWithID() or the FyneApp.toml ID field
このエラーメッセージは、Fyne アプリケーションがユニークなアプリケーション ID を提供していないことを示しています。main.go
内でアプリケーションを作成する方法をa := app.New()
からa := app.NewWithID()
メソッドを使用し、ユニークなアプリ ID を渡すことで解決できます。例えば、a := app.NewWithID("01")
のようにします。
プログラムのパッケージ化#
次のコードを実行します:
go install fyne.io/fyne/v2/cmd/fyne@latest
go get fyne.io/fyne/v2/cmd/fyne
fyne.exe
を%GOROOT%\bin
にダウンロードします(環境変数に追加)。
fyne package -os windows -icon Icon.png
-os
:プラットフォームを指定;-icon
:ソフトウェアアイコンを指定。
しばらく待つと、go mod init
で入力した名前の実行可能ファイルが生成されます。
起動速度は非常に速いですが、ファイルサイズはやや大きいかもしれません。これは Fyne が多くの未使用のコンポーネントやリソースをソフトウェアに同梱しているためです。
ソフトウェアのサイズを減らしたい場合は、手動コンパイルを使用できます。
go build -ldflags "-s -w -H windowsgui" -o test.exe .
-ldflags "パラメータ"
:引用符内のパラメータをコンパイラに渡すことを示します。-s
:シンボル情報を削除します。-w
:DWARF デバッグ情報を削除し、gdb デバッグを使用できなくします。-H windowsgui
:Windows GUI 形式でパッケージ化し、DOS ウィンドウを表示しません。
これにより、ソフトウェアのサイズが半分に縮小されます。こうすることで、ソフトウェアのアイコンや情報を直接設定できなくなりますが、後でResource Hackerを使用して追加できます。
さらにソフトウェアのサイズを圧縮したい場合は、UPXツールを使用できます。UPX は高性能な実行可能ファイル圧縮器です。UPX は通常、プログラムや DLL のファイルサイズを約 50%-70% 削減します。
次のコマンドを実行します:
upx --best test.exe
出力結果:
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2024
UPX 4.2.4 Markus Oberhumer, Laszlo Molnar & John Reiser May 9th 2024
File size Ratio Format Name
-------------------- ------ ----------- -----------
22947328 -> 10285568 44.82% win64/pe test.exe
Packed 1 file.
ソフトウェアのサイズがさらに半分に圧縮されたことがわかります。
後記#
以上が Go 言語 Fyne UI フレームワークの迅速な入門の基礎編で、シンプルな Markdown エディタを作成し、Markdown の作成表示やファイルの開閉保存などの機能を実装しました。
この Fyne フレームワークの小プロジェクトについては、原作者の動画をぜひご覧ください:Go 言語 + Fyne 迅速入門チュートリアル。非常に詳細で包括的に説明されています。
もちろん、これは非常にシンプルなプログラムで、Fyne フレームワークを迅速に理解し入門することを目的としています。明らかにこれらの「表面的な知識」は実際の開発には全く不十分ですが、より良い自己学習を助けるでしょう。
今後、Fyne フレームワークをさらに深く学ぶ必要がある場合、公式のドキュメントは素晴らしい学習リソースです。まだ Go 言語の基本文法を学んでいない場合は、8 時間で Golang エンジニアに転職やGo 言語チュートリアル | 菜鳥チュートリアルのチュートリアルを学ぶことをお勧めします。また、私が整理したノートを参考にすることもできます。Go 入門ノート - Pi3's Notes。