Hacker News new | past | comments | ask | show | jobs | submit login
Gio UI – Cross-platform GUI for Go (gioui.org)
299 points by gjvc 7 months ago | hide | past | favorite | 214 comments



Experience report: Impossible to write any serious complex application in this. Lacks components for basic things everyone gets for free on other platforms, things like video, maps or rich text components. Nor does if offer any clear easy path to add them yourself. Breaking API changes every few months. No way to theme something. Immediate mode graphics are great until you need to start managing some complex state, then you are forced to implement your own retainer mode graphics. Again it reintroduces problems that have been solved a long time ago. Very fancy renderer based on piet-gpu that only takes control points of a bezier curve as input and tessellates everything from that. Cool concept, but try drawing a real circle with that, and some some approximation with 4 bezier curves. Wasm is not more then a proof of concept that won't be production ready without years of engineering by compile team. Overall nice for Go developers that wanna do some simple UI with lists and input fields.


You can write anything with it.

V0.6 made your issues much less tricky.

Also there is a Material Design theme. And also light and dark.

Here is an excellent example of a gioui app that has light / dark with a custom theme.

https://github.com/chapar-rest/chapar

If you’re on MAC or Windows it’s just “ go run .”.

If you wanted text keening or text sweeping around an arc or RTL / LRT it can do it thanks to github.com/go-text/typesetting

Complex widgets for Calendar spinners or diagrams are out there on GitHub. An effort to bring these together is lacking, and I reckon that if all these things weee brought together it would definitely encourage more developers to dive in.


> Breaking API changes every few months.

I find this to be the case with a depressing amount of Google code. They do not seem to have a culture which values not breaking their users' code.


It's even a core point for Carbon, their hopeful C++ replacement

Under language goals on their readme,

> We also have explicit non-goals for Carbon, notably including:

> * A stable application binary interface (ABI) for the entire language and library

> * Perfect backwards or forwards compatibility

There's also this blurb

> Our goals are focused on migration from one version of Carbon to the next rather than compatibility between them. This is rooted in our experience with evolving software over time more generally and a live-at-head model. Any transition, whether based on backward compatibility or a migration plan, will require some manual intervention despite our best efforts, due to Hyrum's Law, and so we should acknowledge that upgrades require active migrations.

https://github.com/carbon-language/carbon-lang/blob/trunk/do...


Gio isn't made by Google


>Go was invented at Google by Rob Pike, Ken Thomson, and Robert Griesemer.


My bad, you said Gio.


This isn’t true in Flutter. They literally bake into the CLI with each release which will automatically identify and upgrade any parts in your application using old APIs without any intervention required. It’s literally the opposite of what you’re describing here.

https://docs.flutter.dev/tools/flutter-fix


What you described is Google breaking your code constantly but also giving you a tool to automatically fix the code they broke, so it fits well within the general philosophy of not taking breaking changes seriously.

It sounds like the tool might make the specific case of flutter version upgrades easier though, if the tool works well, so that's nice. Most Google software doesn't come with similar tools.


There is nothing about that that allows you to come to a good faith conclusion of “doesn’t take breaking changes seriously” when they literally do all of the work for you.


You're right. I should've said they have no qualms about introducing breaking changes.


If you care about WASM, Uno Platform has decent support for it, there’s also AvaloniaUI and both are stable at this point with relatively rich control collections and libraries.


Seemingly it's using a <canvas> to render everything just like Flutter on Web, which is known to have problems with accessibility and feel non-native.


Definitely doesn't feel native or accessible on web. Can't tab between radio buttons. On macOS CMD+A doesn't select all text field text (CTRL+A does).


I’m curious if anyone has a variant of this idea where an invisible DOM lives alongside the canvas for accessibility reasons. It should work but I imagine it would also take a lot of work.


Check out the approach that Pax is taking.[0]

Pax renders vector graphics to canvas layers and composites + clips + occludes native elements (web DOM nodes, iOS SwiftUI Text elements, etc.) in the same space to make a cohesive scene.

This solves accessibility and SEO, as well as dramatically reducing runtime size (~100KB WASM network footprint) because text rendering and atomic native UI elements don't need to be reinvented.

To my knowledge we're the only ones taking this particular approach so far (I'm on the team behind Pax) but it works quite well. Yes it was a lot of work.

[0] see pax.dev or check out a simple example: https://static.pax.dev/space-game/ ; source code for space game in examples on github https://www.github.com/paxengine/pax


This is how Flutter for web implements accessibility. It's been a while since I checked, but last time I tried using a Flutter app on the web with a screen reader, there were problems. I don't remember specifics.


Flutter on Web is still mainly not accessible when it comes to screen readers, despite what anyone wants to make you believe.

I checked it last a couple of weeks ago on my Android phone, and the result was so poor, I didn't check with other platforms.

You need to "opt in" to accessibility as a user, so in the beginning you have one button visible to screen readers, then your screen reader sees that single button, then you need to "double tap to activate" to make the rest of the document screen readable.

Then, somehow they made a funky screen reader voice read stuff out loud, not my system's voice, with all the awkwardness and issues that come with it.

On lists, it only recognized the items that were on screen, if you had to "scroll", you are out of luck.

Now, I'm sure someone will come and tell me how I'm holding it wrong, but somehow, every website and even Flutter on mobile got the accessibility mainly right by default, on Flutter web the accessibility situation is very poor.


The canvas element allows children specifically for this purpose, iirc.

Edit: unless you're doing something like flutter where your goal is to escape the DOM/JS paradigm in your code entirely, the fallback DOM nodes don't tend to be implemented too often.

The biggest reason is that canvas is for things with interactive/consumptive patterns that don't work well without vision.

Cute animations, 3d explorers and configurators, that sort of thing.

For users who rely on screen readers, they are better served by a DOM and interactive patterns that are not strictly recreating the canvas.

As an example, canvas based animations might have a fallback equivalent to an alt attribute on an image. A 3d explorer or configurator might be represented in DOM as a multi step form with verbose descriptions- no need to recreate drag and drop, camera controls, or anything else.

So, if you're not automating it like flutter is (and even if you are) what you really need to do is effectively an entirely alternate UX for screen reading users... Trying to get your product team to budget that is difficult despite being a Good Thing to do.


That's actually how Flutter works now if you enable web accessibility, and it does take a lot of work, and come with a performance cost: https://medium.com/flutter/accessibility-in-flutter-on-the-w...


Can’t even copy or paste at all on an iPhone.


I mean it's not primarily a web app framework, it's a native GUI toolkit which has a web back-end.


It isn't native on any other platform either.


I used "native" as opposed to "web" (think "native code"), not as in "uses Cocoa on macOS". I should've been more precise.


A bit off-topic, but what's the best method to build cross-platform mobile & web apps nowadays ? I'm talking either business logic + UI , or just business logic ?

like gomobile, rust, typescript, etc ?

At some point i thought about using typescript for all business logic, as it seemed the most portable tech, but i realized there's no good way to have decent performance running javascript on iOS.


The best option is probably Flutter right now: https://flutter.dev/

If you don't mind writing the UI native, sharing only business logic code, Kotlin is an option: https://kotlinlang.org/docs/multiplatform.html#kotlin-multip...

Kotlin also can do the UI if you use Compose: https://www.jetbrains.com/lp/compose-multiplatform/ ... however, iOS support is still in alpha, and Web is "experimental". If you're not willing to cope with that (expect to have to change your code as they develop the framework) then Flutter is the way as it's pretty stable already on all platforms.

If you already know Typescript and React, you may also consider React Native (but I can't attest to its performance on iOS or anywhere else): https://reactnative.dev/


I would also add Tauri to the list as they now support mobile as well https://v2.tauri.app/blog/tauri-2-0-0-beta/

I think all cross platform frameworks come with some kind of drawbacks and in most cases, learning about the underlying native platforms is unavoidable (like widgets, visionOS support etc).

So I wouldn’t worry too much or get into a FOMO decision block - I’d pick the one that feels most fun and fits your use case.


A long time ago, nativescript[1] seemed to be a strong alternative to reactnative. Is that still the case?

[1] https://nativescript.org/


If you use oidc, you can't use Flutter with web or desktop as build targets. It requires a feature that isn't supported by Flutter on those platforms.


The one flutter website I have come across is an absolute piece of garbage. Completely destroys the ability to modify or even inspect the HTML source. See for yourself

https://sunrisetv.ch/de/vod/1/details/vod/crid:~~2F~~2Fog.li...


You can export the flutter build as HTML, but the point with flutter is not to be a ”website”, it’s supposed to be seen as a ”web-app”.

If you are going to create simple static homepage or interactive website, I don’t think Flutter is the right tool. Full fledged cross-platform applications is what Flutter is meant for.


I agree, who cares if a website supports accessibility, no one in the world is vision impaired and uses screen readers right? right?


That's not even my point.

Websites should still support accessability, I would even go as far to say it's a must. I just don't want people to mix up web-applications with websites. I've seen some people create a simple "websites" with Flutter which is totally pointless because it could just been created with html + css.

There is also a section in the Flutter docs that talks about accessability and how you can create accessable apps but I don't know how well it translates to Flutter web.

https://docs.flutter.dev/ui/accessibility-and-internationali...


And it has laggy scrolling. What’s the benefit?


Why would the ability to modify HTML matter at all? Most users don't even know what HTML is, much less how to open the dev console.


Regular users know how to install an extension that interacts with the DOM, though


Yeah, why does it even matter if you can control a page? Let’s just make it a fucking canvas, power users and those who care about web experience can go to hell.


[flagged]


First comment on that Reddit thread:

---

Hey folks! Kevin, product manager on Flutter and Dart here.

The layoffs were decided AT LEAST a couple of layers above our team and affected a LOT of teams. (I think I can say that). Lots of good folks got bad news and lots of great projects lost people. Flutter and Dart were not affected any more or less that others. It was a tough day...tough week.

It was crazy to be seeing demos and new things working and discussions about new customers the same day we lost colleagues and friends.

We're sad, but still cranking hard on I/O and beyond.

We know ya'll care SO MUCH about the project and the team and the awesome ecosystem we've built together.

You're nervous. I get it. We get it.

You're betting on Flutter and Dart.

So am I. So is Google.


Reddit post from Project Manager is pretty pointless. If Google decides to get rid of Flutter, they are not going to tell Kevin before hand, they are likely not even going to tell Kevin boss before hand. Stadia employees were swearing up and down that Stadia was full steam ahead despite layoffs until it wasn't. When it happened, it was clear from all Twitter posting that no one except really high up Google Executives knew Stadia shutdown was coming and they didn't tell anyone.


True, but you could say the same thing about anything. That does not help anyone.


It does help. Words mean less than action. If random people are killed from a division due to decisions "many layers above" it means that division is really not valued. Google will kill off flutter in the future. One should not be building long term apps on it. React native and react luckily have been taken over by the open source community and will live long. Shame though, I really liked flutter. Fuck Google.


Not always, if Google Cloud CEO came out and said "We are invested in Flutter", I'd give it more weight since he has real power at Google.

I'm just saying Kevin statement is meaningless. If you look at Google actions before, they do not slowly remove support from things and announce it. They silently layoff, go quiet then BAM, X is gone without warning and little time to deal.


The doom and gloom comes from much the same pontificating and rumormongering. Except somehow less official, and that's what you want us to go with?


Doom and gloom comes from everyone who has followed Google history. Google does not do what I call "Enterprise orderly shutdown of services" which is decrease releases/features, announce depreciation, give shutdown date and shutdown. They just do layoffs, radio silence and BAM, SHUTDOWN!


Building anything on top of Google tech that isn't Android or GMail is a huge risk, and the fact that the higher-ups will just randomly decide to fire large parts of teams confirms that caution is the right approach.


That's so true. They have built a reputation for killing stuff.


The Stadia people were saying the same thing up until the day they were shut down.


Was Stadia the #1 online game streaming service at the time? It's rhetorical.


> You're betting on Flutter and Dart.

> So am I. So is Google.

RIP Dart and Flutter.


That's definitely not true as of today.

There were some rumors that made people think of the worst, and as we speak about Google, a lot of people panicked that Google is dropping Flutter.

However, that was not the case.

They moved some roles to new locations, meaning (they claim) the team size change is net zero. https://x.com/MiSvTh/status/1785767966815985893

I get your frustration. Google just killed two of my favorite products this month (or more accurately, I found out about them this month), and then I heard about the Flutter downsizing rumors. I worked with Flutter for years now, and I decided that I can't let my professional fate in a company like that and started learning something new to switch to. Even if today it looks like they let Flutter live, it's better be prepared and pack up while I can leave on my own terms.



I stopped trusting Google's judgement of products when they killed both Reader and Wave.


Reader extension(s) for Chrome are fine replacements.


My grandfather told me about the Reader shutdown.


Those that do not learn from history are condemned to repeat it.


That's unfortunate. I actually liked Flutter.


Don't worry, it's a lie.


Until it isn’t. Too much faith on Google.


C'mon, just because they lied 295 times before doesn't mean they'll do it again. =)


I think they are just outsourced


Ok this is good to know. Man I thought for a moment flutter will be something Google doesn't kill but no. They are such shareholder automated processes driven that they are imploding from the inside. I'll switch to react native unfortunately. Flutter is definitely better tech but betting on any product from Google is a death knoll.


Downvoted you because the top comment in the link straight up goes against your comment. I hope you’re not spreading FUD on purpose.


Quit spreading lies about Flutter. It’s one of the most popular cross platform development environments, if not THE most popular, out there and that’s not going to change anytime soon.


So what if it’s popular? It’s a revenue driver and majority of development is still made by Googlers, as far as I know. If tomorrow Google drops all development, who’s going to pick it up? Or in your opinion GitHub stars would prevent them from dropping it?


maybe Ubuntu? the web development flow (so closely tied to firebase) might suffer a little bit, but I imagine a fork for non-web env's would be quick and welcome


People keep saying this about Go in every new Go version post and they keep getting disappointed. If you don't like Google languages, products or services then just quit using them and move on to something else.


> If you don't like Google languages, products or services then just quit using them and move on to something else.

Already did 5 years ago.


Native UI for anything that requires polish. I’ve been through too many iterations of frameworks that promise everything and don’t deliver. You’re up and running faster, then soon after you’re patching the core libraries after an OS update to try to get the FPS closer to native, or match a system animation more closely. The time saving only exist if you never polish your UI.

Core logic can be shared. I use gomobile - mostly love it but 3mb overhead for runtime (so not for web). Kotlin multi platform looked good, but I found it missing pretty basic libraries (which exist for Kotlin Android, so no one is building multi platform equivalents). Rust with Mozilla’s language binding layer looks good but I haven’t tried it.


I don’t think that premise of “native UI for anything that needs polish” is true these days.

Canonical the company behind Ubuntu have said for some time now that all future app UIs of theirs would be done in Flutter starting with the very first thing people see the installation process.

Google just rewrote Google Earth’s UI in Flutter.

BMW are doing all of their in-car entertainment systems in Flutter.


Are any of those better than the alternative, or just cheaper?

I suppose if the alternative is “this only exists on one platform” or “this doesn’t exist at all” then maybe, but I find it a bit sad how keen we are as a profession to accept compromise and mediocrity to save developer time and expense.

I get it, but I don’t like it.


2/3 of those examples had no requirements for cross platform and still chose it anyways. Additionally all 3 of those examples decided to take what they already had with native and decided to rewrite it because of the benefits.

I’m saying the “gap” between Flutter and native in this case is much much much smaller than you seem to think it is. Quite a bit has changed there in the past year or two.

That isn’t my opinion but that was the result of many major and very competent teams coming to that conclusion and putting their money where their mouth is in order to substantiate the claim.


Two of the examples mention are platform providers. If they standardize on flutter as their native UI, that’s fine and they are following my suggestion. If they port a BMW app from my dashboard to iOS / Android, I’m 99% sure you’ll see the issues I mentioned.

Google earth is fine, but doesn’t feel native. I think that’s fine for some apps (games mostly).


Could you maybe provide a single clear example of how Google earth doesn’t feel native?


Welcome screen was a popover on iPhone (only available on iPads, should be a sheet on iPhone), with rounded non standard button and non standard horizontal lines.

“Signed in as” toast wasn’t designed for iOS rounded bottom and “swipe up” bar leaving ugly stripe.

Sheet easing is off, and FPS stutter.

No swipe from left to go back support.

Non standard animations all over. Visible FPS issues (on newest HW)

I could go on and on. Feels like an android app running in an emulator.


I think several of your examples appear to be confusing Google’s material design system with the frameworks capabilities.


You asked how it doesn’t feel native. Using a design system from a different platform, and not complying with the interface guidelines of the current platform, is a big part of not feeling native.

And the frame drops and lack of system gestures, and lack of standard nav stack are major infractions on usability outside of design.


I would say React Native with all the Expo stuff. While Flutter is okayish, web is bad in terms of feel and accessibility since it renders to a canvas. Also, iOS still has issues with lag even after introducing Impeller rendering engine.

Look at Bluesky's client. The app performs decent on all supporting platforms and has single codebase.

https://github.com/bluesky-social/social-app


> what's the best method to build cross-platform mobile & web apps nowadays ?

Uno (https://platform.uno):

* open-source

* targets Android, iOS, Windows, Mac, and Linux (https://platform.uno/platforms/)

* C#

* automatically implements views and controls using each platform's native UI frameworks

* good IDE support: Visual Studio, VS Code, Rider (though you are not limited to those)

* Figma plugin for design collaboration


Also in the .NET world, Maui Blazor Hybrid is interesting. Uses HTML and the platform-native web renderer for the front end, and compiles to native code (not WASM)--i.e. clicking a button on your HTML invokes native code. Depending on your front end library, the app will look and feel more or less like a native app or web app.

An older article but puts it in context with Electron and how they differ https://www.codemag.com/Article/2111092/Blazor-Hybrid-Web-Ap...


I mean I guess that's fine if you're into .NET but how about those who prefer to avoid that


Why would you avoid .NET?


Not generally a huge fan of locking myself into Microsoft platforms


If you mean windows, it has been so many years since .NET has been able to run on many different platforms; and by now, most of the ecosystem supports majority of platforms too..

You get an amazing runtime with near native performance, access to value types, no type erasure, access to low-level operations when utmost performance is needed, very good cross platform and architecture SIMD support, three different great IDEs with two of them being cross-platform, AoT compilation that keeps getting better, WASM target with a good framework (Blazor), and so on.

Modern .NET is truly amazing and highly undervalued IMO.


It's all open source, Native AOT, batteries-included stdlib. A very productive and well rounded platform.


We use Tauri, but I think that it’s important to know that we solely use it for internal tools. I have no idea if it’s a good tool for consumer facing products. It works well enough for what we use it for, which is mostly for our solar park technicians where using cross platform Typescript on terrible internet became too much work for our small team.


We use Tauri at GitButler and love it.


Agreed. Tauri for desktop, capacitor for mobile. Bring your own front-end library either way.


In Go land, there's Wails

https://wails.io/


What are all the target platforms? The website doesn't have a list, or I'm unable to find one.

EDIT: never mind, I found it https://wails.io/docs/reference/cli#platforms

It doesn't seem to support Android, IOS or web.


Aren’t those platforms for the dev machine on which you would write the code and build you app?

Edit: looks like it’s for the server machine


Wouldn’t those be the server platforms?


I tried quite a lot of multiplatform frameworks in the context of mobile, and for me Flutter is in a completely different league than the rest of them. I really love it.


What's your definition of decent performance?

My company has built quite a few complex capacitor + Angular + Ionic apps and the performance on iOS is fine. Some even got featured by Apple, so that should be some indication that quality and performance was alright.


Businesses do seem to like AvaloniaUI and Uno.

https://avaloniaui.net/

https://platform.uno/


Thanks, which of the two would people recommend for a C# beginner? And is oidc well supported on all target platforms?


If you are to use Avalonia, which I highly recommend, it may be best to start with WPF. The Visual Studio Community Edition has really good IDE support for WPF and there is a huge amount of information on how to do things in WPF which thankfully hasn't changed in a very long time. Plenty of old books and blogs that go into all manner of detail. Once you have what you wanted working as you want it is straightforward to port the WPF to Avalonia for cross platform support.

Yes this would necessitate using Windows, an OS which I abhor, but as of now . In time I hope that will change with improvements in both JetBrains Ryder and Avalonia.


Both frameworks have various packages that add OIDC support to them so that shouldn't be an issue.

As for beginner - there's quite a bit of learning curve in terms of writing GUI applications themselves. Avalonia is kind of like WPF* but good(tm) and cross-platform. Uno platform is more like Xamarin and MAUI except in a better shape as of today. From technical perspective, Avalonia focuses on consistent rendering on all platforms with Skia while Uno tries to use native controls instead. I generally would not advise using Avalonia for mobile over Uno. In mobile case you might actually want to also give MAUI a try as, despite harsh criticism it has been receiving, it has improved significantly.

* either platform supports various declarative UI libraries (that are either part of their ecosystem or community-maintained), so you are not married to XAML thankfully.


That's a great answer, very helpful. I just picked up Avalonia for a test drive. Why do you think Uno is better than Avalonia for mobile?


Performance on mobile devices and UI libraries. Avalonia ecosystem is predominantly focused on desktop, which is not the case for Uno. But I liked the fact that setting up and AOT compiling Avalonia templates was a breeze so use it for side projects. For something more serious that has to target mobile, I would investigate how much MAUI has progressed in terms of quality and if problematic, would just go with Uno.


For the last 4 years the answer is Flutter.


Flutter is so far in front of anything else out there I think at the moment.


My team achieved better than native performance using RN when rewriting a very large iOS app. And that was in 2018, before Hermes and a lot of other optimizations.

It takes some careful usage of requestIdleCallback and avoiding doing work in the UI thread but it is not rocket science. You do have to avoid a lot of the going advice and bloated libraries / frameworks though.


| better than native performance

Maybe better than the native you had before the rewrite lol


“The app we had before” had 50M+ users, developed by a large iOS team, including a lot of experienced developers working on performance, and generating billions. I think it was a valid baseline.


> better than native performance using RN

You had an app written natively in Objective-C or Swift, switched to single-threaded javascript React Native, and then your app ran faster?


Though JS is single-threaded, it only builds the render tree and is more than fast enough if you’re careful. RN has a separate UI thread for actual rendering, I/O is offloaded and extensions can use extra threads.

The largest bottleneck historically was the bridge between obj-c and js (now superseded by JSI), and not the speed of the engine itself.


Unoptimized native application, probably written in a yolo let’s ship it faster way, is slower than rewrite that learned from mistakes of previous application. What makes you surprised?


I tried React Native, but ended up re-writing and going with SolidJS + Capacitor, and I love the setup. I've barely thought about performance since switching, people think the iOS/Android apps feel native, there's almost never any differences in behavior between the platforms, it's a fantastic setup for a solo dev.


I’m getting on pretty well with Ionic + TypeScript, using React and Redux. Performance hasn’t really been an issue, although I’m also not doing anything that performance heavy. I’d recommend it. I like that it ends up being comprehensible HTML + CSS, as well as simple React that I’m already comfortable with and can debug.


You already answered your own question imo. The web is the best thing we have so far and nothing comes closer to the full package. It literally is write once and write everywhere.

All the other alternatives are young frameworks that have not been battle tested and have weird quirks once you want anything relatively complicated.


For mobile, this looks promising: https://skip.tools

Transpiles SwiftUI over to Kotlin/JetPack Compose. Native all the way down. Haven't used it in production, but the demos work and are native after going through XCode and Android Studio.


> first-class development environment (Xcode)

this made me lol. As somebody who does mobile dev professionally, the worst thing about iOS dev is how terrible XCode is compared to Android Studio.

There's no way I would want this.


I would mention as an alternative QML, although I wouldn't claim it is the "best method". It's marketed as being mobile-capable, but I've heard problems about scrolling inertia and vsync delays.

I'm curious to know what others think about it.


Has been posted here before also, so adding it for people not aware of it already - https://areweguiyet.com


Flutter


Expo targets iOS, Android, web.


Have been using gioui to build streaming apps. It’s very easy and upgrading is always easy because it’s golang and the core devs take it seriously when they make a change.

When I need a web gui I use a gioui plugin system here: https://github.com/gioui-plugins/gio-plugins

WebViews work on web, desktop and mobile. It’s amazing. Deep linking also so you can send out a link to an email or Monike notification and the users app will open the gio gui in the right part of the gui.

It also has notifications and share extensions for all OS’s. It’s really a complete system. I can’t believe how much devs complain about things not being easy , when it’s all there. I definitely share the feelings that’s it’s so hard to support so many OS’s, but it’s the world we live in - plurality.

I like how I can do all of this with only golang , instead of switching between bits and bobs.

I always write my golang backend to work with gio and html.

So if I need SEO or video playback I can still do it in a web view and also keep googles seo happy for the gio web. I just use Hugo and feed it markdown. This is what Google SEO sees.


Go newbie here. Can anybody elaborate on this piece of the docs?

""" You might be thinking that it would be more usual to have an ops.Add(ColorOp{Color: red}) method instead of using op.ColorOp{Color: red}.Add(ops). It’s like this so that the Add method doesn’t have to take an interface-typed argument, which would often require an allocation to call. This is a key aspect of Gio’s “zero allocation” design. """

Why would there be an allocation? Of what? How are we saving it?


This has to do with how Go handles dynamic typing via interfaces and how structs fit into that.

When a function takes an interface type as an argument, and you pass a pure struct to it, it creates a wrapper around it (this is the allocation referred to in your quote) which is simply a pair of pointers, one being a type/vtable pointer and the other being a pointer to the struct's data.

Doing it this way allows code to do run-time type inference as well as allow interface extension implicitly (that is, implementing an interface is done by implementing its methods, and you don't have to explicitly type it like ByteReader extends Reader"). Since you only pay this cost if you use it, a lot of fast-path code will use structs exclusively if it can.


How do generics change this? Can a type bound on a generic work like a static interface implementation specification, and recover the cost of wrapping the struct?


You can declare generic structs and generic functions, and get monomorphized copies (not erased to "any") of each function for all concrete types used. You can't look them up by reflection. You can't declare generic methods, and still can't overload methods by type.


> get monomorphized copies (not erased to "any") of each function for all concrete types used

That's not exactly true. You get one concrete function for all generic pointer types for instance. Generic functions take a hidden paramater called a dictionnary, which is fairly similar to vtable, since it contains type information and pointers for all methods of the generic type that the function calls.

So methods on generic types are still performed through an indirection.

https://github.com/golang/proposal/blob/master/design/generi...


Thanks, had not seen that before. It's odd that they came close to reimplementing method dispatch for builtin types, but didn't surface it for developers.


That'd be how C#'s generics work for struct Ts. Go uses GC shape sharing: https://deepsource.com/blog/go-1-18-generics-implementation


Whenever you do:

  v := interfaceType(concreteTypeValue)
in Go, what you're actually doing on a lower level is:

  dataPtr := &concreteTypeValue
  typePtr := typeData[concreteType]()
  v := interfaceData{
          data: dataPtr,
          typ: typePtr,
  }
The first line here is the allocation, since (at least, the way I recall the rule) in Go pointers never point to values on the stack, so concreteTypeValue must be allocated on the heap. The rule about pointers not pointing to the stack is there to make it easier for goroutine stacks to grow dynamically.

See https://go.dev/doc/faq#stack_or_heap.


>in Go pointers never point to values on the stack

This is only the case for pointers that the compiler can't prove not to escape:

>In the current compilers, if a variable has its address taken, that variable is a candidate for allocation on the heap. However, a basic escape analysis recognizes some cases when such variables will not live past the return from the function and can reside on the stack.


That could be true, but I've done a few optimizations of allocations in Go code, and I don't recall pointers to stack values ever being optimized (unless the entire branch is removed, of course). If anyone could provide an example of the code that does pointer operations yet doesn't cause allocations, I'd appreciate it!



Ah, so extremely localized uses of pointers, got it, thanks.


More or less, yes, but it doesn't have to be extremely local. Here's a variant of the example that introduces a function call boundary:

https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(filename...


Oops, copy paste error there. Here is the example with the function call boundary:

https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(filename...


On the first approach ColorOp{Color: red} would have to be boxed and thus heap allocated. This is because ops.Add in general would receive a (fat) pointer to a value implementing a particular interface rather than a value of concrete type.

(The sibling comment written at the same time has a more detailed explanation of the 'fat' part.)


> You might be thinking that it would be more usual to have an ops.Add(ColorOp{Color: red}) method instead of using op.ColorOp{Color: red}.Add(ops)

Others answered your question, but on a different subject: I find that weird to read. To me

  op.ColorOp{Color: red}.Add(ops)
reads like “add ops to the result of op.ColorOp{Color: red}. I would name that function AddTo:

  op.ColorOp{Color: red}.AddTo(ops)
Still unconventional, but at least it messages that the function argument gets modified.



Thanks all (:


Heh. Go just doesn’t let you write zero-cost generic abstractions the way C# does.


Interesting that the WASM demo on the front page just render a black rectangle where the text is supposed to be on my fairly vanilla Windows 10 PC with Chrome (it rendered fine in Chrome on my Android phone).


It wasn't just me. Whew. It also ran incredibly slow.


same here with edge on windows 11


I built a small app in Go using Fyne.

Never again. Both Gio and Fyne lack tons of polish and features Flutter provides.

I built my core logic in Golang, and then decided to wrap it in an Android app. The GUI feels like it came out of 2003 with limited ways to fix it.


A different option is Wails [1], which allows you to write all logic in Go, and the UI in HTML (with any or no web framework). It's like Electron but lighter because it doesn't ship Chrome but uses the system's web viewer instead.

[1] https://github.com/wailsapp/wails


Wails is great. Also, see Tauri for a similar lightweight approach in the Rust ecosystem.


Sounds interesting. How did you wrap it in an Android app if you could elaborate?


Simple, I basically wrote a script to figure out probabilities for gambling ( I won't open source it since I don't want someone angry at me when they lose money). Then you basically have the UI layer call the script.

It's really hacked together, but it works.


Why do all these cross-platform GUIs look like they were designed 50 years ago?


I...would like to know what you were using in 1974 that looked like that.


Heh. The "50 years ago" part was an intentional stretch to add more weight to how disappointed I am. But seriously, the first demo they presented is an immediate rejection.


The first demo is a Webassembly thing that looks like any generic web thing. The next one is a cryptocurrency app that seems to have a "modern" design.

The other ones (gotraceui, sointu) seem like they might be what you're talking about. I can see how they might be scary to someone used to "modern" UIs because their information density is much higher.

Personally I'd prefer if more people treated computers like a tool, and not some kind of art installation.


I was referring to the Webassembly one. Looks like the design was largely inspired by the Material Design created by Google. Material Design is a massive failure and nobody should use it these days.

The cryptocurrency app looks good.

The gotraceui and sointu are actually decent. They are niche tools and look fine to me.


Material design always looked like a total mess to me.


Smalltalk wasn't that far ;)



The demo doesn't work for me. I see some buttons but mostly it's all black. Chromium on Win 11.


It's a good sign that unlike fyne, this library passed the very first test I threw at it: rendering some CJK text. Fyne can't do that unless you give it one custom font to render everything in — well, good luck finding one satisfactory font encompassing all commonly used scripts around the world, not to mention emojis. Which means fyne is immediately dead to me whenever I'm building anything with a remote chance of user-generated/web content and/or localization.


Noto sans is pretty good in this regard.


Noto Sans isn't limited to Latin — it supports Cyrillic and Greek as well — but immediately fails my CJK test. Or Arabic, or various other scripts used by half of the world.


I note form the demo that there's a "Flat" button that looks like normal text. This is a mis-feature and should be removed; controls should look different from things you can't interact with.


strongly agree


doesn't appear to support Unicode.


How does this compare with Fyne?


They both owner-draw every widget themselves (not using platform native widgets).

Gio is pure Go, Fyne is cgo.

Gio is immediate-mode, Fyne is retained-mode.

Flamewar starts here: I don't know why anyone would seriously choose an immediate mode GUI toolkit. When you receive an event, in immediate mode you have to recreate the whole world, then the toolkit has to then either rerender the world from scratch, or else diff the world against a clone on the heap, and rerender dirty regions. These kind of toolkits "advertise" hitting 60fps rerender speed as if that was impressive. In retained mode you merely don't respond to events you don't need to, the framebuffer doesn't need modification at all, and getting only 60fps updates would be embarassingly slow.

I understand the appeal of integrating e.g. Dear Imgui into your game's render loop if you're already re-rendering the whole viewport. But for desktop/mobile applications where the platform has a retained framebuffer, it seems like a deliberate deoptimisation.


I recently wrote a little document previewer in Fyne. It's a great experience and super easy to build simple GUIs, however Fyne struggled with a few pages of text (slow scrolling and resizing). I'll have to try Gio.


One positive side of immediate mode is that the code becomes a lot more straight forward. You only see that loop function, so it's very nice if you need a POC, or if it's going to be ran on embedded.


Here's some pseudocode for argument's sake: http://paste.debian.net/1317369

I don't think the immediate-mode code is really more straightforward. Retained mode looks just as simple and only has that one same function with the same 5 basic SLoC, only

- (A) the ui library has to do less work at runtime, resulting in a more responsive app (as per parent comment);

- (B) i was forced to reorder the component instantiation. In immediate mode, the counter's label depends on the button's state, whereas in retained mode, the button update callback depends on the counter instead; and

- (C) immediate mode only needed one sprintf instead of two since the initialization and update logic is unified. You can combine them in retained mode with a helper function or closure (and in real-world apps you would); in this trivial case this increases the SLoC but in real-world cases it reduces it.


> Gio is pure Go

7% C is not pure Go.


There is hardly any real C code in Gio, it's just bindings for the platforms' APIs (X11, Wayland, GL).

Somehow, they managed to avoid requiring CGO on Windows so it's 100% Go there.


Yet non of the GUI libraries/frameworks for GO support drag/drop file to get the real path


Blazor is cross-platform, in combo with MAUI.NET


I didn't downvote.

AFAIK it's not supporting Linux as a target platform. Correct me if I'm wrong.


.NET MAUI supported platforms:

* Android 5.0 (API 21) or higher is required.

* iOS 11 or higher is required

* macOS 10.15 or higher, using Mac Catalyst

* Windows 11 and Windows 10 version 1809 or higher

While Linux isn't supported, that is also not a typically significant market for GUI apps.

https://learn.microsoft.com/en-us/dotnet/maui/supported-plat...


However Linux has a non-negligible share among platforms that developers use (as a daily driver). To me, as a Go developer, this library is dead on arrival. It would take extraordinary circumstances to consider it for an app (even in business setting).


For Linux, there are Avalonia, Uno Platform and Gir.Core (rich GObject and GTK4 bindings).

The point of MAUI is to be a successor to Xamarin, for which the primary target are mobile devices, by far the largest market niche.


Can't even right click text lol


The amazing thing is that 30 years ago there were cross platform toolkits like Neuron Data and the toolkit under OpenOffice(called StarOffice originally), and yet today the options are still fragmented and imperfect.

We have far better compilers and even languages for cross-platform work, so it should be easier by now.


Building a cross-platform GUI toolkit takes an incredible amount of work & time, especially at the systems level.[0]

A robust cross-platform ecosystem for the underlying programming language is a necessary but insufficient piece of the puzzle.

Given the proliferation of HTML and WebView/web-tech wrappers (Electron, Tauri, React Native etc.) there are now enough "good enough" solutions that most organizations that would underwrite the in-house R&D of a new Neuron Data or Delphi or Flash simply don't feel the need.

When it does happen — say Google Flutter — it's almost statistically impossible to keep the hydra of VPs and biz folks aligned over the decades of ongoing investment it takes to mature & form community around this kind of technology — see the recent Flutter team layoffs at Google.

[0] speaking from my experience building a cross-platform GUI solution in Rust for several years now; see pax.dev


Exactly. Many programmers don’t want to worry about edge cases, and cross platform GUI frameworks are essentially coding an “oops all edge cases” project.


Maybe Google execs watched Theo’s JS frameworks review? https://m.youtube.com/watch?v=WJRf7dh5Zws


Isn't the whole "Flutter team layoffs" narrative somewhat debunked at this point? My understanding is that some positions were cut and some were moved, but no more than any other engineering area at Google.


Budget was cut because priorities were stacked and Flutter wasn't high enough. That's exactly the existential risk when beholden to "the hydra."


Yes. Layoffs were across all departments.


I really think that the Lazarus Component Library took the right approach: https://en.wikipedia.org/wiki/Lazarus_Component_Library

I wonder why the idea of widgetsets never really went anywhere: https://en.wikipedia.org/wiki/Widgetset

You could take a program that says you need a button in the window and it would make one for you on Qt, GTK or whatever else was supported, on any platform that you were compiling for.

We might as well have gone a step further: your programming language --> UI toolkit bindings for your language --> programming language independent GUI toolkit --> widgetsets for GTK, Qt, WPF, Win32 or whatever else --> executable for that specific platform

With that many layers of abstraction it's likely that we'd get the lowest common denominators for all functionality across platforms, but at least it would run better than web technology does, with the accessibility and platform look & feel you'd expect.

Of course, for whatever reason, seems like nobody wanted to undertake the borderline crazy effort of creating something like that, something foundational for others to build upon, so that's why we get super fragmented frameworks that are bound to specific languages nowadays and each of them have to reinvent a wheel a lot.

Either way, FreePascal/Lazarus were pretty amazing for RAD: https://en.wikipedia.org/wiki/Lazarus_(software) except that the community and ecosystem isn't exactly getting bigger.


Now there is a generation of software developers who grew up with web technology, and they aren’t old enough to recall the days of native apps - they don’t know any way other than HTML.


Lol. One of good cross platform example is Calibre [1], built with Python and Qt. And it’s the only one I carried with me from Windows XP/10 to macOS, through Linux. Another is Sublime Text.

[1]: https://calibre-ebook.com/


If I'm reading this correctly, Sublime Text wrote their own custom cross-platform layer [1]. Well that's one way to do it!

[1]: https://forum.sublimetext.com/t/is-qt-framwork-is-use-used-i...


I’m not sure whether those toolkits abstracted over native GUI interfaces or whether they attempted to recreate a native look and feel or whether they attempted to provide their own look and feel across platforms, but in any case the problem isn’t languages and compilers, it’s that the expectations for a GUI toolkit are dramatically greater now than then. Here are a few things that are (I think) expected from GUI toolkits today, but not 30 years ago:

* Hardware acceleration (in particular abstracting over metal, opengl, direct x, vulkan, etc)

* More complex layouts

* Animations

* Much hateful text rendering (e.g., right-to-left language support): https://faultlore.com/blah/text-hates-you/

* Accessibility

And if you want to emulate a native experience, getting keyboard shortcuts, focus behavior, and a billion other details correct is nearly impossible.

And by the way, today we have web engines that take care of most of these things for free and a huge pool of people who know how to build for them, so it’s often easier to leverage that capability than to essentially reinvent them.

And if people can contain their knee-jerk anti-electron reaction for a moment, I think that’s a pretty reasonable approach. I would really like to see something like an unlocked ChromeOS where the browser is the native interface, but unlike electron, we don’t ship a web browser with each app. Especially as webasm takes form, I could see this as a more compelling solution for cross-platform graphics with multi-language support than cross-language bindings or by trying to maintain a toolkit per language while trying to maintain some illusion of a consistent experience.


In some ways, expectations for UI toolkits have dropped too, though. Practically no UI toolkits created in the past 5-10 years come with a row recycling tableview/datagrid widget (table with column headers, sort by column, etc) for example, which used to be table stakes (which is why they’re present in Win32, MFC, AppKit, GTK, and Qt among others of the old guard). New toolkits that lacked a tableview would not have been taken seriously back then.

This has been a major blocker for my adoption of newer toolkits. I understand that it’s a result of mobile UI trends dominating the space, but that’s not helpful when I’m looking to build useful desktop apps, for which these widgets are crucial. Relying on third party libraries to fill these gaps (if they even exist) isn’t appealing either, adding yet another dependency to the pile and making a major part of my app subject to likely eventual abandonment by the library’s dev.


Tableview?

Try a Treeview. For Go UI kits you can count the treeviews on one hand.


Yep that’s another one that’s frequently missing. Basically any scrollable displays of data that aren’t a simple single column list or a grid are entirely absent in newer UI toolkits.


Why would it be easier now? What does a better compiler get you in terms of building a cross-platform UI toolkit?

We now have GPUs, mobile OSs with their own separate UI abstractions, the web, WebAssembly, etc. And people want write-once deploy anywhere.

You didn’t have any of that 30 years ago.


The compilers of 30 years ago had incompatible behaviors between OSes, for instance C or C++ had a great deal of variation. And 30 years ago you had pre-OSX MacOS as well.

Now you can just choose 1 compiler such as GCC and it works the same on all platforms; even cross-compiling to a different CPU architecture works well and is far easier to setup (before it was a black art).


In what way does GCC play any role in cross platform GUIs whatsoever? It’s a very small niche on Windows, macOS, iOS and Android. Visual C++, respectively LLVM/clang are much more dominant on those, and even then they are barely the right tools for GUI (maybe except Windows, but even then competing with .NET).


> You didn’t have any of that 30 years ago.

"Ubiquitous Applications: Embedded Systems to Mainframe"

"To support a variety of platforms, Smalltalk uses a virtual machine approach to portability that allows applications to be easily migrated between platforms with little or no change to the code."

https://dl.acm.org/doi/pdf/10.1145/226239.226264

~

"… Smalltalk developers can work and deploy on Linux, Windows, AIX®, Sun Solaris, HP-UX, and OS/2®. You can also create applications to be deployed on the mainframe with VisualAge Smalltalk Server for OS/390 and z/OS."

https://www.ibm.com/docs/en/announcements/archive/ENUS202-10...


Pre-Java there was a need to have UI applications that ran on Windows NT as well as Solaris and HP-UX. I worked with a commercial software package called Visix Galaxy. We developed in C++. It included libraries for each platform. It also had an interface builder very similar to those today (like the one in XCode). These were polished tools that made it easy to build beautiful GUIs.


>You didn’t have any of that 30 years ago.

Java ?


Java was introduced slightly before the cutoff -- 23 May 1995, so almost exactly 29 years ago. The earliest ancestor of its Swing desktop GUI library, called Internet Foundation Classes, was released 16 December 1996.


Inferno looked nice.


The toolkit was Tk, IIRC.


I don't understand how Java is relevant here? Perhaps I'm missing your point.

My point was that making GUIs today should not be any easier than 30 years ago because we have a lot more complexity across different OSs, phones, and the web.

Update: I think I understand your comment. I think you latched on the very last past of my comment about "write-once deploy anywhere". I meant that as in people want to create their GUIs with one language and one toolkit and have them deployable across different stacks without having a custom version for each and every final target platform.

Yes, technically Java did deliver on that as a programming language and runtime. And I guess swing also deliver on that as a cross-platform UI toolkit. However, we don't see a lot of Java UI applications around, with the exception of a few big ones, so it's fair to say that in the end it didn't work out. Of course, Java as general purpose language and runtime is alive and doing well today.


Yes, as a longtime software developer people have been trying to solve this problem different ways my entire career. The closest we got was Java swing. And it works well enough for things like eclipse but for some reason, nobody wants to use it and they want to use things like Electron instead


Regarding the "for some reason": Java Swing (and JavaFX, and Windows Forms for that matter) all suffer from lack of integration with modern web browsers. It is near impossible to find a way to combine these model-view-controller based user interfaces with the DOM in a reasonable way.

Horrible as it is, web browsers have managed to provide a common platform for user interface delivery. The browser wars have been fierce, and getting this foot between the door has cost several companies a lot of money. This technological monopoly is far from optimal, but I fear that we are stuck with it, as we are with QWERTY keyboards, USB thumb drives that must be unmounted manually, and the hopeless misery that is Bluetooth.


That’s because companies want you tethered to their servers. There are plenty good native apps that doesn’t require to have half GB to run them. Most SaaS coul be native if they want too, but hey, you have a 32GB laptop, right? And we want all your data anyway. Here is our Electron app!


> That’s because companies want you tethered to their servers.

It is slightly more nuanced, IMHO. For enterprise software it actually makes sense to use browser based software, because it saves the IT department a lot of hassle with local installations and version management.


Isn’t Eclipse written using SWT?


Yes. In fact, IBM created SWT to implement Eclipse.

Ghidra is an example of a large, cross-platform application I use regularly that does use Swing. While it's a terrific reverse engineering tool, its UI leaves at least a little to be desired. Examples, not necessarily Swing's fault:

• Non-native text controls. This is particularly painful on macOS, where Ghidra text controls don't provide access to useful system services (Web search, dictionary look-up, translation, spell check, text-to-speech, sharing, … [it's an extensible list]) and don't honor custom key bindings defined in ~/Library/KeyBindings/DefaultKeyBinding.dict.

• Non-native file open/save and print/page setup dialog boxes.

• Non-native font selection with very limited options: can't choose weights other than standard or bold, can't choose widths (condensed, expanded, etc.), can't choose OpenType stylistic alternatives, etc.

• Per-window menu bars even on platforms where global menu bars are an option (KDE) or standard (macOS). As a consequence, no menu bar search or ability to remap menu item keyboard shortcuts on macOS.

• Other fiddly control differences. For example, on macOS, Option+Right/Left Arrow on a tree view node typically expands/collapses all descendants. On Ghidra, Option+Left Arrow collapses all, but Option+Right Arrow expands only children, with an additional level expanded for each subsequent Option+Right Arrow keypress. While Ghidra's behavior is arguably more useful, it's still inconsistent with platform norms.

• High DPI scaling inconsistent across platforms (works fine by default on macOS, requires fiddling on Windows and Linux).

• No integration with system-provided dark modes.

• No out-of-box support for installation as a native GUI application (macOS app, Windows Start Menu shortcut, Linux .desktop file). To be fair, with the arguable exception of Mac apps, this is out of scope for a GUI toolkit, and I suspect most people in Ghidra's target audience have no problem hand rolling a solution.


Not OP, but thank you for the detailed feedback. I've been considering various options, including Swing, for a small desktop tool.

May I ask how are the apps made with Electron, Tauri, Wails or other WebView-based GUI toolkits performing on macOS in these regards?


We have HTML now, which is a great advancement. Don't forget about that.


HTML was a huge advancement, but it is likely a local maximum.

The HTML / CSS stack comes with significant ergonomic hurdles (layout / positioning / "creative fidelity") and performance hurdles (inescapable GC pauses, constant overhead of constraint-solving layout system, DOM overhead in general.)

Can we do better? IMO the future GUI lingua franca is deeply inspired by HTML and will stand on the shoulders of that giant, but will:

  - Build to LLVM native apps as well as websites
  - Include React-style templating as a foundational concern
  - Be fundamentally designed for visual building (think of the ergonomic differences between Webflow & Figma — if "an HTML" existed that "a Figma" could read & write natively, building front-ends would take a quantum leap)
WebAssembly makes all of this possible while still extending the Web and browser ecosystems.


I'm still super disappointed that javafx died.


JavaFX is alive.

Check out what do people work on using JavaFX: https://www.jfx-central.com/links


cljfx is worth a look too!

https://github.com/cljfx/cljfx


It's not dead. I just launched an app this year with it. Users love it.


Anything related to Java dying is a win in my book


Not about Gio UI but related.

I'm really enjoying the conversation around UI toolkits here. But I think we're all missing the elephant in the room and it's that we already had (have?) a superb toolkit and development model in the Visual Basic (later Windows Forms) era and nothing really manages to replicate that experience nowadays.

Microsoft destroyed it when they tried to push WPF and later shenanigans, only to realize it was a mistake years later.

I can't understand why we all, as a sector, agree about standards being a good thing, even if some are only de facto, and never agreed to maintain that really simple model.

I remember Mono tried to bring that to all platforms and everybody ignored/smashed them because "it's Microsoft".

Edit: typo


> I remember Mono tried to bring that to all platforms and everybody ignored/smashed them because "it's Microsoft".

> Microsoft destroyed it when they tried to[…] only to realize it was a mistake years later.

Answer is right there.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: