Go

From ArchWiki

Go is an open source programming language supported by Google. From the Go documentation:

Go is expressive, concise, clean, and efficient. Its concurrency mechanisms make it easy to write programs that get the most out of multicore and networked machines, while its novel type system enables flexible and modular program construction. Go compiles quickly to machine code yet has the convenience of garbage collection and the power of run-time reflection. It's a fast, statically typed, compiled language that feels like a dynamically typed, interpreted language.

Installation

Compiler

To compile programs written in Go, install one of the following compilers.

gc

The standard Go compiler is called gc and is included in the go command, which is provided by the go package. The go command also includes many other tools.

gccgo

A frontend for GCC called gccgo is provided by the gcc-go package. ggcgo may produce faster binaries than gc in some cases and can target additional operating systems and architectures. In practice, gc produces faster binaries than gccgo for almost all workloads.

TinyGo

TinyGo is an LLVM based compiler designed to produce very small binaries for embedded systems and WebAssembly. It is provided by the tinygo package.

Tools

The following packages provide developer tools for Go:

  • Go tools — Various tools and Go packages mostly for static analysis of Go programs.
https://cs.opensource.google/go/x/tools || go-tools
  • gopls — The official Go language server.
https://pkg.go.dev/golang.org/x/tools/gopls || gopls
  • Delve — A debugger for the Go programming language.
https://github.com/go-delve/delve || delve
  • go-bindata — A small utility which generates Go code from any file. Useful for embedding binary data in a Go program.
https://github.com/shuLhan/go-bindata || go-bindata, go-bindata-hashicorp
  • GoReleaser — A release automation tool for Go projects.
https://goreleaser.com/ || goreleaser
  • gox — A tool for Go cross compilation that will parallelize builds for multiple platforms.
https://github.com/mitchellh/gox || gox
  • ko — A container image builder for Go applications.
https://github.com/ko-build/ko || ko
  • revive — A fast, configurable, extensible, flexible, and beautiful linter for Go.
https://revive.run/ || revive
  • Staticcheck — A state of the art linter for the Go programming language.
https://staticcheck.io/ || staticcheck
  • Yaegi — A Go interpreter. Includes the yaegi command-line interpreter/REPLo.
https://github.com/traefik/yaegi || yaegi

Workspace

Go expects Go source files and executables to be in the workspace directory defined in the GOPATH environment variable, which defaults to ~/go.

Tip: You can see all Go variables by running go env

To create the workspace:

$ mkdir -p "$(go env GOPATH)/{src,bin}"

For convenience, add the workspace's bin subdirectory to PATH:

$ export PATH="$PATH:$(go env GOPATH)/bin"
Tip: GOPATH works like PATH and can contain multiple entries. This can be useful to split out packages downloaded with go get and your own source code; e.g. GOPATH=$HOME/go:$HOME/mygo

See How to Write Go Code with GOPATH and go help gopath for more information.

Tips and Tricks

Compiling source code

You can write a Hello World program as follows:

hello.go
package main

import "fmt"

func main() {
    fmt.Println("Hello, Arch!")
}

Then run it with the go tool:

$ go run hello.go
Hello, Arch!

Compilation with the standard compiler (same as go build -compiler=gc hello.go):

$ go build hello.go

Compilation with gccgo (same as go build -compiler=gccgo hello.go):

$ gccgo hello.go -o hello

Compilation with tinygo (same as go build -compiler=tinygo hello.go):

$ tinygo build -o hello ./hello.go

Cross compiling to other platforms

The standard compiler can natively cross-compile to a number of platforms. The procedure varies depending on whether the source code calls C code using cgo,

Without cgo

If cgo is not required for your build, then simply specify the target OS and architecture as env vars to go build:

$ GOOS=linux GOARCH=arm64 go build .

See the official documentation for the valid combinations of GOOS and GOARCH.

With cgo

If cgo is required for your build, you have to provide the path to your C/C++ cross-compilers, via the $CC/$CXX environment variables.

Say you want to cross-compile for GOOS=linux and GOARCH=arm64.

You need first to install the aarch64-linux-gnu-gcc cross-compiler.

Here is a sample program that requires cgo, so that we can test the cross-compilation process:

$ cat > hello.go <<EOF
package main

// #include <stdio.h>
// void hello() {  puts("Hello, Arch!"); }
import "C"

func main() { C.hello() }
EOF

Then, you can cross-compile it like this:

$ GOOS=linux GOARCH=arm64 CGO_ENABLED=1 CC=/usr/bin/aarch64-linux-gnu-gcc go build hello.go

You can check that the architecture of the generated binary is actually aarch64:

$ file hello
hello: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=b1d92ae8840a019f36cc2aee4606b6ae4a581bf1, for GNU/Linux 3.7.0, not stripped

If you copy hello to a suitable host, you can test-run it:

[alarm@rpi3 ~]$ uname -a
Linux alarm 5.3.8-1-ARCH #1 SMP Tue Oct 29 19:31:23 MDT 2019 aarch64 GNU/Linux
[alarm@arpi3 ~]$ ./hello
Hello, Arch!

Troubleshooting

Jetbrains Go Plugin

If you are using a Jetbrains IDE and the Go plugin cannot find your Go SDK path, you might be using an incompatible package. Remove the gcc-go package and replace it with go}. If your GOPATH is set, the IDE should now be able to find your Go SDK at /usr/lib/go.

See also