Workspaces, cross-compilation, building and execution in macOS/OSX

In this article, we are going to explain how to build, compile, cross-compile, execute Go binary files, and create workspaces. These topics are very important if you consider developing and deploying large scale Go applications in a production environment.

First off, we must explain what is a workspace and why do you need it.


The workspace itself is a directory consist of the following hierarchy:


The bin directory stands for binary which includes the binary files of the project that has been created.


The pkg directory stands for packages that include all external packages that belong to the specific project.


The src defines the source directory which includes your source codes and dependency.

When installing Go on your mac, your default environment is located in /usr/local/go where all the necessary default files/packages are being stored. Now the question is: why create a workspace? Creating a workspace is important if you want to create your own custom project that includes only the necessary packages that belong to that specific project. In all our previous example we were using the default environment (well-known as GOROOT) to run our Go codes. A workspace provides you with the ability the import packages and codes into your own workspace. Ones your workspace is created, all your packages that you imported for your project will be stored in the pkg directory of your workspace.

Before you can start using your workspace, you must set the GOPATH to point to your project directory in the environment variables.

When you specify the GOPATH environment variable, Go expects an executable to exist in the specified directory. Furthermore, GOPATH tells Go where your workspace is to import packages, install binaries and store intermediate archives.

In macOS, the Go environment variables in your .bash_profile. The following instructions demonstrate how to set your base directory for the workspace and GOPATH in the environment variables.

Start off by creating the project directory. In this example, we are going to create this folder on our desktop.

After creating the project directory, you must create the src folder on which our source code will be stored.

Next, the Go file that contains the main package file since it requires at least one .go file in the specified directory. For this example, we will be using Atom as our code editor, but it all depends on your personal preference. For more information about code editors that can be used read this article.

  • Create a new blank file
  • Type the following Go codes

Package main

Func main(){


  • Save the file into your src folder.

Now comes the interesting part which is specifying your GOPATH in order to create the workspace. Before we can continue with this step, you must get the absolute path of the directory. In order to get this path just right click on the project directory and select the Get Info and you can retrieve the absolute path.

This path will be your GOPATH. Now to set the GOPATH, launch terminal and enter the ls -la command to retrieve the list of all directories (including hidden file/directories).

Press return and the list of files/directories appear and see if the .bash_profile appears in the results. In macOS/OSX, the GOPATH must be stored in the .bash_profile file.

In case the .bash_profile file does not appear in the list, you need to create it. In order to create this file manually, execute the following command:

touch .bash_profile

After creating the .bash_profile file or in case it already exists, open it in TextEdit by executing the following command:

open -a TextEdit .bash_profile

Ones the .bash_profile is open in TextEdit, you need to add the absolute path of your project directory as your GOPATH variable. Also you must set the GOBIN path, which is your GOPATH/bin. In this case, add the following lines:

export GOPATH=”$HOME/Desktop/go_project”

export GOBIN=”$GOPATH/bin”

Save your .bash_profile changes and close terminal completely in order for the changes to take effect.

To verify if the changes took effect, execute the following command:

go env

From the Go environment result check if the GOBIN and GOPATH are set.

If everything is set accordingly, only the last step remains which is creating your workspace. To complete this last step, just open the terminal, navigate to the project directory src folder were the .go file is located:

cd /Users/[user]/Desktop/go_project/src

and execute the following command:

go install

When you run this command on a project, executables will be compiled and written to bin.

Congratulations your workspace is created and now you can start importing packages to your project by using the go get command. For example, execute the following command:

go get -u

and your pkg folder appear with your package in your environment.

Go will walk through the codebase and get any referenced external packages. In this case, it sees the external reference, gets the package, and makes it available in the current workspace.

Import packages

Most packages are imported from other repositories through the version-control system such as Git, Mercurial, SVN and Bazaar. When you import a package Go retrieves codebase from Git and checks out the latest commit from the default branch.

Go build

To build Go application, you must use the go build command and an executable file will be generated. When creating an executable, it means that it does not require any external libraries in order to run.

Before building an executable Go goes through a set of strict rules to avoid silly errors and bugs in your code. This command also helps you make your code easier to read among the Go community. One thing you always need to remember is that the Go compiler is here to help you and not making your life miserable. The purpose of the compiler is to compile and increase the quality of your Go code.

One of the Go rules is you cannot just include any package that you might think you will need and not use it afterward.

package main
import (

func main() {
fmt.Println(“Hello world!”)

This will generate the following error message when trying building this Go file:

# command-line-arguments
./main.go:5:1: imported and not used: “os”

Although you can break this rule by using an underscore which bypasses this restriction.

package main
import (

func main() {
fmt.Println(“Hello world!”)

The use of semicolons is strictly checked by the compiler because Go requires the use of semicolons as statement terminators in many contexts. The compiler automatically inserts the required semicolons when it thinks it is necessary. Look at the following example:

package main
import (

func main()
fmt.Println(“Hello world!”)

Although it looks just OK, if you try to execute it, you will be fairly disappointed because you will get the next syntax error message, and the code will not compile and therefore not run:

# command-line-arguments
./main.go:7:6: missing function body
./main.go:8:1: syntax error: unexpected semicolon or newline before {

This is because putting the opening braces { in its own line will make the Go compiler insert a semicolon at the end of main(). This will produce the error message.

Go format (fmt)

The go fmt command set your code to the correct format. Which means if you code looks messy, you can just launch this command to format your code accordingly.


Cross-compilation is important if you want to generate executable to run on different machine with a different architecture. Luckily, Go has built-in support for cross-compilation which means you only need a single machine for your development.

To cross-compile a Go file, you need to set the GOOS (target Operating System) and GOARCH (target Architecture). In order to retrieve this information, execute the following command:

  • go version
  • go version go1.13.4 darwin/amd64

In this example, the GOOS is darwin and amd64 the GOARCH. The cross-compilation can be done through the following command:

  • env GOOS=[target OS] GOARCH=[target architecture] go build [target go file]

In this example, the command will be as following:

  • env GOOS=darwin GOARCH=arm64 go build main.go

The result consists of the following example:

This command generates a binary file that works on macOS machines that use the ARM architecture. See the list of the available Go values for the GOOS and GOARCH environment.

Execute Go codes

The go run command has been used in most of our examples in previous articles. When executing the go run command, the Go compiler creates a temporary executable file. During and after the execution of the Go application with the go run command, you will not see this temporary executable. Since the application is automatically executed, this temporary executable will be created and deleted after the program is finished executing. This means that Go does not leave any files on your hard drive.

To create an executable file, you need to use the go build command. This command creates this standalone executable which can be executed directly without needing to use go run command. The go build command consists of the following order:

  • Go build [go filename]

In an example where you have the filename main.go, the execution will be as following:

  • go build main.go

Ones the execution is completed, the main executable will be created in your current directory. To execute this executable, first navigate to your directory in your workspace and enter the following command:

  • ./main

Follow us:

Leave a Reply

Your email address will not be published. Required fields are marked *