Golang Basic

Hello World

1
2
3
4
5
6
7
8
9
package main

import (
"fmt"
)

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

Basics

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package main

import (
"fmt"
"math"
"math/rand"
)

func add(x int, y int) int {
// or
// func add(x, y int) int {
return x + y
}

// Multiple results
func swap(x, y string) (string, string) {
return y, x
}

// Named return values
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return
}

// package level variables
// default values:
// 0 for numeric types,
// false for the boolean type, and
// "" (the empty string) for strings.
var c, python, java bool

// Constants cannot be declared using the := syntax.
const Pi = 3.14

const (
// Create a huge number by shifting a 1 bit left 100 places.
// In other words, the binary number that is 1 followed by 100 zeroes.
Big = 1 << 100
// Shift it right again 99 places, so we end up with 1<<1, or 2.
Small = Big >> 99
)

// Variables with initializers
var i, j int = 1, 2

func main() {
fmt.Println("My favorite number is", rand.Intn(10))

fmt.Println(math.Pi) // In Go, a name is exported if it begins with a capital letter.

fmt.Println(add(42, 13))

a, b := swap("hello", "world")
fmt.Println(a, b)

fmt.Println(split(17))

// function level variables
var i int // default 0
fmt.Println(i, c, python, java)

var c, python, java = true, false, "no!"
fmt.Println(i, j, c, python, java)

// Inside a function, the := short assignment statement can be used in place of a var declaration with implicit type.
// Outside a function, every statement begins with a keyword (var, func, and so on) and so the := construct is not available.
//var i, j int = 1, 2
//k := 3
//c, python, java := true, false, "no!"
//fmt.Println(i, j, k, c, python, java)
}

Basic Types

types

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bool

string

int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr

byte // alias for uint8

rune // alias for int32
// represents a Unicode code point

float32 float64

complex64 complex128

example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

import (
"fmt"
"math/cmplx"
)

var (
ToBe bool = false //xx
MaxInt uint64 = 1<<64 - 1
z complex128 = cmplx.Sqrt(-5 + 12i)
)

func main() {
fmt.Printf("Type: %T Value: %v\n", ToBe, ToBe)
fmt.Printf("Type: %T Value: %v\n", MaxInt, MaxInt)
fmt.Printf("Type: %T Value: %v\n", z, z)
}

type conversion

The expression T(v) converts the value v to the type T.

1
2
3
4
5
6
7
8
var i int = 42
var f float64 = float64(i)
var u uint = uint(f)

//or
i := 42
f := float64(i)
u := uint(f)

Control Flow

for

Unlike other languages like C, Java, or JavaScript there are no parentheses surrounding the three components of the for statement and the braces { } are always required.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import "fmt"

func main() {
sum := 0
for i := 0; i < 10; i++ {
sum += i
}
for ; sum < 10; {
sum += sum
}
for sum < 10 {
sum += sum
}
fmt.Println(sum)

// loop forever
for {
}
}

if

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package main

import (
"fmt"
"math"
)

func sqrt(x float64) string {
if x < 0 {
return sqrt(-x) + "i"
}
return fmt.Sprint(math.Sqrt(x))
}

// if statement can start with a short statement to execute before the condition.
func pow(x, n, lim float64) float64 {
if v := math.Pow(x, n); v < lim {
return v
} else {
fmt.Printf("%g >= %g\n", v, lim)
}
// can't use v here, though
return lim
}

func main() {
fmt.Println(
sqrt(2),
sqrt(-4),
pow(3, 3, 20),
)
}

switch

Go’s switch is like the one in C, C++, Java, JavaScript, and PHP, except that Go only runs the selected case, not all the cases that follow. In effect, the break statement that is needed at the end of each case in those languages is provided automatically in Go. Another important difference is that Go’s switch cases need not be constants, and the values involved need not be integers.
Switch cases evaluate cases from top to bottom, stopping when a case succeeds.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package main

import (
"fmt"
"time"
)

func main() {
fmt.Println("When's Saturday?")
today := time.Now().Weekday()
switch time.Saturday {
case today + 0:
fmt.Println("Today.")
case today + 1:
fmt.Println("Tomorrow.")
case today + 2:
fmt.Println("In two days.")
default:
fmt.Println("Too far away.")
}

// Switch without a condition is the same as switch true.
// This construct can be a clean way to write long if-then-else chains.
t := time.Now()
switch {
case t.Hour() < 12:
fmt.Println("Good morning!")
case t.Hour() < 17:
fmt.Println("Good afternoon.")
default:
fmt.Println("Good evening.")
}
}

defer

A defer statement defers the execution of a function until the surrounding function returns.
Deferred function calls are pushed onto a stack. When a function returns, its deferred calls are executed in last-in-first-out order.

1
2
3
4
5
6
7
8
9
10
11
12
13
package main

import "fmt"

func main() {
fmt.Println("counting")

for i := 0; i < 10; i++ {
defer fmt.Println(i)
}

fmt.Println("done")
}

More Types

pointer (C)

The type *T is a pointer to a T value. Its zero value is nil.
The & operator generates a pointer to its operand.
Unlike C, Go has no pointer arithmetic.

1
2
3
4
5
6
var p *int

i := 42
p = &i

*p = 21

struct (C)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import "fmt"

type Vertex struct {
X int
Y int
}

