Contents

Go(lang) now!

🌱 notes 🌱

I’ve been working in Python and learning Rust, ignoring Go for a few months. Getting set up in a new language (Rust) and circling back to one I’d used before (Python), I bumped into perhaps-avoidable issues getting dev envs set up for each. Restarting a new project with Go, I thought I’d take a few notes to serve as a reference for future-me.

Getting started with Go

Before jumping into Go, specifically - a note on package management in the context of any general-purpose programming language. Packages are essential to doing even basic things, like managing I/O or operating in the context of any sort of network. Also, the many useful packages available for different languages enable building non-trivial projects relatively quickly. Thus, it’s generally useful to have a package management strategy before diving in to a project.

With Python, there are a number of options, and one must consider which { version and package } manager(s) to use based on one’s needs and preferences. With Rust, there’s Cargo - a veritable default, though technically separate from Rust and not strictly required. When just beginning, the pros/cons won’t necessarily be clear for a particular use case, yet a decision as to whether or not to use Cargo is inevitably made. In contrast, standardized package management via modules is built-in for Go and has been required since v1.13: it’s necessary to run go mod init before any Go code will compile. In effect, the process of getting started with Go has been streamlined simply by removing any optionality on that front.

The very basics

  1. Install Go. Normally, the default GOPATH will be /usr/local/go/bin unless you’re installing via Homebrew on a MacBook Pro with Apple silicon. In that case, GOPATH should be opt/homebrew/opt/go/bin (or opt/homebrew/opt/go@<go-version-number>/bin), so update the environment PATH variable in the shell config file. Be sure to add the new path as a prefix so it’ll be the default.
# in ~/.bash_profile
export PATH="/opt/homebrew/opt/go/bin:$PATH"
  1. Create a directory for a project:
mkdir go-project
  1. Go code is divided into ‘modules’. A project can be a single module or multiple modules. Starting simply, make the project a single module. Multiple modules can be pulled into a single project later, or they can be imported into a new project that coordinates the independent modules. From within the project directory, initialize go’s module-management of the current module with go mod init <path>; it’ll also manage modules imported by the current module. If the module will be published, <path> is the path from which Go can download the module. If you don’t need to think about this initially, give it a placeholder path.
cd go-project
go mod init github.com/github-account/github-project
  1. Create a file in go-project
touch code-file
  1. Open the file in your editor and write some go code. NB: To make the code executable, make package main the first line of the file and ensure that package main includes func main() {...code to execute...} within it.
package main

func main() {
  ...
}
  1. Run the code from the go-project directory: the compiler will build an executable and run it. Alternately, build the executable to run later.
go run .
go build .
./go-project

Modules

Go modules are independent building blocks of code, assembled by importing them into new/different modules. You can (and will need to) start using modules from the get-Go(!), but there can be more to using modules than initially meets the eye. Beyond the standard Go docs, I found slides and code from Ryoto Sawada’s 2022 talk Go Module with Microservices and Monorepo: Clear Dependencies with Ease of Development insightful.

The basic of example of importing a Go module:

package main

import "fmt"

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

Your IDE may prompt you to actually import “fmt” but, even if it doesn’t, you’ll need to:

go get fmt

And, then, don’t forget:

go mod tidy