2 Punkte von GN⁺ 2024-05-19 | 1 Kommentare | Auf WhatsApp teilen
  • Eine Bibliothek, mit der Go-Entwickler Immediate-Mode-GUIs für mehrere Betriebssysteme und WebAssembly erstellen können
  • Unterstützt Linux, macOS, Windows, Android, iOS, FreeBSD, OpenBSD und WebAssembly und bietet damit eine breite Plattformabdeckung
  • Das Design zielt darauf ab, Abhängigkeiten zu reduzieren und für Fensterverwaltung, Eingabe und GPU-Zeichnen die jeweiligen Plattformbibliotheken zu nutzen
  • Das Rendering umfasst einen auf OpenGL ES und Direct3D 11 basierenden Pathfinder-Vektorrenderer und befindet sich im Übergang zu einem Compute-Shader-Renderer auf Basis von piet-gpu
  • Text und Formen werden nicht als Texturen vorgerendert, sondern als Konturen gerendert, was Animationen, transformiertes Zeichnen und Unabhängigkeit von der Pixelauflösung unterstützt

Ziel und unterstützte Plattformen von Gio

  • Gio ist eine Bibliothek zum Erstellen effizienter, flüssiger und portabler GUIs in Go
  • Unterstützte Plattformen sind Linux, macOS, Windows, Android, iOS, FreeBSD, OpenBSD und WebAssembly
  • Es gibt eine WebAssembly-Demo für eine schnelle Vorführung; zum Ausführen ist ein Browser mit WebAssembly-Unterstützung erforderlich
  • Den Beispielquellcode findet man im Kitchen project

Installation und Lernpfad

  • Gio ist mit dem Ziel weniger Abhängigkeiten konzipiert
  • Die erforderlichen Abhängigkeiten sind in der jeweiligen plattformspezifischen Installationsdokumentation zu finden
  • Nach der Installation kann man mit der Dokumentation Learn und Hello World beginnen
  • Der Showcase umfasst unter anderem godcr, Tailscale, gotraceui, Sointu und Protonet

Rendering-Technologie

  • Gio kombiniert die Flexibilität des Immediate-Mode-Grafikparadigmas mit moderner 2D-Grafiktechnologie
  • Der Vektorrenderer basiert auf dem Pathfinder project und ist auf OpenGL ES und Direct3D 11 implementiert
  • Der Renderer befindet sich im Übergang zu einem effizienteren Compute-Shader-basierten Renderer, der auf piet-gpu aufgebaut wird
  • Text und Formen werden nicht vorab als Texturbilder gebacken, sondern ausschließlich über Konturen gerendert
    • Unterstützt effiziente Animationen
    • Eignet sich für transformiertes Zeichnen
    • Erhält die Unabhängigkeit von der Pixelauflösung

Finanzierungsmodell

  • Die Entwicklung von Gio wird durch Sponsoring finanziert
  • Wenn das Projekt nützlich ist, kann man eine Unterstützung des Gio-Projekts auf OpenCollective oder ein direktes Sponsoring der Entwickler in Betracht ziehen

