Go (Programming Language) Knowledge
Kip Landergren
(Updated: )
My Go knowledge base that evolves as I learn more.
Contents
Overview
The Go programming language is a statically typed, compiled, strongly typed language focused on simplicity, reliability, and efficiency. In particular, Go attempts to make concurrent programming easier and more robust by offerring facilities like goroutines and channels built into the language.
Core Idea
The Go programming language and its tooling should provide a solid foundation upon which to build concurrent programs.
Key Concepts
Concurrency
- goroutines
- channels
Programmer Effectiveness
- simple language
- infer types where possible
- fast compiler
- “one true way” of formatting
- functions are first class citizens
The Language
Types, Pointers, and Values
&, the address-of operator
Note: the Go Language Specification section on address operators covers this in depth.
Consider:
x := []int{0, 1}
fmt.Printf("%T\n", x) // prints `[]int`
fmt.Printf("%T\n", &x) // prints `*[]int`
fmt.Printf("%T\n", *&x) // prints `[]int`
&x
is read as “taking the address” of x
and, given that the type of x
is a slice of type []int
, it returns a pointer of the type *[]int
.
The address-of operator only works on things that are addressable, like variables, so it does not work in certain situations:
c := &make([]int, 1, 2) // invalid
d := &fmt.Sprint("whoops") // invalid
but the composite literal syntax:
type Point struct{ x, y int }
d := &Point{1, 2} // valid!
is an exception, and the explanation is covered in the Go Language Specification section on composite literals (tl;dr it creates a variable behind the scenes).
*, the indirection operator
Note: the Go Language Specification section on address operators covers this in depth.
Consider the following code:
var y *[]int
y = &[]int{2, 3}
fmt.Printf("%T\n", y) // prints `*[]int`
fmt.Printf("%T\n", *y) // prints `[]int`
Note that *
has two separate uses:
- as part of the type definition
var y *[]int
; this declaresy
as a PointerType, elsewhere called a reference type, and indicates thaty
is a pointer to a[]int
. Note: the*
is part of the type definition ofy
. - as an indirection operator in
*y
, where it gives the value of a pointer
When *
is used as an indirection operator, like in *y
, it can be thought of as saying “give me the value at the address y”. It is equivalent to state that *
dereferences the pointer y
.
Modules
Modules are how Go distributes code. Modules are collections of related Go packages that are released together.
A source file contains useful code. That useful code is grouped with related code into a package. One or more related packages are grouped into a module. A module can then be imported and used / applied in the service of another module. A go.mod file informs the Go tooling on how to build the module, including how to find the location of its dependencies.
By metaphor:
- a module is a book
- a package is a chapter
- an import by an external library is a citation referencing the book and chapter
go.mod specifies dependencies:
- Go version
- the set of other modules it requires
Note: if you publish a module, the module path must be downloadable by Go tools.