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 ./...
a := 5 var b int = 5
for i := 0; i < 10; i++ { } for ; sum < 1000; { } for sum < 1000 { } for { }
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 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 {}
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
type Vertex struct { X int Y int } s := Vertex{1,2}
var a [10]string primes := [6]int{2, 3, 5, 7, 11, 13}
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)
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
s := strings.Split("a,b,c", ",") s := strings.Fields("one two three")
Reasons to use pointer receivers:
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)