Wails: Building Desktop Apps in Go

Durga Dasan | November 10, 2020

Go is an extraordinary language commonly used for APIs and/or libraries. When someone thinks about graphical interfaces, he/she will probably use a built-in web server. However, there is a different approach that is gaining popularity. Wails is a technology that allows you to wrap both Go code and a web frontend into a single binary, making things simpler.

The purpose of this article is to get you acquainted with Wails by walking you through a simple example to show the CPU status in a graphical way. With this example, you will be able to understand the basic concepts and will have a new tool as an additional option whenever you need to build something similar.

What is Wails?

Wails is a framework that lets you write desktop apps using Go. The difference between Wails and other tools is that it exposes Go code to the frontend as functions that return promises. Wails is capable of this through a binding mechanism, which will be explained further on.

The frontend code can be developed using any common Javascript framework, e.g. Angular, React, Vue.js, and Vuetify.

Wails provides the ability to wrap both Go code and a web frontend into a single binary. The Wails Command Line Interface makes this process easier because it handles project creation, compilation, and bundling.

How do the Go Code and Javascript Framework Interact?

The interaction between the Go Code and Javascript happens through shared IPC (Inter-process communication). It works across the Javascript runtime and the Go runtime. Both runtimes provide a simple interface that hides the burden of dealing with the IPC mechanism directly. The developer can interact with the Binding and Event components.

 

application

https://wails.app/about/concepts/

 

Wails Binding

The Wails application provides a single method that exposes your Go code to the frontend. You can bind a function or a struct with exposed methods. At startup, Wails will analyze bound functions and provide the equivalent function in Javascript. This will allow the Go code to be directly called from Javascript.

 

wails binding

 

The developer just needs to call the function in Javascript and will receive a promise back. If the call to the Go code is completed successfully, the result will be passed to the resolve function. If an error is returned, this will be passed to the reject function.

Wails Events

Wails has a unified event system similar to Javascript’s native event system. Each event sent either by Go or Javascript can be picked up on each side. Data may be passed along with any event. 

Wails Installation

Prerequisites

  • Go v1.12 or above

 

PATH environment variable should include the path to your ~/go/bin directory. You should also ensure Go modules are enabled with:


echo “export GO111MODULE=on” >> ~/.bashrc
npm
gcc + libraries (xcode-select --install)

 

Let’s Build an Application

We will build a desktop app using React and Go. It will be a very simple app to display the CPU usage of our machine in real-time. 

How to Create a Project

Command:

wails init

Enter the project name and choose which Javascript framework you want to use.

wails init

For our example, we are going to use React. This will generate the following project structure and files:

wails project structure

If we want to run the code we just generated:

  • To run the React front end: 

~/Documents/GoCode/wails/cpustats-react/frontend:$ npm start
  • To run the backend:
~/Documents/GoCode/wails/cpustats-react:$ wails serve

The application will run in the web browser at http://localhost:3000/. We will learn how to build it later. For testing and debugging purposes, we can code and check in the browser.

application preview

So now, how do we start reaping the benefits of using Wails for our project?

Binding Go Methods

To bind a Go method to be used in Javascript you should declare it in the following way:

binding go methods

Above, look at the method called basic. You will have to use the wails.CreateApp method with the desired configuration and then you will have to use the Bind() method to expose the method to the frontend.

Now, to call that method in Javascript you will have to use window.backend.methodName. Also, notice that this is a promise. See window.backend.basic() in the following example:

window backend methods

Binding Structs

Suppose you have a struct created in Go with the following method: GetCPUUsage. What this method does is use the gopsutil library to obtain the percentage of the machine’s CPU.

binding structs

To call this struct method in Javascript, you will have to use window.backend.StructName.methodName. You can see in the example how the struct method is called: window.backend.Stats.GetCPUUsage(). In this case, we are just going to print the result in the console.

struct implementation

Binding Events

To bind an event you will use WailsInit. This is a method you will declare in the Go code. Look at how we declare an event called cpu_usage. The event will call the GetCPUUsage method every second.

 

binding events

To detect the event in Javascript we will use Wails.Events.On, capturing the event we created in Go, in this case cpu_usage.

binding events sample

In order to visualize the CPU usage graphically and with a radial bar, we use React graphs. To declare them, use the react-apexcharts library.

binding events cpu usage

Building the project

The command used to build the project is wails build.

 

building the project

 

This will create our executable file: cpustats-react.

cpustats react

In addition, you can package the app using wails build -p.

wails build

This will generate an .app file, and in Mac, it will look like this:

.app file generated

The image for the app can be modified as well, by changing the appicon.png image.

When running, the desktop app will look like the following image. The CPU usage will be updated every second on the screen to reflect the corresponding percentage.

sample of cpu usage app

 

References

 

 

idea-Nov-14-2020-05-00-39-57-PM

KEY TAKEAWAYS

After reviewing this simple example, we can conclude:

  1. Wails allows us to use Go in unexpected ways, not just to build APIs, web backend, and CLI tools.

  2. We can build a desktop app with Go in any common Javascript framework using Wails.

  3. Wails has the ability to wrap Go Code and web frontend into a single binary. We can use the Wails CLI to handle project creation, compilation, and bundling.

 

Insight Content

Share this Post

Featured Insights