2 ポイント 投稿者 GN⁺ 2024-05-19 | 1件のコメント | WhatsAppで共有
  • 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 ESDirect3D 11上に実装されている
  • レンダラーは、piet-gpu上に構築される、より効率的なコンピュートシェーダーベースのレンダラーへ移行中
  • テキストや図形はテクスチャ画像に事前に焼き込まず、アウトラインのみを使ってレンダリングする
    • 効率的なアニメーションをサポート
    • 変換された描画に適している
    • ピクセル解像度非依存性を維持できる

スポンサーモデル

  • Gioの開発資金はスポンサー支援で賄われている
  • プロジェクトが有用なら、OpenCollectiveのGioプロジェクトまたは開発者への直接支援を検討できる

1件のコメント

 
GN⁺ 2024-05-19
Hacker News の意見
  • 実際に使ってみたところ、これで本格的で複雑なアプリを作るのは不可能でした
    ほかのプラットフォームでは標準で提供される動画、地図、リッチテキストのようなコンポーネントがなく、自分で追加するための明確で簡単な道筋もありません
    数か月ごとに API が壊れ、テーマを適用する方法もありません
    即時モードのグラフィックスは複雑な状態を管理するまでは良いのですが、そこから先は結局独自の保持モードグラフィックスを実装する必要があり、昔に解決済みの問題を再び持ち込むことになります
    piet-gpu ベースの華やかなレンダラーも、ベジェ曲線の制御点だけを入力として受け取り、すべてをテッセレーションする方式なので、コンセプトは格好いいものの、実際に円を描くには 4 本のベジェによる近似に頼ることになります
    Wasm は、コンパイラチームが数年かけて工学的に磨き込まないと製品レベルにならない概念実証に近く、全体としては Go 開発者がリストや入力フィールド程度の単純な UI を作るには悪くなさそうです

    • これで何でも作れますし、v0.6 ではこうした問題はかなり扱いやすくなっています
      Material Design テーマもあり、ライト/ダークモードもあります
      ライト/ダークとカスタムテーマを備えた優れた gioui アプリの例は https://github.com/chapar-rest/chapar です
      Mac や Windows では go run . で動きます
      テキストのカーニング、円弧に沿って流れるテキスト、RTL/LTR も github.com/go-text/typesetting のおかげで可能です
      カレンダースピナーやダイアグラムのような複雑なウィジェットも GitHub にありますが、それらを一つにまとめる取り組みが不足しています
      こうしたものが集まれば、より多くの開発者が参加する動機は十分に大きくなると思います
    • 数か月ごとに壊れる API 変更は、Google のコードでは憂うつになるほど頻繁に見かけます
      ユーザーコードが壊れないことを重視する文化がないように見えます
    • Wasm が重要なら、Uno Platform はかなり良くサポートしており、AvaloniaUI もあります
      どちらも今では安定していて、比較的豊富なコントロール群とライブラリを備えています
  • Web では Flutter のようにすべてをキャンバスにレンダリングしているようですが、この方式はアクセシビリティとネイティブ感に問題があることで知られています

    • Web では確かにネイティブのようには感じられず、アクセシビリティも良くありません
      ラジオボタン間を Tab で移動できず、macOS で CMD+A がテキストフィールド全体を選択せず、CTRL+A ならできます
    • アクセシビリティのために、見えない DOM をキャンバスの横に一緒に置くバリエーションがあるのか気になります
      可能ではありそうですが、作業量もかなり多そうです
    • iPhone ではコピーや貼り付けすらまったくできません
    • これはそもそも Web アプリフレームワークではなく、ネイティブ GUI ツールキットであり、Web バックエンドを持っているものに近いです
  • 少し話題から外れるが、最近 クロスプラットフォームのモバイル・Webアプリを作る最善の方法が何なのか気になっている
    ビジネスロジックとUIを両方共有する場合でも、ビジネスロジックだけを共有する場合でも、という話
    gomobile、Rust、TypeScriptのような選択肢で悩んでいた
    一時期はTypeScriptが最も移植性の高い技術に見えて、すべてのビジネスロジックに使おうと思っていたが、iOSでJavaScriptを十分な性能で動かす良い方法がないことに気づいた

    • 今ならおそらく Flutter が最善である可能性が高い: https://flutter.dev/
      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/
    • 完成度が必要なアプリなら ネイティブUI が正解
      何でも解決すると約束して果たせなかったフレームワークをあまりにも多く経験してきた
      最初はより早く始められるが、やがてOSアップデート後にFPSをネイティブに近づけたり、システムアニメーションにもっと似せたりするために、コアライブラリにパッチを当てることになる
      UIを磨き込まない場合にだけ時間を節約できる
      コアロジックは共有できる
      gomobileを使っていて概ね気に入っているが、ランタイムのオーバーヘッドが3MBあるためWebには向かない
      Kotlin Multiplatformは良さそうに見えたが、基本的なライブラリが欠けており、Kotlin Androidにはすでにあるせいか、マルチプラットフォーム対応版を作る人があまりいなかった
      RustとMozillaの言語バインディング層も良さそうだが、まだ使ってはいない
    • React Native とExpoの組み合わせをおすすめする
      Flutterも悪くはないが、Webではキャンバスにレンダリングするので、感触やアクセシビリティの面でいまひとつ
      iOSもImpellerレンダリングエンジンを導入した後でも、依然として遅延の問題がある
      Blueskyクライアントを見ると、対応プラットフォーム全体で性能が良く、単一のコードベースを使っている
      https://github.com/bluesky-social/social-app
    • Uno(https://platform.uno) がある
      オープンソースで、Android、iOS、Windows、Mac、Linuxをターゲットにしている: https://platform.uno/platforms/
      C#を使い、各プラットフォームのネイティブUIフレームワークでビューとコントロールを自動実装する
      Visual Studio、VS Code、RiderなどのIDEサポートも良く、それ以外のツールにも制限されない
      デザイン協業用のFigmaプラグインもある
    • 私たちは Tauri を使っているが、内部ツールにだけ使っている点が重要
      コンシューマー向け製品にも良いツールなのかは分からない
      私たちの用途には十分合っている。主に太陽光発電所の技術者向けツールであり、劣悪なインターネット環境でクロスプラットフォーム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 がインターフェースで動的型を扱う方法と、構造体がそこに関わる仕組みによるもの
      関数がインターフェース型の引数を受け取り、そこに純粋な構造体を渡すと、Go はその周囲にラッパーを作るが、これが引用文でいうアロケーション
      このラッパーは型/vtable ポインタと構造体データへのポインタからなるポインタのペア
      これにより、実行時の型推論と暗黙的なインターフェース拡張が可能になる
      つまりインターフェースの実装はメソッドを実装すればよく、ByteReader extends Reader のように明示的に型を書く必要はない
      このコストは使うときだけ払うので、多くの高速パスのコードは可能なら構造体だけを使う
    • Go で v := interfaceType(concreteTypeValue) をすると、低レベルではだいたい次のようなことが起きる
      dataPtr := &concreteTypeValuetypePtr := 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)
      それでも慣用的ではないが、少なくとも関数の引数が変更されるという合図にはなる
    • https://stackoverflow.com/questions/39492539/go-implicit-con...
  • Windows 10 と Chrome を使っているごく普通の PC で、最初のページの WASM デモが、テキストがあるべき場所に黒い四角形だけをレンダリングするのが興味深い
    Android スマートフォンの Chrome では正しくレンダリングされた

    • 自分だけではなかった
      しかもものすごく遅く動作した
    • Windows 11 の Edge でも同じ
  • Go で Fyne を使って小さなアプリを作ったが、二度と使うつもりはない
    Gio も Fyne も、Flutter が提供する磨き込まれた完成度と機能に大きく欠けている
    コアロジックは Golang で作り、Android アプリで包むことにしたが、GUI は 2003 年から出てきたように見え、修正する方法も限られていた

    • 別の選択肢として Wails がある
      すべてのロジックを Go で書き、UI は HTML で作成でき、Web フレームワークを使っても使わなくてもよい
      Electron に似ているが、Chrome を同梱せずシステムの Web ビューアを使うのでより軽い
      [1] https://github.com/wailsapp/wails
    • 興味深い
      Android アプリとしてどう包んだのか説明してもらえるとうれしい
  • なぜこういうクロスプラットフォーム GUIはどれも 50 年前にデザインされたように見えるのだろう

    • 1974 年にいったい何を使っていたら、あれが当時のように見えたのか知りたい
  • デモが自分の環境では動作しない
    Win 11 の Chromium でボタンがいくつか見えるが、大部分は全部黒い

  • Fyne と違って、このライブラリは自分が最初に投げたテストである CJK テキストレンダリングを通過した点が良い兆候
    Fyne は、すべてをレンダリングするためのカスタムフォントを 1 つ与えない限り、これができない
    世界中で一般的に使われるすべての文字体系はもちろん、絵文字まで満足に含むフォントを 1 つ見つけるのは、幸運を祈るしかない
    だからユーザー生成コンテンツ、Web コンテンツ、ローカライズの可能性が少しでもあるものを作る場合、Fyne は私にとって即座に対象外になる

    • この点では Noto Sans がかなり良い