
Building Native Desktop Apps with Go and Wails: A Quick Dive
This blog is also available as a video lesson that you can watch for free here
Have you ever thought about building a native desktop application using Go? It might not be the first thing that comes to mind when you think of the Go language—most people associate it with server-side development or CLI tools. But I recently stumbled upon an interesting way to create native Mac applications using Go, and I want to share how it works.
Spoiler: it involves a Rust Crab invading my Goland IDE and a toolchain called Wails. Let’s dive in!
The Unexpected Fun of Go Desktop Apps
I’m coding in Go, and suddenly, the Rust Crab (apparently he’s called Ferris) takes over my IDE screen. My mission? Kill it with Go functions in a little game.
I’m admittedly terrible at the game, but that’s beside the point. What’s exciting here is that this game is a native Mac application written in Golang. And it’s not just limited to Mac—you can build Windows applications and Linux applications too.
The secret behind this is Wails, a cross-platform toolchain that lets you create native apps using Go and familiar web technologies. In this blog post, I’ll give you a speedrun of how it works so you can start building your own desktop apps.
Getting Started with Wails
To kick things off, you’ll need to install Wails. Head over to their site, where you’ll find clear instructions. It’s as simple as running:
go install github.com/wailsapp/wails/v2/cmd/wails@latest
Once installed, open your terminal, navigate to your development folder and initialize a new Wails project:
wails init -n native-app
I named mine “native-app” for simplicity. This command generates a project structure, which you can then open in your IDE— I use Goland, but any Go-compatible editor works. You’ll see a clean layout with two key pieces: the frontend folder and app.go at the root.
Understanding the Project Structure
The generated project is straightforward. Inside the frontend folder, you’ll find index.html
, where you can put all your frontend logic—the part users will see and interact with. Think of it as your app’s UI layer, built with HTML, CSS, and JavaScript.
Then there’s app.go
, the entry point to your Go backend. It’s not intimidating—just standard Go. Here’s a snippet of what you might see:
type App struct {
ctx context.Context
}
func NewApp() *App {
return &App{}
}
func (a *App) startup(ctx context.Context) {
a.ctx = ctx
}
func (a *App) Greet(name string) string {
return fmt.Sprintf("Hello %s, it's showtime!", name)
}
This file defines an App struct with a startup function and a Greet function. What’s wild is that this Greet function becomes callable from JavaScript in your frontend—more on that in a sec.
Bridging Go and JavaScript with Wails
Here’s where Wails gets magical. It creates a Go runtime and generates JavaScript bindings for your Go methods. When you run wails dev or wails build, these bindings are automatically set up, letting you call Go functions directly from your JavaScript. For example, Wails exposes the Greet function on the window object, so you can invoke it like this in index.js
:
window.greet("Matt").then(result => console.log(result));
To see it in action, I ran wails dev on my “native-app” project. It launched a sample app with a text input. I typed “Matt,” and it responded with “Hello Matt, it’s showtime!” — straight from the Greet function in app.go
. I tweaked it to say “It’s time for ByteSizeGo,” saved the file, and Wails hot-reloaded the app instantly.
Compiling Your Native App
Ready to turn your project into a standalone app? Just run:
wails build
Since I didn’t specify a target (you can with flags like -windows or -linux), it used my system’s Go OS target— Mac, in my case. After building, I navigated to the output directory and there it was: a native Mac application! You could even ship this to the Mac App Store for others to download.
What Can You Build with This?
The possibilities are vast. With a Go backend, you can integrate a database, make API calls, or follow any service pattern you’d use in a web app. Essentially, anything you can build on the web with Go and Go templates can become a native app with Wails. I’ve been tinkering with converting my ByteSize Go website into a native Mac app just to explore the experience.
Why This Matters
Building native Go applications might not be the first thing you associate with Go, especially with tools like Electron dominating this space. But I think it’s incredibly cool that we can do this within the Go ecosystem. Wails combines the power of Go’s backend simplicity with web tech’s frontend flexibility, all while delivering a native feel.
So, give Wails a try! Play around with it, see what you can create, and let me know what you think.