var (
v1 = Vertex{1, 2} // has type Vertex
v2 = Vertex{X: 1} // Y:0 is implicit
v3 = Vertex{} // X:0 and Y:0
p = &Vertex{1, 2} // has type *Vertex
)

func main() {
v := Vertex{1, 2}
p := &v
(*p).X = 1e9 // p.X = 1e9 is the same
fmt.Println(v)
}

array (C)

The type [n]T is an array of n values of type T. Slices are like references to arrays.

1
var a [10]int

slice

An array has a fixed size. A slice, on the other hand, is a dynamically-sized, flexible view into the elements of an array. In practice, slices are much more common than arrays.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
a[low : high]

// A slice literal is like an array literal without the length.
q := []int{2, 3, 5, 7, 11, 13}

// The default is zero for the low bound and the length of the slice for the high bound.
a[0:10]
a[:10]
a[0:]
a[:]

// The length of a slice is the number of elements it contains.
// The capacity of a slice is the number of elements in the underlying array, counting from the first element in the slice.
// The length and capacity of a slice s can be obtained using the expressions len(s) and cap(s).

// The zero value of a slice is nil.

// Slices can be created with the built-in make function; this is how you create dynamically-sized arrays.
b := make([]int, 0, 5) // len(b)=0, cap(b)=5

// func append(s []T, vs ...T) []T
var s []int
s = append(s, 0)

range

When ranging over a slice, two values are returned for each iteration. The first is the index, and the second is a copy of the element at that index.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main

import "fmt"

var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}

func main() {
for i, v := range pow {
fmt.Printf("2**%d = %d\n", i, v)
}
pow := make([]int, 10)
// If you only want the index, drop the , value entirely.
for i := range pow {
pow[i] = 1 << uint(i) // == 2**i
}
// You can skip the index or value by assigning to _.
for _, value := range pow {
fmt.Printf("%d\n", value)
}
}

map

The zero value of a map is nil. A nil map has no keys, nor can keys be added.
The make function returns a map of the given type, initialized and ready for use.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package main

import "fmt"

type Vertex struct {
Lat, Long float64
}

var m map[string]Vertex

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

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

m = make(map[string]Vertex)
m["Bell Labs"] = Vertex{
40.68433, -74.39967,
}

m[key] = elem

elem = m[key]

delete(m, key)

// If key is in m, ok is true. If not, ok is false.
elem, ok = m[key]

function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import "fmt"

func adder() func(int) int {
sum := 0
return func(x int) int {
sum += x
return sum
}
}

func main() {
pos, neg := adder(), adder()
for i := 0; i < 10; i++ {
fmt.Println(
pos(i),
neg(-2*i),
)
}
}

Methods

method

Like C, struct is passed by value (copy).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main

import (
"fmt"
"math"
)

type Vertex struct {
X, Y float64
}

func (v Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func main() {
v := Vertex{3, 4}
fmt.Println(v.Abs())
}

interface

Interfaces are implemented implicitly, no “implements” keyword.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import "fmt"

type I interface {
M()
}

type T struct {
S string
}

// This method means type T implements the interface I,
// but we don't need to explicitly declare that it does so.
func (t T) M() {
fmt.Println(t.S)
}

func main() {
var i I = T{"hello"}
i.M()
}

An empty interface interface{} may hold values of any type. (Every type implements at least zero methods.)

t := i.(T) asserts that the interface value i holds the concrete type T and assigns the underlying T value to the variable t. If i does not hold a T, the statement will trigger a panic.

t, ok := i.(T) If i holds a T, then t will be the underlying value and ok will be true.

A type switch is a construct that permits several type assertions in series.

1
2
3
4
5
6
7
8
switch v := i.(type) {
case T:
// here v has type T
case S:
// here v has type S
default:
// no match; here v has the same type as i
}

Stringer (Java)

1
2
3
type Stringer interface {
String() string
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

import "fmt"

type Person struct {
Name string
Age int
}

func (p Person) String() string {
return fmt.Sprintf("%v (%v years)", p.Name, p.Age)
}

func main() {
a := Person{"Arthur Dent", 42}
z := Person{"Zaphod Beeblebrox", 9001}
fmt.Println(a, z)
}

Error

1
2
3
type error interface {
Error() string
}
1
2
3
4
5
6
i, err := strconv.Atoi("42")
if err != nil {
fmt.Printf("couldn't convert number: %v\n", err)
return
}
fmt.Println("Converted integer:", i)

Reader (C)

package: io.Reader

1
func (T) Read(b []byte) (n int, err error)

Concurrency

goroutine (Coroutine)

1
go f(x, y, z)

channel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ch := make(chan int)
// with buffer
ch := make(chan int, 100)
// Sends to a buffered channel block only when the buffer is full. Receives block when the buffer is empty.

close(c)

ch <- v // Send v to channel ch.
v := <-ch // Receive from ch, and
// assign value to v.
v, ok := <-ch // ok is false if there are no more values to receive and the channel is closed.
for i := range c // receives values from the channel repeatedly until it is closed.

// A select blocks until one of its cases can run, then it executes that case. It chooses one at random if multiple are ready.
select {
case i := <-c:
// use i
case <-quit:
default:
// receiving from c would block
}

sync.Mutex

Go’s standard library provides mutual exclusion with sync.Mutex and its two methods:

1
2
Lock
Unlock