Core Wiki

Golang

General

CLI

go build hello.go
go run hello.go
go mod init example.com/user/hello #creating module
go install example.com/user/hello # builds executable hello and installs in $HOME/go/bin/hello
export PATH=$PATH:$(dirname $(go list -f '{{.Target}}' .)) # appending path, we can now call ''hello''
go clean -modcache # remove all downloaded modules
go test # runs unit tests for *_test.go files
go test ./platform/newsfeed
go test ./...

Syntax

Equivalent inside a function
a := 5
var b int = 5
There is only ''for'' loop
for i := 0; i < 10; i++ {
}
 
for ; sum < 1000; {
}
 
for sum < 1000 {
}
 
for {
}
Switch can be with and without condition
today := time.Now().Weekday()
switch time.Saturday {
case today + 0:
	fmt.Println("Today.")
default:
	fmt.Println("Not today.")
}
t := time.Now()
switch {
case t.Hour() < 12:
	fmt.Println("Good morning!")
default:
	fmt.Println("Good evening.")
}
defer

defer statement defers the execution of a function until the surrounding function returns

func main() {
      defer fmt.Println("world")
      fmt.Println("hello")
}
//hello world

Range iterator

var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}
for i, v := range pow {
//
}
for i, _ := range pow {}
for _, value := range pow {}
for i := range pow {}
Pointers

Type *T is a pointer to a T value which has zero value nil by default.

i := 10
p := &i // & operator generates a pointer to its operand
*p = 20 // dereferencing operator denoting pointers underlying value

Data structures

Structs
type Vertex struct {
	X int
	Y int
}
s := Vertex{1,2}
Arrays
var a [10]string
primes := [6]int{2, 3, 5, 7, 11, 13}
Slices

slice does not store any data, it just describes a section of an underlying array

var s []int = primes[1:4] // [3, 5, 7]
a := make([]int, 5)
a = append(a, 0)
Hash map
type Vertex struct {
   Lat, Long float64
}
var m map[String]Vertex
 
m = make(map[string]Vertex)
m["BL"] = Vertex{-2.0, 3.0}
fmt.Println(m["BL"])

Map literal

var m = map[string]Vertex{
	"Bell Labs": Vertex{
		40.68433, -74.39967,
	},
	"Google": Vertex{
		37.42202, -122.08408,
	},
}
 
var m2 = map[string]Vertex{
	"Bell Labs": {40.68433, -74.39967},
	"Google":    {37.42202, -122.08408},
}

Map mutations

m[key] = elem
elem = m[key]
delete(m, key)
elem, ok := m[key] //if key is in m ok=true, else ok=false
String
s := strings.Split("a,b,c", ",")
s := strings.Fields("one two      three")

Methods and interfaces

Reasons to use pointer receivers:

  • Allows method to change value
  • Avoid copying value to each method call

Define a method on struct

type Vertex struct {
	X, Y float64
}
 
func (v Vertex) Abs() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
 
func (v *Vertex) Scale(f float64) {
	v.X = f * v.X
	v.Y = f * v.Y
}
 
v := Vertex{3, 4}
v.Scale(10) // works because go automatically casts v to &v
(&v).Scale(10)
fmt.Println(v.Abs())
fmt.Println((&v).Abs()) // works because go automatically dereferences &v to *(&v)

Methods on non-structs

type MyFloat float64
 
func (f MyFloat) Abs() float64 {
	if f < 0 {
		return float64(-f)
	}
	return float64(f)
}
f := MyFloat(-math.Sqrt2)
fmt.Println(f.Abs())

Interfaces are implemented implicitly

type I interface {
	M()
}
 
type T struct {
	S string
}
 
func (t T) M() {
	fmt.Println(t.S)
}
 
var i I = T{"hello"}
i.M()

Type assertions on Interface value

var i interface{} = "hello"
 
s, ok := i.(string)
fmt.Println(s, ok)
 
f, ok := i.(float64)
fmt.Println(f, ok)

Stringers allow to implement struct.String() method called by fmt.Println implicitly

type IPAddr [4]byte
 
func (ip IPAddr) String() string {
	return fmt.Sprintf("IPAddr: %v %v %v %v", ip[0], ip[1], ip[2], ip[3])
}
host := IPAddr{127, 0, 0, 1}
fmt.Println(host)