1 Kommentare

 
GN⁺ 2024-05-19
Hacker-News-Kommentare
  • Nach tatsächlicher Nutzung war es unmöglich, damit ernsthafte komplexe Apps zu bauen
    Es fehlen Komponenten wie Video, Karten oder Rich Text, die andere Plattformen standardmäßig mitbringen, und es gibt auch keinen klaren und einfachen Weg, sie selbst hinzuzufügen
    Alle paar Monate brechen APIs, und es gibt auch keine Möglichkeit, Themes anzuwenden
    Immediate-Mode-Grafik ist gut, solange man noch keinen komplexen Zustand verwalten muss, aber ab dann muss man am Ende doch seine eigene Retained-Mode-Grafik implementieren und holt damit ein längst gelöstes Problem wieder hervor
    Auch der schicke Renderer auf Basis von piet-gpu nimmt nur Bézier-Kontrollpunkte als Eingabe und tesselliert dann alles; das Konzept ist cool, aber um tatsächlich einen Kreis zu zeichnen, ist man auf eine Näherung mit vier Bézier-Kurven angewiesen
    Wasm ist eher ein Proof of Concept, das das Compiler-Team noch einige Jahre technisch ausreifen lassen müsste, bevor es produktionsreif ist, und insgesamt wirkt es für Go-Entwickler brauchbar, wenn sie einfache UIs mit Listen und Eingabefeldern bauen wollen

    • Man kann damit alles Mögliche bauen, und in v0.6 sind diese Probleme deutlich weniger lästig geworden
      Es gibt auch ein Material-Design-Theme sowie einen Light-/Dark-Modus
      Ein großartiges Beispiel für eine gioui-App mit Light-/Dark- und benutzerdefinierten Themes ist https://github.com/chapar-rest/chapar
      Auf Mac oder Windows reicht go run .
      Text-Kerning, Text entlang von Bögen sowie RTL/LTR sind dank github.com/go-text/typesetting ebenfalls möglich
      Komplexe Widgets wie Kalender-Spinner oder Diagramme gibt es auch auf GitHub, aber es fehlt an Bemühungen, diese Dinge an einem Ort zu bündeln
      Wenn das geschieht, dürfte der Anreiz für mehr Entwickler groß genug sein, einzusteigen
    • API-Änderungen, die alle paar Monate etwas kaputt machen, sieht man in Google-Code deprimierend oft
      Es scheint keine Kultur zu geben, in der wichtig ist, dass Nutzer-Code nicht kaputtgeht
    • Wenn Wasm wichtig ist, unterstützt Uno Platform das ziemlich gut, und AvaloniaUI gibt es ebenfalls
      Beide sind derzeit stabil und verfügen über vergleichsweise umfangreiche Sammlungen an Controls und Bibliotheken
  • Im Web scheint es wie Flutter alles auf ein Canvas zu rendern; dieser Ansatz ist bekanntermaßen problematisch bei Barrierefreiheit und nativer Anmutung

    • Im Web fühlt es sich definitiv nicht nativ an und die Barrierefreiheit ist auch nicht gut
      Man kann nicht per Tab zwischen Radio-Buttons wechseln, und auf macOS markiert CMD+A nicht den gesamten Inhalt eines Textfelds, während CTRL+A funktioniert
    • Ich frage mich, ob es eine Variante gibt, die für Barrierefreiheit ein unsichtbares DOM neben dem Canvas mitführt
      Möglich wäre das wohl, aber der Aufwand dürfte ebenfalls beträchtlich sein
    • Auf dem iPhone funktionieren nicht einmal Kopieren oder Einfügen
    • Das ist von vornherein kein Web-App-Framework, sondern eher ein native GUI toolkit mit Web-Backend
  • Etwas abseits des Themas, aber ich frage mich, was heutzutage der beste Weg ist, plattformübergreifende Mobile- und Web-Apps zu entwickeln
    Egal ob man sowohl die Business-Logik als auch die UI teilt oder nur die Business-Logik
    Ich habe zwischen Optionen wie gomobile, Rust und TypeScript geschwankt
    Eine Zeit lang schien TypeScript die portabelste Technologie zu sein, sodass ich es für die gesamte Business-Logik verwenden wollte, aber dann habe ich festgestellt, dass es keinen guten Weg gibt, JavaScript auf iOS mit akzeptabler Performance auszuführen

    • Im Moment ist wahrscheinlich Flutter die beste Wahl: https://flutter.dev/
      Wenn es für dich in Ordnung ist, die UI nativ zu schreiben und nur die Business-Logik zu teilen, ist Kotlin ebenfalls eine Option: https://kotlinlang.org/docs/multiplatform.html#kotlin-multip...
      Mit Compose kann man auch die UI in Kotlin erstellen: https://www.jetbrains.com/lp/compose-multiplatform/
      Allerdings ist die iOS-Unterstützung noch im Alpha-Stadium und das Web ist „experimental“, daher ist Flutter, das auf allen Plattformen bereits recht stabil ist, die richtige Wahl, wenn man nicht in Kauf nehmen will, mit der Weiterentwicklung des Frameworks den Code anpassen zu müssen
      Wenn du TypeScript und React bereits kennst, kannst du auch React Native in Betracht ziehen, aber zur Performance auf iOS oder anderswo würde ich keine Garantie geben: https://reactnative.dev/
    • Für Apps, die einen hohen Reifegrad brauchen, ist native UI die richtige Wahl
      Ich habe zu viele Frameworks erlebt, die versprochen haben, alles zu lösen, und dieses Versprechen nicht halten konnten
      Anfangs kommt man schneller voran, aber schon bald patcht man die Kernbibliotheken, um nach einem OS-Update die FPS wieder in die Nähe von nativ zu bringen oder Systemanimationen ähnlicher wirken zu lassen
      Zeit spart man nur, wenn man die UI nicht wirklich ausarbeitet
      Die Kernlogik kann man gemeinsam nutzen
      Ich verwende gomobile und bin im Großen und Ganzen zufrieden damit, aber der Runtime-Overhead von 3 MB macht es ungeeignet fürs Web
      Kotlin Multiplatform sah gut aus, aber grundlegende Bibliotheken fehlten, und weil es sie für Kotlin Android schon gab, schien kaum jemand plattformübergreifende Entsprechungen zu bauen
      Rust und Mozillas Sprach-Binding-Schicht sehen ebenfalls gut aus, aber ich habe sie noch nicht ausprobiert
    • Ich empfehle die Kombination aus React Native und Expo
      Flutter ist auch nicht schlecht, aber fürs Web rendert es auf ein Canvas, was sich in Bezug auf Gefühl und Barrierefreiheit nicht gut anfühlt
      Auch auf iOS gibt es selbst nach der Einführung der Impeller-Rendering-Engine weiterhin Latenzprobleme
      Wenn man sich den Bluesky-Client ansieht, ist die Performance über die unterstützten Plattformen hinweg ordentlich, und er verwendet eine einzige Codebasis
      https://github.com/bluesky-social/social-app
    • Es gibt Uno(https://platform.uno)
      Es ist Open Source und zielt auf Android, iOS, Windows, Mac und Linux ab: https://platform.uno/platforms/
      Es verwendet C# und implementiert Views und Controls automatisch mit den nativen UI-Frameworks der jeweiligen Plattform
      Die IDE-Unterstützung für Visual Studio, VS Code und Rider ist ebenfalls gut, und man ist auch nicht auf andere Tools beschränkt
      Es gibt auch ein Figma-Plugin für die Design-Zusammenarbeit
    • Wir nutzen Tauri, wobei wichtig ist, dass wir es nur für interne Tools einsetzen
      Ich weiß nicht, ob es auch für Consumer-Produkte ein gutes Werkzeug ist
      Für unseren Einsatz passt es gut genug, hauptsächlich weil es sich um Tools für Techniker von Solarkraftwerken handelt und plattformübergreifendes TypeScript unter schlechten Internetbedingungen für ein kleines Team zu belastend geworden war
  • Ich entwickle mit gioui eine Streaming-App, und es ist sehr einfach, außerdem verlaufen Upgrades immer reibungslos
    Das liegt an Go und daran, dass die Kernentwickler Änderungen ziemlich ernst nehmen
    Wenn ich eine Web-GUI brauche, verwende ich dieses gioui-Plugin-System: https://github.com/gioui-plugins/gio-plugins
    Es ist erstaunlich, dass WebView im Web, auf dem Desktop und auf Mobilgeräten funktioniert
    Deep Links funktionieren ebenfalls, sodass beim Versenden von E-Mails oder Monike-Benachrichtigungslinks die App des Nutzers genau an der richtigen Stelle der GUI geöffnet wird
    Es gibt auch Benachrichtigungen und Share Extensions für alle Betriebssysteme, daher würde ich sagen, dass es fast schon ein wirklich vollständiges System ist
    Ich stimme zu, dass es schwierig ist, alle Betriebssysteme zu unterstützen, aber in der heutigen Welt ist Vielfalt der Standard
    Mir gefällt, dass man das alles nur mit Go umsetzen kann, ohne zwischen mehreren Technologien hin- und herzuwechseln
    Ich schreibe das Go-Backend immer so, dass es sowohl mit gio als auch mit HTML funktioniert
    Wenn SEO oder Videowiedergabe nötig sind, wird das im WebView verarbeitet, und auch Googles SEO-Anforderungen auf der Web-Seite von gio lassen sich erfüllen
    Ich packe Markdown in Hugo, damit Google es für SEO sehen kann

  • Aus Sicht eines Go-Anfängers ist dieser Teil der Dokumentation interessant.
    Es heißt, dass man op.ColorOp{Color: red}.Add(ops) statt ops.Add(ColorOp{Color: red}) verwendet, damit die Add-Methode kein Argument vom Interface-Typ entgegennimmt und so beim Aufruf keine Allokation entsteht; das sei ein zentraler Punkt in Gios „zero allocation“-Design.
    Ich würde gern verstehen, warum dabei eine Allokation entsteht, was genau allokiert wird und wie dadurch etwas eingespart wird.

    • Das liegt daran, wie Go Interfaces für dynamische Typen behandelt und wie Structs damit zusammenspielen.
      Wenn eine Funktion ein Argument vom Interface-Typ entgegennimmt und man ihr ein reines Struct übergibt, baut Go darum einen Wrapper, und genau das ist die im Zitat erwähnte Allokation.
      Dieser Wrapper ist ein Zeigerpaar aus Typ-/vtable-Zeiger und einem Zeiger auf die Struct-Daten.
      Dadurch sind Typinferenz zur Laufzeit und implizite Interface-Erweiterung möglich.
      Ein Interface zu implementieren bedeutet also einfach, die Methoden zu implementieren; man muss den Typ nicht explizit angeben wie bei ByteReader extends Reader.
      Diese Kosten fallen nur bei der Verwendung an, deshalb nutzen viele schnelle Codepfade nach Möglichkeit nur Structs.
    • Wenn man in Go v := interfaceType(concreteTypeValue) macht, passiert auf niedriger Ebene ungefähr Folgendes:
      dataPtr := &concreteTypeValue, typePtr := typeData[concreteType](), und dann wird ein Interface-Wert aus Datenzeiger und Typzeiger aufgebaut.
      Die erste Zeile ist hier die Allokation, denn soweit ich mich an die Regeln erinnere, dürfen Pointer in Go nicht auf Stack-Werte zeigen, also muss concreteTypeValue auf dem Heap allokiert werden.
      Diese Regel, dass Pointer nicht auf den Stack zeigen, dient dazu, dass Goroutine-Stacks leichter dynamisch wachsen können.
      Siehe https://go.dev/doc/faq#stack_or_heap
    • In der ersten Variante muss ColorOp{Color: red} geboxt und auf dem Heap allokiert werden.
      Der Grund ist, dass ops.Add im Allgemeinen einen dicken Pointer auf einen Wert erwartet, der ein bestimmtes Interface implementiert, und nicht einfach einen konkreten Typwert.
    • Andere Antworten haben die eigentliche Frage schon beantwortet, aber unabhängig davon liest sich op.ColorOp{Color: red}.Add(ops) seltsam.
      Für mich klingt es wie „addiere ops zum Ergebnis von op.ColorOp{Color: red}“.
      Deshalb würde ich die Funktion gern AddTo nennen: op.ColorOp{Color: red}.AddTo(ops)
      Das ist zwar immer noch nicht ganz idiomatisch, signalisiert aber wenigstens, dass das Funktionsargument verändert wird.
    • https://stackoverflow.com/questions/39492539/go-implicit-con...
  • Interessant ist, dass auf einem ziemlich gewöhnlichen PC mit Windows 10 und Chrome die WASM-Demo auf der ersten Seite nur schwarze Rechtecke dort rendert, wo eigentlich Text sein sollte.
    In Chrome auf meinem Android-Handy wurde alles korrekt gerendert.

    • Ich war damit nicht allein.
      Außerdem lief es extrem langsam.
    • Unter Edge auf Windows 11 ist es genauso.
  • Ich habe mit Go eine kleine App mit Fyne gebaut und würde es nie wieder benutzen.
    Sowohl Gio als auch Fyne fehlen deutlich die Politur und der Funktionsumfang, die Flutter bietet.
    Ich habe mich entschieden, die Kernlogik in Golang zu schreiben und sie in eine Android-App einzupacken, aber die GUI sah aus wie aus dem Jahr 2003, und die Möglichkeiten, daran etwas zu ändern, waren begrenzt.

    • Eine andere Option ist Wails.
      Man kann die gesamte Logik in Go schreiben und die UI in HTML erstellen, mit oder ohne Web-Framework.
      Es ist ähnlich wie Electron, aber leichter, weil Chrome nicht mit ausgeliefert wird und stattdessen der Web-Viewer des Systems verwendet wird.
      [1] https://github.com/wailsapp/wails
    • Interessant.
      Es wäre schön, wenn du erklären könntest, wie du es in eine Android-App gepackt hast.
  • Warum sehen diese Cross-Platform-GUIs alle so aus, als wären sie vor 50 Jahren entworfen worden?

    • Ich würde gern wissen, was man 1974 bitte benutzt hat, damit das danach aussieht.
  • Die Demo funktioniert bei mir nicht.
    In Chromium unter Windows 11 sehe ich ein paar Buttons, aber das meiste ist komplett schwarz.

  • Im Unterschied zu Fyne ist es ein gutes Zeichen, dass diese Library meinen ersten Test bestanden hat: CJK-Textrendering.
    Fyne schafft das nicht, wenn man ihm nicht eine einzige Custom-Font gibt, die alles rendern kann.
    Eine einzelne Font zu finden, die alle weltweit gebräuchlichen Schriftsysteme und dazu noch Emoji zufriedenstellend abdeckt, ist Glückssache.
    Deshalb ist Fyne für mich sofort raus, wenn ich etwas mit nutzergenerierten Inhalten, Web-Inhalten oder auch nur der geringsten Möglichkeit von Lokalisierung bauen will.

    • Noto Sans ist in dieser Hinsicht ziemlich gut.