Go Notes
Table of Contents
Setup
Getting the latest release
- Digital Ocean: How to install Go on Debian 10
- The latest release of Go can be downloaded here
- Copy the
sha256
from the website to a local text file,echo "SHA_256_FROM_WEBSITE" > go_release_sha256.txt
- Calculate the
shaa256
of the download and ensure it matches the value in the text file made abovesha256sum go<VERSION>.linux-amd64.tar.gz
- Extract the tarball with,
tar -xvf go<VERSION>.linux-amd64.tar.gz
- Change ownership of the
go
directory to the root user,sudo chown -R root:root ./go
- Move the
go
folder to/usr/local
,sudo mv go /usr/local
- Update your path to include
/usr/local/go/bin
- Typically you will set
GOROOT=/usr/local/go
then update the path to have$GOROOT/bin
- Typically you will set
GOPATH
- The default value for the
$GOPATH
environment variable is$HOME/go
- Tools that are installed will be in
$GOPATH/bin
folder - It might be advantageous to add
$GOPATH/bin
to your$PATH
environment variable
Hello World
- The below code sample is a simple hello world program written in Go
- It should go into its own project folder named
hello-go
and be namedmain.go
package main import "fmt" func main() { fmt.Printf("Hello, Go!\n") }
- To test out the Go install run
go install hello-go
- This should put a binary named
hello-go
in your path that should output "Hello, Go!" when run
Installing Beta Versions of Go
- If you have go installed you can install a beta version using the
go
tool - For example:
go install golang.org/dl/go1.18beta2@latest
- Before you can run the beta version you need to run
go1.18beta2 download
- This will download the SDK into the
$HOME/sdk
folder
- This will download the SDK into the
- This will now make the beta available on your system as
go1.18beta2
. Use this as you would thego
tool
Language Server
- gopls is the official Go language server
- You can install it with,
go install golang.org/x/tools/gopls@latest
- As far as I can tell the language server does not work in org babel source blocks
Emacs Org Babel Support
- Emacs Package: ob-go
- Manually edit
org-babel-load-languages
to include Go by adding it to the hash table(go . t)
- This is an example using the
args
header argument,:args '("-count=5" "-msg=Hola")
Appending to a list
package main import "fmt" func main() { x := []int{} x = append(x, 10) fmt.Println(x) }
Generics
Things you can do with generics that you cannot do with interfaces
- The
interface
type only lets you define methods - This means that if you have a set of structs that all have a similar property you would need to define a method to access it generically
- Using type constraints with structs allows you to define a generic type this is the union of all the other types
Simple Example
Non Generic Sum Functions
- These sum functions only accept variables of a fixed type
- These are here to contrast with the generic versions that can accept mulitple types
- Note that the implementation of these functions is the exact same with the only difference being the type
func SumInts(m map[string]int64) int64 { var s int64 for _, v := range m { s += v } return s } func SumFloats(m map[string]float64) float64 { var s float64 for _, v := range m { s += v } return s }
Generic Sum Function
- In the square brackets below
K
andV
are the names of the types used comparable
is a built in generic type that covers all types that support==
and!=
- Go requires map keys to be comparable
- The
V
type is the union ofint64
andfloat64
, meaning only those types are allowed
func SumIntsOrFloats[K comparable, V int64 | float64](m map[K]V) V { var s V for _, v := range m { s += v } return s }
Generics with Type Constraint
- You can create a named type constraint using an
interface
type Number interface { int64 | float64 } func SumNumbers[K comparable, V Number](m map[K]V) V { var s V for _, v := range m { s += v } return s }
Main
- When calling a generic function you can specify the types being used in square brackets
- For example,
SumIntsOrFloats[string, int64](ints)
is clearly stating the types used for the key and value - The square brackets can be omitted when the compiler is able to infer the types like the below example
func main() { ints := map[string]int64{ "first": 34, "second": 12, } floats := map[string]float64{ "first": 35.98, "second": 26.99, } fmt.Printf("Non-Generic Sums: %v and %v\n", SumInts(ints), SumFloats(floats)) fmt.Printf("Generic Sums: %v and %v\n", SumIntsOrFloats(ints), SumIntsOrFloats(floats)) fmt.Printf("Generic Sums with Constraint: %v and %v\n", SumNumbers(ints), SumNumbers(floats)) }
Putting it all together
package main import "fmt" func SumInts(m map[string]int64) int64 { var s int64 for _, v := range m { s += v } return s } func SumFloats(m map[string]float64) float64 { var s float64 for _, v := range m { s += v } return s } func SumIntsOrFloats[K comparable, V int64 | float64](m map[K]V) V { var s V for _, v := range m { s += v } return s } type Number interface { int64 | float64 } func SumNumbers[K comparable, V Number](m map[K]V) V { var s V for _, v := range m { s += v } return s } func main() { ints := map[string]int64{ "first": 34, "second": 12, } floats := map[string]float64{ "first": 35.98, "second": 26.99, } fmt.Printf("Non-Generic Sums: %v and %v\n", SumInts(ints), SumFloats(floats)) fmt.Printf("Generic Sums: %v and %v\n", SumIntsOrFloats(ints), SumIntsOrFloats(floats)) fmt.Printf("Generic Sums with Constraint: %v and %v\n", SumNumbers(ints), SumNumbers(floats)) }
Using flag
package
package main import ( "flag" "fmt" ) func main() { var msg string var count int64 flag.StringVar(&msg, "msg", "hello world", "message to show the user") flag.Int64Var(&count, "count", 1, "number of times to show the message") flag.Parse() for i := 0; i < int(count); i++ { fmt.Println(msg) } }
Recommended Packages
- tarm/serial - Great cross platform serial communication library