funcadd(x int, y int)int { // or // func add(x, y int) int { return x + y }
// Multiple results funcswap(x, y string) (string, string) { return y, x }
// Named return values funcsplit(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
funcmain() { 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) }
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.
funcmain() { 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 { } }
funcsqrt(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. funcpow(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 }
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.
funcmain() { 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"
funcmain() { 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.
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 )
funcmain() { 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.
// 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.
funcmain() { 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.
// 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) }
funcmain() { 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 }
ch := make(chanint) // with buffer ch := make(chanint, 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: