Johnny and Jon are joined by Andy Williams to talk about some of the unusual ways developers are using Go. In this particular episode they deep dive into building GUIs and discuss all of the challenges imposed by trying to build a UI that is both cross platform and functional. How do you create buttons that work on both mobile and a desktop app? Should you even be designing both apps at the same time? Tune in to find out!
DigitalOcean – DigitalOcean’s developer cloud makes it simple to launch in the cloud and scale up as you grow. They have an intuitive control panel, predictable pricing, team accounts, worldwide availability with a 99.99% uptime SLA, and 24/7/365 world-class support to back that up. Get your $100 credit at do.co/changelog.
Algorithms with Go – A free Go course where panelist Jon Calhoun teaches you how algorithms and data structures work, how to implement them in Go code, and where to practice at. Great for learning Go, learning about algorithms for the first time, or refreshing your algorithmic knowledge.
- Enlightenment Window Manager - Window manager mentioned on the show
- Shiny Go Bindings - A way to access Shiny with Go
- Qt Go Bindings - A way to interact with Qt in Go
- andlabs UI - GUI library in Go
- Fyne - GUI library in Go
- Wails - GUI library in Go using Vue.js
- Awesome Go - List of Go projects with a GUI section
- Hands on GUI Application Development in Go - Andrew’s book on GUI development
Click here to listen along while you enjoy the transcript. 🎧
Hello, everybody! Welcome to Go Time. Today we are joined with guest Andrew Williams. Wanna say hi, Andy?
Hi, everybody. Thanks very much for inviting me along. It's really cool to be part of the chat.
And then we have one of our hosts, Johnny Boursiquot…
Hello, everybody. Good to be back.
And myself, Jon Calhoun. Today we're gonna be talking about unusual uses for Go; just the weird ways developers are using Go. Maybe not weird, but just not quite the normal ones.
First, we just wanna establish what are some of the more common use cases of Go, and then we're gonna jump into what we'd consider anything that sort of falls outside of that, is what we'd say is slightly unusual. That isn't to say that all of these are unusual. Some of them are more common than others, so you'll see that going in all different directions… And we're not trying to encourage anybody to not use go for any specific reasons; this is more of just exploring some different ways you might use it, that you might not have traditionally heard about.
Who wants to take the common use cases? What do you think those are?
I can take a stab… Do you mind if I take a first stab, Andy?
Yeah, on you go.
Okay. So my own personal experience is that when I first heard of Go, it was all about back-end, systems-level kind of work, queueing technologies, databases, that kind of thing. High throughput, networked applications and services; what was being called at the time lower-level kind of back-end things, as opposed to your traditional web developer framework stacks we were familiar with. And really, that's been fairly consistent, up until about, I'd say, three(ish) years ago. Then I saw an explosion of all kinds of different uses of Go. But yeah, we're gonna get into that… But that's my personal experience of what the common uses of Go have been for me until a few years ago.
Yeah, I think that sounds about right for me as well. I've only really been in the community for not even two years actually, so after all of these new and exciting areas started opening up… But the common use cases still seem to be focused around web servers, back-end systems, like you say; that's where the examples are. And often, if you ask somebody "What's this language for?", they're pretty much gonna say "What it was designed for." I think, like you said, that's solidly where it started.
[00:04:00.14] Yeah, I'd say my experience has been pretty similar. I've definitely seen – even on the web side of it; you see it a lot more in APIs and things that are returning JSON than with the – like, you don't see the templating library being used quite as often to generate HTML. A lot of times when people think about web frameworks, they think about Rails, or something else… And that stuff has started to exist in Go, but it just wasn't nearly as common until more recently, as tools have started to emerge.
Okay, let me jump to the next question… Before we deep-dive into any specific areas, what is the strangest thing you've seen Go used for?
Am I gonna throw you both off with that one?
I mean, I'm biased working so much in the GUI space; I've seen some pretty crazy things done there, and there are some ideas around running user interfaces using native, that's then rendered through the web browser instead of using the web technologies. That feels pretty whacky to me. Interesting area, some cool applications, but not my first choice for how to build something.
So if somebody has actually made that sale, please let me know how you did it, because that's definitely an interesting one to pull off.
It's a super-power. [laughs]
Yeah. So it sounds like what we need to do is get somebody who's an expert in these areas and have them come on and change our mind, which would be pretty awesome.
Yeah, I don't know. Do you think we can find one of those?
We can look, we'll see. So we have Andrew here with us, and Andrew has a little bit more experience in what I'd consider more the native graphical user interface area. For those of you who are not familiar with Andrew, he created - or helped create; I'm not sure how that started - Fyne, which is something that allows you to sort of build native graphical user interfaces (GUIs). So I guess the first question I wanna ask is "Why don't we see more people doing graphical user interface type stuff in Go or in some of these languages?" What makes it challenging? Because truly, people want to build these applications that work natively on any OS.
Yeah, it's actually a bit of a mystery to me, honestly. When I was first thinking about how might you reimagine building graphical applications, which is kind of where Fyne came from, I looked at Go as a language and compared it with a few others and it just seemed like such a great fit, with the concurrency, memory management, and just the language semantics seemed to fit really well.
Partly, I think maybe there's not much going on in this space because that's not what people originally expected that the language would be useful for, so it's kind of a few years behind that opportunity, because it was particularly not worked on for a long time… But like Johnny said, it's been expanding over the last few years into lots of different areas, and people are starting to think outside of that area, so the graphical toolkits along with other things are coming along now… And you probably look at the Awesome Go list and see like 25 different toolkits, all trying to do something with graphical user interfaces in Go, and maybe half of those are on the embedded website, and the others would be to some flavor of native. That said, it is a really hard thing to do well, and if I tell somebody "Oh yeah, we're building a new graphical interface toolkit from scratch", they just look at you and go "Why? That's so much work… Surely, the ones that exist are good enough." So it is, I think, one of those challenges that people just go "What's the point…?"
I know one of the big issues I see – because people have been trying to make this cross-platform GUI-type thing for a while… You see React Native, and you see a bunch of others out there, and even on mobile, there were people who would be like "Okay, come learn our thing and you can develop for both iOS and Android at the same time", which was always a big challenge… So I guess the first question is "Do you think it's really possible to make good user interfaces that are cross-platform one time, or are we stuck just building it for each different operating system separately, because they all expect different stuff?"
Well, I absolutely think that it can be done. That is the purpose behind the project, to show that one of these considered impossible tasks actually just hadn't been tackled with the latest toolset, a language that supports these ideas. And if I didn't think it was possible, I'd be doing something else with my time, for sure… So I think it's a question of trying to figure out "How do you apply current technologies on top of all of the learning that we've had over the last 20-30 years of building graphical interfaces and the toolkits that support them, and bring all of that together with a bit of fresh thinking?"
[00:11:59.27] One of the things that really drove me initially was when the smartphone apps were really taking off and we saw what good usability could really look like… And then people looked at desktop and just went, "Oh, these two are incompatible." Well, you know, maybe that's because actually we needed to take the opportunity to reimagine it and see how this could work across all platforms with a fresh look, and can we apply the design learnings, the usability, and take those concepts onto both desktop, but also the cross-platform with one codebase concept. I think there's a lot of space there to really come at this with a fresh angle, and that's what we're trying to do.
There's always a trade-off. If you're trying to create something that's cross-platform, in some environments you might say "Well, for the Mac environment - we can take advantage of certain things here, but for a Windows environment we can't take advantage of the same things; we have to sort of give up some things here in order to get that…" So where are the trade-offs that you're making? Are you hiding those from the developer, from having to create sort of specific OS-based APIs and things for allowing a developer to do what they wanna do with the project?
Yeah, absolutely. I guess there's definitely trade-offs in anything that you're trying to do cross-platform, although as the Go team have showed us, you can actually find clever ways to work around most of these and still have an elegant API at the end of the day. It probably would be worth looking at what native means, because there's a lot of different toolkits that are trying to be native and they can take different approaches. The andlabs UI project, which is doing a really fantastic job of abstracting a standard API across system standard components so that you build an application with one codebase, and when you run it, it looks exactly like any other application on the system it's running on…
So the trade-off that they're gonna be taking on board is, I guess, the lowest common denominator to element, although they're managing to build more complex components off the standard items available… So Fyne's in a place where we thought "Actually, let's have a standard user interface across all of these systems." So the trade-off there is probably the immediate recognition that a user might expect when they're loading a new application. We're presenting them something that is a little bit different. We're going for consistency across the platforms, as opposed to specifically consistency with the current system, which is a potentially courageous, but design choice that we made… So there's a bit of trade-off there with user familiarity.
The one that we're looking at at the moment is around system dialogs. If you're running on, for example, the Apple desktop, there's a lot of functionality there (the iCloud document store etc.) that if you're saving a file, you would expect to have it presented to you… So we're needing to look at a system-by-system basis, how exactly that integration might work, so that people can get access to the files that they would expect on their system without a huge variance in the capability of the software running on different platforms. There's all sorts of ways that it has to vary across systems, but that's the one that's certainly on our mind at the moment.
When you said "The Go team showed us that we can actually use some clever things to get around the differences between the operating systems", just for anybody who's not familiar, I'm assuming you're referring to having build tags and having specific Go files that compile depending on the language you're building for?
Absolutely, that's a big part of it, but I guess I was more thinking that from the language and a standard library level you really don't need to worry about it at all, for the most part. If you're reaching for a build tag, you're probably wanting to do something specific for a certain platform when you're making that choice to break away from the guaranteed consistency across systems… And that is certainly a challenge when you start working in the graphical world, where those guarantees don't necessarily go away completely, but they certainly introduce a lot more challenges… And how you manage to have an API that is as easy to use as the standard Go library is, whilst dealing with these more system-specific concepts is a challenge, as well.
[00:16:17.06] Yeah, so what I meant initially was that you can have multiple Go files, and each one, depending on the language you're building for, is the one that's used… But the actual API that people are calling is the same functions, and they're generally expected to do the same thing, it's just how they do it might be a little bit different.
Oh yeah, absolutely.
But then the flip side to that is you kind of get lured into this almost wanting to have two things act in different ways, and you don't want developers to call a function and have to mentally think "If I call this function and I'm running on Mac, it's gonna do this thing. But if it's on Windows, it's gonna do something similar, but not quite the same… My code needs to adapt for both of those", which would be very challenging, especially – like you said, in the GUI world, everything from alerts and notifications and just permissions… There's just so many different things that are really challenging to pull off, because that's where the differences in the operating systems really start to stick out.
For sure, yeah. I think if anybody's ever trying to design an API that's gonna be consumed outside of your team at work, it's important to consider the path of least surprise for any developer that's gonna be using the API… And if you do want to put platform specifics in there, the outcome should really be entirely consistent, irrespective of the specifics that are happening behind the scenes… So there may be a significant difference to how things are functioning, but really the end result should be consistent. Notifications is a really interesting example there, but there's probably a hugely long list of those sorts of system items that are going to be challenged to do consistently across systems… But from the developer's point of view - yeah, they call a function, and a thing happens; the documentation, whether it's GoDoc or something more elaborate, is going to describe the functionality, not the platform-specific item, and I think that's important.
So you're working on Fyne, which does (I believe) mobile and desktop… Is that correct?
It was desktop initially, and just in December we added mobile, so that's iOS, Android, and also a Raspberry Pi fitted in there, because it's running the same chipsets for the graphics output as the mobile devices are, so… It's not really mobile, but it was a nice added bonus at the same time.
So when you're thinking about that, do you think about those – like, when you're exposing an API, do you guys feel that that API should be the same for mobile and desktop, or is this something where you've actually drawn a line and said "One's different enough from the other that we can't just make it universal"?
[00:20:10.12] No, absolutely… These APIs that we're building have to be consistent completely. We're following Go's design principles on that, and everything that we do is idiomatic, or aiming to be idiomatic to the language, and consistent APIs is really important there. So if somebody's rating an application with Fyne, then they know that it's going to work across all of these different devices in the same way.
That said, there are sometimes differences between devices that you want to enable that aren't generic. The one that springs to mind right now is a virtual keyboard. That's not typically available on a desktop platform, so there are some APIs that are device-specific, and you can use appropriate calls to say "You know what, if I'm running in this environment, then take this action." So that's available if people want to customize their systems to the device it's running on, but it's not really encouraged, because we want to make as much of this completely transparent as possible.
Yes, absolutely. The performance that we've experienced has been really phenomenal, actually. You're quite right, a lot of the technologies that try to tackle the cross-platform do suffer in some of their choices, and performances can be challenging to keep up there… But when the Go code is compiled down to the machine, apart from some implementation details that we might have, it's gonna be running at the same speed as the native code as if you'd been building with the toolkits that the platform was designed with… And partly because the graphics drivers that we have implemented are going straight down to the same hardware acceleration that the Swift or Java codes would be using as well.
So I guess I find that interesting, because if you're getting down to that level, I know one of the common concerns that I hear people talk about - and this isn't specific to GUIs, but I talk to people in the system administration space and stuff like that, and they always make the argument that like – say I'm a Mac sys admin; they say that eventually I need to get into Swift to touch the lower-level things that I need to touch. I guess, do you ever run into cases where that's the case, where you really need to touch OS-specific APIs? Because that's one of the issues…
Or I guess a better way of putting this is that it seems like to write for Mac, you need to know Swift; to write for Windows, you need to know one of those .NET languages that actually can interact with the things they want you to sort of restrict… And it seems like they don't care as much about supporting other languages with those really specifics… So has that been a challenge, or is that something – you're just not doing those things?
It really is a challenge, yeah. Absolutely. There's certain things that there's just no way to address using a language that's not what was intended… And it's something that occupies my mind when we're working to do new capabilities on systems. But our best efforts are to hide all of that complexity from anybody that would be building their application with our APIs… So the project exposes a pure Go API, which is great for everybody who's working on it, and it makes a lot of sense in all the standard tools… But if you were to go and look at our source code, then you would find Java, and Objective-C, and some C… It's all brought together under the hood, depending on the target build system. And there's a couple of tricks in there to make sure that you don't have to have all of those variants installed all of the time just for a build to work. This is largely gonna work out of the box if you have Go and a C compiler.
[00:24:15.12] So there's a lot of complexity under the hood… But it means that we're able to hook into the platform-specific APIs, the types of things that are only available on an Android device if you're accessing the Java APIs, or that might only be exposed through Objective-C on an Apple computer… But we want to make sure that that is never anything that you would need to think about if you were building on top of our system.
There's obviously going to be areas where we haven't completely added all the support that we need to, but we're working on it over time, and if people find an area that they're having to reach out to some other language for, then we'd encourage them to open a ticket and help us work that support into the main project.
So you say that you build with Java and seeing these things… I guess can you talk a little bit more about that? Are you using just C bindings and connecting to things that are gonna be on every system? What does that look like? Are you talking like OpenGL, or is it something else?
Yeah… So it is pretty much through cgo like you say and the main dependency issue is talking to OpenGL, which gives us access to the graphic subsystems. In fact, that is the only dependency for this on most systems. On desktop we don't need to do any clever things, for the most part… And some Apple APIs that might be required are actually accessible by C, or Objective-C that it compiles down to using the standard toolchain, so it's not really too much of a problem. When you're building for mobile, this becomes a lot more challenging, but the Go mobile team have done a fantastic job of actually solving a lot of the challenges there for us, and through extending that project we've managed to add that support.
I think the craziest thing that I saw in terms of making that work was that the Android target has some Java code in it that's pre-compiled into a text binary that's then bundled into the Go source code as a data asset, and then that's extracted as part of the build process to give you your bootstrap into the Go runtime. Now, I would rather hope that nobody using this would ever know that that existed under there… But if you wanted to delve into "How can I improve this for Android specifically?", you're gonna find some really weird stuff.
Yeah, I could imagine that being confusing, at the very least, when you're getting started… So the Go mobile project is what was helping you bootstrap into that… Was there anything that you've found - open source or otherwise - that helped you get started with the overall project, or getting into OpenGL and that sort of space?
Actually, the graphics is a complicated area, I guess… And it's very low-level, so the code reuse between projects is not exactly shining in that area. Really, I guess I was just basing on experience I had with previous projects as much as anything. I can't think of anything in particular that we really called on… Although I suppose initially the project did use the render pipeline from the EFL toolchain (that's the Enlightenment Project). That gave us some abstraction for the graphics driver. But in the end, we realized that to really build an idiomatic API top to bottom, we couldn't depend on an abstraction built in another language. It just didn't really speak the right language for us, and we were working a lot to work around the way it functioned, and we had duplicated code in there, and thought "Actually, this doesn't make sense", so we took it out and implemented it from scratch, right the way down to the hardware.
I mean, it's probably even more pronounced in your space, but I think in a lot of spaces you'll see that sort of difference, as to whether or not they started with the end user – like, they're designing the API for end users, versus starting with something they had to work with to touch the back-end, and then working their way towards the end user… Because an API that's designed for end users will look very clearly like they designed this for me to use it.
[00:28:22.06] And then there's other cases where you get an API where it's really confusing, or everything's just scattered all over… I'm trying to think of an example, but I can't off the top of my head. But I know I've definitely seen even just Web APIs, where you can tell the Web API is based off of the data models that they're storing things in, rather than what end users are actually gonna wanna use, and as a result, it just ends up looking not very user-friendly, because they didn't think "What is a user actually going to want here, versus what's easiest for us to give to them?"
Absolutely, yeah. And sometimes you want a design that's close to the hardware, or close to the data model, and there are projects out there that would use that design on purpose… But I think really for our project we're trying to make this as easy to use as possible, even for a first-time graphical app developer; so it needs to be built with them in mind, with as few lines of code as possible, very clear intent in every single line of code, so that nothing is excess, nothing is confusing.
But there are different approaches for a lot of graphic libraries that expose exactly how a graphics pipeline works, and you're feeding instructions into that pipeline. If you were building a game engine, that would be really important for you. But we're pretty sure that really enabling folks to quickly build applications that are user-friendly is what's most significantly lacking at the moment, and especially cross-platform. There's just not really anything there if you don't want to worry about the fun of web technologies inside your seemingly native applications.
Yeah, that makes sense. And I guess one way I view it is – you mentioned game engines, and I think there are some people who wanna definitely access the low-level stuff, but for the most part, at least when I'm watching people make games, it seems like a lot of them want to use engines of some sort; they wanna use Unreal Engine, or some engine of some sort that abstracts some of that away for them, so that they can kind of speak in a not quite system-level language; they can actually start talking about things in a way that makes more sense to them.
So I get what you mean, there's definitely some people who need that low-level, but I think there's a lot more people that tend to talk at that higher-level, a little bit easier to understand language.
Yeah, absolutely. I mean, every API is still built with a design in mind, and I think you're right, it's important to know who you're designing for when you set out, because changing that after the fact is gonna be really difficult, and probably make a rather confusing product at the end of the day.
Okay, so we talked a little bit about gaming stuff… Do you think a lot of this is why the gaming space is just not that common in Go as well? Is it basically the same type of challenges getting that stuff rendering, or do you think there's different challenges there?
Well, there's a lot of projects out there that can actually get something rendering to the screen; I'm not entirely sure that that's a challenge now. Maybe people are still cautious because it's new or not strictly part of the language… If you'll excuse the phrase, but I've heard it a fair amount. I think that it's more around putting together the libraries and the support, the type of stuff that you described. "I don't want to write a game engine, I just want to pull together a game", and that is another huge amount of work. I wouldn't be surprised if sooner or later we do see something emerge that is a pretty compelling approach. Maybe close to a cool typed API that would look really great for Go.
I just imagine that maybe it's gonna take a while before folks are happy to put the effort into building that sort of an engine binding to an existing engine in Go. It wouldn't really make any sense in my mind – the differences between the languages in this space are so vast that I think you could spend a lot of time and realize that actually it's just too hard to read.
[00:32:16.26] Yeah. I think one of the things that might also help there is that there's a lot of tools out there that are also very good at cross-platform game stuff. Steam has done a lot of work to make sure a lot of their games run on every OS, and as a result, you can kind of use their tools… So we're not really lacking. Whereas, like we talked about earlier, the rendering of graphical user interfaces across systems - at least every approach I've seen so far has had issues of some sort that people typically run into.
Basically, the really big UI that would start to lag if you had too much data or too much of anything in there was a big one that I saw a lot of companies complaining about. Because if you're doing an Airbnb and you have a bunch of listings, it would start to not render correctly when you're swiping up, or it just wouldn't feel natural. So Go is a good fit for that. But if you've got games that are kind of working, I get that maybe it's not as big of an issue to get something in that space when there's already somebody who's solved that problem in another language, another way.
Yeah, I guess that's a good point. I'm not entirely sure how solved it is. Just from my experience with the games Christmas sale, I saw this huge list of great bargains and thought "Oh, fantastic! I'll get a load of them." And then of course, only one in ten actually worked on the platform I was running on. So it may be technically solved, but there's clearly challenges there that mean it's not absolutely consistent.
This is a real problem actually with any API or platform that tries to do cross-platform; if there's really any roadblock to just rolling out across all of them, then you're gonna find people drop off really quite substantially. And if we're seeing new games getting released only for one platform out of three or four on a major system like steam, then I have to think – I don't know the APIs, but I have to feel that there's probably something in there that makes it a real challenge. And if you're gonna claim cross-platform, it really needs to truly be cross-platform, without having to jump through hoops or do special things to make your code work.
So given that that's the case, do you think that anybody who's making a GUI library in Go needs to actually keep track of what languages things are being released in? If somebody's using Fyne and you find that a lot of your users are only actually releasing to MacOS, they're not actually releasing to Windows, Linux, Mac, or maybe they're choosing two of them - do you keep track of things like that, or try to keep an eye on that to sort of see if that's a sign that you're not doing as well as you could be in one operating system?
That is probably something that we should do, actually, to have a better idea about where this is working for people and where it's not working so well. I imagined that we would get a lot of feedback from the community, which – we have an awesome community, very supportive, very active, but the challenge here is that actually we're finding more people than I expected are using this in their workplace, to add a user interface to something that was maybe a command line tool, or an ugly web form that they wanted to get rid of. So these types of projects are not really going out in the open, to be able to give us that visibility… So it's kind of lacking there a little bit.
We're trying to figure this out by publicizing the applications that are available. Anything that is open source, we're putting together a list of, and recommending that people check it out. But when it comes to "What are you distributing for?", we're really trying to emphasize the cross-platform approach and say "Look, just run the build for different target platforms." That's the only step. It doesn't make sense with the way that we're designing it to target only one platform. It may be that you only want to perform one upload or submit it to one store, but if the links are available on a website or on an open source repository, it's there for the taking; there's no additional complications to just rebuild it for the additional platforms… In theory.
[00:36:08.25] I'm curious about the design process, and the thinking that goes into deciding basically which direction the project should go in terms of this API footprint, what should it do, how should it do it, when should feature X, Y and Z come… I mean, you're at version 1.2.1 right now… Along those lines, are there design decisions that you made up to this point that you wish you could take back, or are there some things that you've found out later on that basically you think could have been caught during the design phase?
I'm asking because I don't know this world, and I don't know how different it is from the traditional software-engineering, practice and design, and all of the thinking and best practices that goes along with that.
Sure, yeah. There's absolutely things that I would change with a year-and-a-half of hindsight, but not as much as maybe I'd imagined we would. We're very careful about our design process, both from an interface design point of view, but also from an API design point of view. And the design of the API came before really a single line of implementation. The project started with an ambition to rethink how you could build graphical user interfaces across platform, and then came a broad strokes design outline as to how that API might function. Then we started implementing, initially with this other back-end component; so we didn't have to write the graphics drivers, but then eventually coached it all the way down.
So it is a very considerate approach… This is the way that I would consider any software engineering project if I was in a workplace. So when I started to think about this open source project, I wanted to make sure that we didn't compromise at all in that way. Obviously, there's other ways to build projects - get the code running, share it with some people and start building from there, but I felt that without a real design backing to this, it would struggle to keep its consistency over time. So when people ask for new features to be added, not only do we think "How would that look as an API?" and maybe even ask them how they'd like to interact with it, but we also have to consider "Well, is this something that makes sense for the majority of our users, and is it something that can make sense across the different target platforms that we want to support?" So that we're not just dropping in a small feature for one platform, that then doesn't do what you'd expect on other systems.
That process - I think it has served us very well. It does mean that sometimes features take a long time to develop… And you know, others are dropping quickly, but not always. So we have a roadmap that I've put together probably initially, two years ago, and it evolves all the time; first of all, we wanted to get desktop apps working, and then we thought "Okay, that's solid. Let's add some new widgets to it." Then it came time to look at mobile, so we targeted that for the 1.2 release last year.
Actually, as part of that release, we wanted to get data binding in there as well, because it's really simple to build a simple application, but then if you want to back a big data model into it, or connect more complex systems, display lots of items - even though that's pretty slick, there's still a lot of code to be written, and we thought "If we're really gonna do this properly, we need a good data binding system." And we started designing it.
There was a lot of discussion, there was a bit of experimentation to see what could work, and it came close to release time and the mobile stuff was polishing out quite nicely. We had to say "Look, actually, if we put this in right now, we don't think that we could commit to this being the API going forward forever." So we took that out of the release and invented a new 1.3.
[00:40:04.26] We were initially going to go directly to a big 2.0 drumroll, but we thought, "No. Actually, to do this properly, we need to take more time. We need to engage with more external developers, so we're not just building as a development team what we think is right, but actually what makes sense for everybody else."
I'm sure that the guys who are working on that could think it's been a lengthy process, because we've been building that API now for over three months… That's quite a long time in any engineer's lifetime, I suppose. We're confident that we're gonna get it right, and actually the demos that are coming together now - they're blowing me away, actually, what a bit of time and consideration has created. It's really cool. So we're gonna continue to think really hard about all of these design elements.
The items that we would change if we could - they're very small details in the grand scheme of things, and maybe when 2.0 comes along, we can change some deprecated stuff and do a walkthrough about how people might update their code, but it shouldn't be a big deal… Long answer.
No, it's great insight into the process. Yeah, it sounds like there's just as much agonizing over what the API should look like, what the developer experience should be that goes into any great API. So along those lines, you've written a book, Hands on GUI Application Development in Go, and I'm curious basically what the process, having worked with a lot of different GUI toolkits, from GTK to Qt, to any number of the ones you talk about in your book - I'm curious what makes Go uniquely suited for Fyne, for the current project you're working on? What makes Go a good fit, or even what are some areas where it struggles compared to what you're familiar with in other frameworks, in other languages? Where does Go shine in this project?
Yeah, wow… Thinking back to when we picked this as a language - I think part of it was how well-thought-out the language is, and the documentation that goes with it. If you're going to learn a new language and you just want to learn a new language, Go would be a fantastic option. It's so well put together. The documentation is there, the community support is there, and also the broader open source community and the way that all of this complex functionality is readily available for any developer, without having to know additional tooling. That was very compelling from a language design point of view.
But really, the process of writing the book, thinking about the challenges that have existed in graphical user interfaces through the ages, and looking at the challenges that the existing toolkits push on to their end users, I just couldn't help but notice that concurrency, memory management and building across multiple platforms - they were just like the three standout issues that really there was an opportunity to solve. And if you put a bullet list together like that and you say "Which language is this a good fit for?", you don't have a very long list, and Go was really clearly at the top of it.
So if we're looking at different ways to build GUIs in Go, I guess first off, can we talk about just what options are there? You created Fyne, you mentioned andlabs UI, which is the one that compiles down to something that looks native to the OS… What other ones are out there, and can you talk a little bit about how they're going about rendering the UI? Does that make sense?
Yeah, I can try. Honestly, the list is too long; I'm going to miss people out if I try to pick through them. I hope this list doesn't show any of my particular prejudices, but it's somewhat inevitable. See, I mentioned andlabs; there are absolutely great projects that will bind to existing technologies as well. There's a couple of different ones for GDK and for Qt, so if that's something that you would like to play with, there's some really great stuff there. You might need a bigger amount of free space on your hard drive to be able to set those up, but they are established projects, with really substantial APIs.
If we're looking at – things are a little bit different, I guess… A few years ago there was a couple of famous projects: Gx-ui and the Shiny project. Gx-ui, actually, I don't know a huge amount about, because that kind of went dormant a number of years ago… And although it was interesting maybe when I started researching the book, it seemed like it wasn't really going to pick up… So I looked at Shiny instead. This was a project that was put together by some people on the Go team, although I honestly can't remember their names right now… Apologies.
[00:48:19.13] This was, I guess, a really powerful technology demo of what could be done with Go. They implemented in very similar ways the OpenGL drivers in an abstraction on how you might paint using Go primitives… And in fact, that is used (I believe) for certain runtime configurations in the Go Mobile project to this day. It's a really solid project, it just doesn't really have much widget toolkit built on top of it. It sort of stopped where it was.
Then there is the [unintelligible 00:48:48.01] It's actually kind of contemporary with Fyne; it's been going for a couple of years or thereabout. But the approach that that project has taken is - although rendering a similar low-level API behind the scenes, they're using an immediate mode API, as opposed to the retain mode that Fyne has put together.
Basically, what that means is that each time the user interface wants to render a refresh, then the developer's code is going to describe how the system should look at that point in time. That's really powerful for games development embedded systems… And actually, it's a manner of putting together a graphics API that's gaining popularity in many areas. But the approach that I wanted to take with Fyne was to say "Actually, this is gonna be minimal code for the end developer. We're gonna make a lot of assumptions on their behalf", and in that regard, Fyne is a very opinionated toolkit. It looks a certain way, it behaves a certain way, and if you like it - brilliant; if no, it's maybe not gonna be for you… Whereas a toolkit that's got more flexibility could be very tempting to folks who wanna control every single aspect of how their application is going to work. I am sure that I have missed a couple off that list…
There's also bindings to other systems… The Nuclear project is quite interesting, and that contains Go bindings that are pretty easy to use. Then you've got Wails and Walk for Windows-specific APIs. There are other platforms out there for solving particular problems, but I've really only looked into the ones that we're aiming to make cross-platform graphical apps.
I hope I've not missed anybody out there that thinks they're really happening in the space right now…
That's my understanding. Actually, that's probably about the limit of my understanding of the project as well, because it falls in the category of hybrid or using web technologies. I haven't explored it anywhere near as much as the other ones that I spoke about there.
Yeah. I know that this is a space that it would be fun to go build projects… Try to build a small project in each one of these… Because even like you'd said, some of these are a little bit more involved, and I've never dove into those… You said – is it Q T? I don't know how you pronounce that one.
Well, I think it's pronounced Qt.
Qt? Okay. I was gonna say, I don't even know how to pronounce it, that's how limited my exposure is there… So I'm just like "Alright, I see people doing this, but I've just never gotten there."
[00:52:13.07] People tend to pick a camp, one that works for them for the reasons that they need at that time, and they just get passionate about it because it's solving the problems that they want. I think that people who are picking up graphical app development now are looking to solve different problems.
One of the challenges I realized when exploring this is that very few of them have any web services integration; they don't really help you with persisting state between user sessions, or even different devices… And I'm thinking if we can solve all of those things, you don't have to be on the web to take advantage of modern cloud-based technologies… So yeah, the right tool for building something is not necessarily the same tool as you want for communicating through the back-end systems.
So yeah, native apps I think have got an opportunity to perhaps gain a little bit more popularity if we really could make the cross-platform work well.
I also liked – you had mentioned that a lot of people are using Fyne to do things like take something that's command line and make it a little bit more user-accessible… Which I find useful, because I find myself doing random, one-off tasks for my wife… My wife's a photographer, and there have been times where she's imported all the photos twice in a folder, so she's got a bunch that have the “ 2” at the end… And as a programmer, you're like "It takes no time at all to write something that just goes and deletes those all." She doesn't wanna go through it manually and delete them all; that's just really tedious for thousands of photos… So I see that and I'm like "Alright, this would be cool, to build a UI for her to work with, that she's not gonna mess things up. She can choose the right folder and do it."
I think there's a lot of small problems that could be solved that way. So if somebody wants to get into this, building something with a graphical user interface, do you have suggestions for them? Where would you suggest they start, what types of projects should they keep an eye out for?
Before you answer, Andy… Jon, there is nothing wrong with a command line interface.
No, there's nothing wrong with it. We're using it. But if I'm trying to show my wife how to use it, there's a problem…
[laughs] It sounds like you need to teach your wife how to use the command line, my friend.
What happens if she says "Honey, please come do this for me again", so I just do it every time?
I think how you get started depends on what you want to do. There's a lot to explore, and somebody who's curious should definitely check out the Awesome List. Go to the GUI section in Awesome Go and see what's there, and just try them all out, really.
Personally, I would think if somebody wants to get up and running with something graphical in Go, then they should absolutely head to the Fyne.io homepage and have a little read. We've put together a tour that kind of follows the format that the Go Tour used, because it's just so easy to pick up really quickly… So we step people through what it means to put together a graphical application - how applications are linked to Windows, and how content is handled, and callbacks, that kind of thing.
So I'm gonna absolutely just say that that's the way you should go… But given the graphical nature of it, I would also say head to YouTube, see what you can find. There's such a good selection of demos out there… And if you put a couple of key search terms in there, you're gonna see a huge variety of different things… And the code tutorials often come with them. That's sort of my biased angle on it…
Also, the GopherCon talks - I know this has come up a couple of times at GoLab, and hopefully you can discover more upcoming conferences as well… Although as an unusual use for Go, it's not something that gets a lot of air time on the bigger conferences, because it's not what people go there for.
[00:56:04.18] Yeah, so a bit of Go code up and running in your favorite editor and start typing out some keywords, and it's gonna discover these for you and suggest how you pull something together. A little application is really only gonna take a couple more lines of code than a command line application. Not everybody's really thinking quite so big as the Fyne team, who are currently reinventing the desktop by building the app from scratch in Go as well. There's a very big space for innovative and exciting applications in between those two, and I think it doesn't have to be difficult anymore. This is something that really is so much simpler in a modern, higher-level language.
Don't sell yourself short, don't sell this project short… At Go conferences currently - and I can speak very confidently, at least for GopherCon - there are way more folks that are new to Go coming into the community than there are experienced developers. That's currently the state of affairs. We have way more newbies than any number of experienced developers… So a lot of folks are gonna be coming to the language and to the community through different avenues. The bigger the population, the more variation you're gonna have, and basically for people to take up the language.
So if somebody who's familiar with other GUI frameworks and they want to also learn Go, maybe Fyne is the gateway; that's the gateway by which they come into the Go community. So I think you're gonna see a lot more of this type of adoption through non-traditional avenues for new Go beginners.
That's really good to hear, actually. I think you're right, there's so many more people coming into it now that we do need to think how you're bringing this to brand new folk, not to established Go developers… And I think that we've been bearing that in mind, "How do you make this obvious for the first-time developer?", of which a lot do fine and then apologize for the questions, and we say "No, no, we want to know what you're struggling with, so we can make it better."
I think actually one of the unexpected challenges is that sometimes people come across the Fyne project and they want to learn Go and they're familiar with GUIs, and they're confused about why a thing that's really difficult for them isn't even present in the language or the toolkit… And there are a couple of times where folks say "No, no, you're missing this capability", and actually we have to say "Well, we've designed it slightly differently. That thing that you're familiar with and struggling with - just completely forget it."
So the preconceptions that people can have is actually harder work to help with than somebody coming in and going "Oh man, I completely don't know this. What do I do?", because in that regard you point them at some documentation or a video… But if somebody knows an old system and they want to try and break free of it, that's a lot of built-in learning, and you don't necessarily know where it came from or why they picked up a previous system… So perhaps some reeducation to do, but also perhaps we do need to make something that looks more familiar, or adapt to familiar use cases, if that seems like the right thing to do.
Mat likes to do this segment, where we ask our guests what is their unpopular opinion… And it can be a tech opinion - I think he kind of leans towards that - but it doesn't have to be.
So Andy, what is your unpopular opinion that you'd like to share?
Well, so I thought about this, and I don't know how unpopular it is… I think that people might agree with it, but often don't… So I thought I would say that to me, a quality engineered approach is more important than the speed of development. This may be completely obvious to some folk, or it may be pretty challenging… And if you're building a project to a deadline, there's obviously gonna be a time pressure, but I'd far more like to be involved in a project where they took their time, thought it through, and built something that was pretty solid… And maybe it was late or maybe it didn't have the functionality that was expected, but it's something to build on.
Looking project to project, it's perhaps a little bit difficult to think which is more important, but I look at the overall ecosystem of applications that we build our lives on now, and I think "Goodness, if actually somebody had taken a little bit longer and thought this through, maybe it would work a little bit better, or maybe it could be easier maintained."
So although the Fyne project is about helping people get up and running with graphical apps really quickly, actually what's more important to us is helping people do it well, build a codebase that is easy to understand three, four, ten years down the road, rather than having to replatform or reinvent things.
I don't know if it's too out there or not, but it's something that I'm surprised that not everybody agrees with, so… I thought I'd just say it.
I will see your unpopular opinion and raise you that level of quality of a project should match its urgency to get to market. [laughter]
Yeah, I like that. It's a challenging thing sometimes though… It's obviously important to get somewhere fast, but if you get there fast and then have to back-track, or need a whole bunch more time to fix the things that got you there, it's difficult to see that it was worth the effort… [laughs] Anyway…
A lot of this comes down to – we've talked about this a million times, but the size of your team, and everything else… Because if I'm working on a project completely by myself, what I can get away with is drastically different, especially if I'm not open-sourcing something… Because it's like, I'm the only person that sees this, and if I need to rip this all out, nobody's gonna give me any grief for it, and I already understand how it all works, so it's not like I have to figure out "What does this hodgepodge of code do?" But I definitely agree that if you're working with teams on projects, especially like with you guys, releasing a graphical user interface, and having other people use it - that is a very different beast to tackle… And when you're doing that, you can't have people using it and then all of a sudden say "All these APIs we had - we're ripping them all out. Good luck. If you wanna migrate to version two, you basically just throw all your code out." That's not a realistic migration strategy.
No, that's painful. There's been a couple of famous situations with that over the last few years… It's difficult to say that it could have been done better, but you just have to think "Well, maybe a little bit less speed and a lot more thought in designing this could have been beneficial."
[01:03:14.15] It just occurred to me that the thing about team size is really interesting - it may be easy to not think about it so carefully when it's just you, but I find it to be helpful to think or actually do any new project out in the open, and think "Would anybody who saw my code think I was doing a good job?", and imagine that the rest of the community is your code review peers. They're probably never gonna look at it, but I think it helps keep me honest, especially early days.
A project like this one - it had huge ambitions, and I had to start somewhere, and without the community as it started… It was helpful to think "Well, if I was looking at this and had no idea, would it make sense?" So yeah, I just pretended that the rest of the internet was reviewing my code.
That's a lot of pressure to put on yourself… [laughter]
I was gonna say, I think you could write perfect code, and the internet would still be brutal… But maybe I'm too pessimistic, I don't know…
It's true… [laughs] Somebody, somewhere is always gonna have an issue.
Alright, Andrew, thank you for joining us. Everybody, thanks for joining us for Go Time. Hopefully, we'll get to cover the subject again in the future, and we'll cover some other unusual use cases for Go. If you have any ideas or suggestions for weird ways that people are using Go, definitely reach out and get in touch with us. We'd love to hear about them.
Our transcripts are open source on GitHub. Improvements are welcome. 💚