Gio UI - Go向けクロスプラットフォームGUI
(gioui.org)- Go開発者が複数のOSとWebAssemblyを対象に即時モードGUIを構築できるようにするライブラリ
- Linux、macOS、Windows、Android、iOS、FreeBSD、OpenBSD、WebAssemblyまで対応し、プラットフォーム対応範囲が広い
- 依存関係を減らし、ウィンドウ管理・入力・GPU描画には各プラットフォームライブラリを活用する設計
- レンダリングにはOpenGL ESとDirect3D 11ベースのPathfinderベクターレンダラーを含み、piet-gpuベースのコンピュートシェーダーレンダラーへ移行中
- テキストや図形をテクスチャに焼き込まず、アウトラインでレンダリングすることで、アニメーション、変換描画、ピクセル解像度非依存をサポート
Gioの目的と対応範囲
- Gioは、Goで効率的かつ滑らかで移植性の高いGUIを作るためのライブラリ
- 対応プラットフォームはLinux、macOS、Windows、Android、iOS、FreeBSD、OpenBSD、WebAssembly
- 高速なデモ用WebAssemblyデモがあり、実行にはWebAssembly対応ブラウザが必要
- サンプルソースはKitchen projectで確認できる
インストールと学習パス
- Gioは少ない依存関係を目標に設計されている
- プラットフォーム別のインストール文書で必要な依存関係を確認できる
- インストール後はLearnドキュメントとHello Worldから始められる
- ショーケースにはgodcr、Tailscale、gotraceui、Sointu、Protonetなどが含まれる
レンダリング技術
- Gioは即時モードグラフィックスのパラダイムの柔軟性と最新の2Dグラフィックス技術を組み合わせている
- ベクターレンダラーはPathfinder projectをベースにしており、OpenGL ESとDirect3D 11上に実装されている
- レンダラーは、piet-gpu上に構築される、より効率的なコンピュートシェーダーベースのレンダラーへ移行中
- テキストや図形はテクスチャ画像に事前に焼き込まず、アウトラインのみを使ってレンダリングする
- 効率的なアニメーションをサポート
- 変換された描画に適している
- ピクセル解像度非依存性を維持できる
スポンサーモデル
- Gioの開発資金はスポンサー支援で賄われている
- プロジェクトが有用なら、OpenCollectiveのGioプロジェクトまたは開発者への直接支援を検討できる
1件のコメント
Hacker News の意見
実際に使ってみたところ、これで本格的で複雑なアプリを作るのは不可能でした
ほかのプラットフォームでは標準で提供される動画、地図、リッチテキストのようなコンポーネントがなく、自分で追加するための明確で簡単な道筋もありません
数か月ごとに API が壊れ、テーマを適用する方法もありません
即時モードのグラフィックスは複雑な状態を管理するまでは良いのですが、そこから先は結局独自の保持モードグラフィックスを実装する必要があり、昔に解決済みの問題を再び持ち込むことになります
piet-gpuベースの華やかなレンダラーも、ベジェ曲線の制御点だけを入力として受け取り、すべてをテッセレーションする方式なので、コンセプトは格好いいものの、実際に円を描くには 4 本のベジェによる近似に頼ることになりますWasm は、コンパイラチームが数年かけて工学的に磨き込まないと製品レベルにならない概念実証に近く、全体としては Go 開発者がリストや入力フィールド程度の単純な UI を作るには悪くなさそうです
Material Design テーマもあり、ライト/ダークモードもあります
ライト/ダークとカスタムテーマを備えた優れた gioui アプリの例は https://github.com/chapar-rest/chapar です
Mac や Windows では
go run .で動きますテキストのカーニング、円弧に沿って流れるテキスト、RTL/LTR も
github.com/go-text/typesettingのおかげで可能ですカレンダースピナーやダイアグラムのような複雑なウィジェットも GitHub にありますが、それらを一つにまとめる取り組みが不足しています
こうしたものが集まれば、より多くの開発者が参加する動機は十分に大きくなると思います
ユーザーコードが壊れないことを重視する文化がないように見えます
どちらも今では安定していて、比較的豊富なコントロール群とライブラリを備えています
Web では Flutter のようにすべてをキャンバスにレンダリングしているようですが、この方式はアクセシビリティとネイティブ感に問題があることで知られています
ラジオボタン間を Tab で移動できず、macOS で
CMD+Aがテキストフィールド全体を選択せず、CTRL+Aならできます可能ではありそうですが、作業量もかなり多そうです
少し話題から外れるが、最近 クロスプラットフォームのモバイル・Webアプリを作る最善の方法が何なのか気になっている
ビジネスロジックとUIを両方共有する場合でも、ビジネスロジックだけを共有する場合でも、という話
gomobile、Rust、TypeScriptのような選択肢で悩んでいた
一時期はTypeScriptが最も移植性の高い技術に見えて、すべてのビジネスロジックに使おうと思っていたが、iOSでJavaScriptを十分な性能で動かす良い方法がないことに気づいた
UIをネイティブで書き、ビジネスロジックだけ共有できればよいならKotlinも選択肢になる: https://kotlinlang.org/docs/multiplatform.html#kotlin-multip...
Composeを使えばKotlinでUIも作れる: https://www.jetbrains.com/lp/compose-multiplatform/
ただしiOS対応はまだアルファで、Webは「experimental」なので、フレームワークの発展に伴ってコードを変更せざるを得ない状況を避けたいなら、すべてのプラットフォームですでにかなり安定しているFlutterが適している
TypeScriptとReactをすでに知っているならReact Nativeも検討できるが、iOSやその他の環境での性能については保証して言うのは難しい: https://reactnative.dev/
何でも解決すると約束して果たせなかったフレームワークをあまりにも多く経験してきた
最初はより早く始められるが、やがてOSアップデート後にFPSをネイティブに近づけたり、システムアニメーションにもっと似せたりするために、コアライブラリにパッチを当てることになる
UIを磨き込まない場合にだけ時間を節約できる
コアロジックは共有できる
gomobileを使っていて概ね気に入っているが、ランタイムのオーバーヘッドが3MBあるためWebには向かない
Kotlin Multiplatformは良さそうに見えたが、基本的なライブラリが欠けており、Kotlin Androidにはすでにあるせいか、マルチプラットフォーム対応版を作る人があまりいなかった
RustとMozillaの言語バインディング層も良さそうだが、まだ使ってはいない
Flutterも悪くはないが、Webではキャンバスにレンダリングするので、感触やアクセシビリティの面でいまひとつ
iOSもImpellerレンダリングエンジンを導入した後でも、依然として遅延の問題がある
Blueskyクライアントを見ると、対応プラットフォーム全体で性能が良く、単一のコードベースを使っている
https://github.com/bluesky-social/social-app
オープンソースで、Android、iOS、Windows、Mac、Linuxをターゲットにしている: https://platform.uno/platforms/
C#を使い、各プラットフォームのネイティブUIフレームワークでビューとコントロールを自動実装する
Visual Studio、VS Code、RiderなどのIDEサポートも良く、それ以外のツールにも制限されない
デザイン協業用のFigmaプラグインもある
コンシューマー向け製品にも良いツールなのかは分からない
私たちの用途には十分合っている。主に太陽光発電所の技術者向けツールであり、劣悪なインターネット環境でクロスプラットフォームTypeScriptを使うことが、小さなチームには負担が大きくなりすぎたためだ
giouiで ストリーミングアプリ を作っているが、とても簡単で、アップグレードもいつも楽だ
Goであり、コア開発者たちが変更をかなり真剣に扱っているからだ
Web GUIが必要なときは、このgiouiプラグインシステムを使っている: https://github.com/gioui-plugins/gio-plugins
WebViewがWeb、デスクトップ、モバイルで動作するのは驚きだ
ディープリンクにも対応していて、メールやMonikeの通知リンクを送ると、ユーザーのアプリがGUI内の正確な位置で開く
すべてのOS向けの通知と共有拡張もあり、本当に完成されたシステムに近いと思う
すべてのOSをサポートするのが難しいという点には同意するが、今の世界では多様性が前提だ
複数の技術を行き来せずに Goだけで これをすべてできる点が良い
Goバックエンドは常にgioとHTMLの両方で動作するように書いている
SEOや動画再生が必要ならWebViewで処理し、gioのWeb側でもGoogle SEOを満たせる
HugoにMarkdownを入れて、Google SEOに見せるようにしている
Go 初心者の立場から見ると、ドキュメントのこの部分が気になる
ops.Add(ColorOp{Color: red})の代わりにop.ColorOp{Color: red}.Add(ops)を使う理由は、Addメソッドがインターフェース型の引数を受け取らないようにして、呼び出し時のアロケーションを避けるためであり、Gio の「zero allocation」設計の中核だと書かれているなぜアロケーションが発生するのか、何が割り当てられるのか、どう節約されるのかを知りたい
関数がインターフェース型の引数を受け取り、そこに純粋な構造体を渡すと、Go はその周囲にラッパーを作るが、これが引用文でいうアロケーション
このラッパーは型/vtable ポインタと構造体データへのポインタからなるポインタのペア
これにより、実行時の型推論と暗黙的なインターフェース拡張が可能になる
つまりインターフェースの実装はメソッドを実装すればよく、
ByteReader extends Readerのように明示的に型を書く必要はないこのコストは使うときだけ払うので、多くの高速パスのコードは可能なら構造体だけを使う
v := interfaceType(concreteTypeValue)をすると、低レベルではだいたい次のようなことが起きるdataPtr := &concreteTypeValue、typePtr := typeData[concreteType]()、そしてデータポインタと型ポインタを持つインターフェース値を作る、という具合ここで最初の行がアロケーションで、私の記憶している規則では Go ではポインタはスタック上の値を指さないため、
concreteTypeValueはヒープに割り当てられなければならないからポインタがスタックを指さないという規則は、ゴルーチンのスタックを動的に伸ばしやすくするためのもの
https://go.dev/doc/faq#stack_or_heap 参照
ColorOp{Color: red}がボクシングされ、ヒープに割り当てられる必要があるops.Addは一般に、具体型の値ではなく、特定のインターフェースを実装した値への太いポインタを受け取るためop.ColorOp{Color: red}.Add(ops)は読み方として変に感じる私には「
op.ColorOp{Color: red}の結果にopsを加える」ように読めるなので関数名を
AddToにしたくなる:op.ColorOp{Color: red}.AddTo(ops)それでも慣用的ではないが、少なくとも関数の引数が変更されるという合図にはなる
Windows 10 と Chrome を使っているごく普通の PC で、最初のページの WASM デモが、テキストがあるべき場所に黒い四角形だけをレンダリングするのが興味深い
Android スマートフォンの Chrome では正しくレンダリングされた
しかもものすごく遅く動作した
Go で Fyne を使って小さなアプリを作ったが、二度と使うつもりはない
Gio も Fyne も、Flutter が提供する磨き込まれた完成度と機能に大きく欠けている
コアロジックは Golang で作り、Android アプリで包むことにしたが、GUI は 2003 年から出てきたように見え、修正する方法も限られていた
すべてのロジックを Go で書き、UI は HTML で作成でき、Web フレームワークを使っても使わなくてもよい
Electron に似ているが、Chrome を同梱せずシステムの Web ビューアを使うのでより軽い
[1] https://github.com/wailsapp/wails
Android アプリとしてどう包んだのか説明してもらえるとうれしい
なぜこういうクロスプラットフォーム GUIはどれも 50 年前にデザインされたように見えるのだろう
デモが自分の環境では動作しない
Win 11 の Chromium でボタンがいくつか見えるが、大部分は全部黒い
Fyne と違って、このライブラリは自分が最初に投げたテストである CJK テキストレンダリングを通過した点が良い兆候
Fyne は、すべてをレンダリングするためのカスタムフォントを 1 つ与えない限り、これができない
世界中で一般的に使われるすべての文字体系はもちろん、絵文字まで満足に含むフォントを 1 つ見つけるのは、幸運を祈るしかない
だからユーザー生成コンテンツ、Web コンテンツ、ローカライズの可能性が少しでもあるものを作る場合、Fyne は私にとって即座に対象外になる