Golang is an open source programming language that makes it easy to build simple, reliable, and efficient software.
Created inside Google by Rob Pike, Ken Thompson & Robert Griesemer
Started in 2007, open-sourced in 2009
Golang is an attempt to combine the ease of programming of an interpreted, dynamically typed language with the efficiency and safety of a statically typed, compiled language.
Every Go program is made up of packages.
Programs start running in package main.
This program is using the packages with import paths "fmt" and "math/rand".
By convention, the package name is the same as the last element of the import path. For instance, the "math/rand" package comprises files that begin with the statement package rand.
You can write import statements, like:
import "fmt"
import "math"
// or factored imports (recommended way)
import (
"fmt"
"math"
)
In Go, a name is exported if it begins with a capital letter. For example, Pizza is an exported name, as is Pi, which is exported from the math package.
pizza and pi do not start with a capital letter, so they are not exported.
When importing a package, you can refer only to its exported names. Any "unexported" names are not accessible from outside the package.
// declare any variable with `var` keyword
var i int = 1
// if an initializer is present, the type can be omitted;
// the variable will take the type of the initializer.
var j = 2
// short variable declarations
k := 3
// multiple declarations
x, y := true, false
// use keyword `func` for declaring a function
// first parenthesis are for parameters
func foo () {
// do something
}
// return type is defined after parenthesis
func foo () int {
// return an integer value
return 1
}
// functions can also return multiple values
func foo () (int, string) {
// return an integer and a string
return 1, "bar"
}
// named return values
func foo () (i int, str string) {
// i, str are already declared
i = 1
str = "bar"
// return `i` & `str` automatically
return
}
Functions are values too. They can be passed around just like other values.
Function values may be used as function arguments and return values.
func calc(fn func(int, int) int) int {
return fn(4, 2)
}
calc(func(i int, j int) int {
return i + j
})
calc(func(i int, j int) int {
return i - j
})
calc(func(i int, j int) int {
return i * j
})
calc(func(i int, j int) int {
return i / j
})
Go functions may be closures. A closure is a function value that references variables from outside its body. The function may access and assign to the referenced variables; in this sense the function is "bound" to the variables.
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
The expression T(v) converts the value v to the type T.
Go has only one looping construct, the for loop.
// look, ma! no parenthesis
for i := 0; i < 10; i++ {
// do something
}
// `for` is Go's `while`
sum := 1
for sum < 1000 {
sum += sum
}
// forever
for {
// do something
}
// similar to `for`, there are no parenthesis in `if` either
if i > 0 {
// do something
}
// `if` statement can start with a short statement to execute before the condition.
if n := rand.Intn(); n > 5 {
// true
} else {
// false
}
// Note: `n` won't be accessible here.
A defer statement defers the execution of a function until the surrounding function returns.
The deferred call's arguments are evaluated immediately, but the function call is not executed until the surrounding function returns.
package main
import "fmt"
func main() {
defer fmt.Println("world")
fmt.Println("hello")
}
// The type *T is a pointer to a T value. Its zero value is nil.
var p *int
// The & operator generates a pointer to its operand.
i := 42
p = &i
// The * operator denotes the pointer's underlying value.
fmt.Println(*p) // read i through the pointer p
*p = 21 // set i through the pointer p
// This is known as "dereferencing" or "indirecting".
// Unlike C, Go has no pointer arithmetic.
A pointer holds the memory address of a variable.
package main
import "fmt"
type Vertex struct {
X, 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() {
fmt.Println(v1, p, v2, v3)
}
Go does not have classes. However, you can define methods on types.
A method is a function with a special receiver argument.
The receiver appears in its own argument list between the func keyword and the method name.
type T struct {
value int
}
// method is just a function with a receiver argument
// value receiver operates on a copy of the original's value
func (t T) fn() {
// do something with t.value here
}
// pointer receiver
// methods with pointer receivers can modify the value
// to which the receiver points
func (t *T) fn() {
// do something with t.value here
}
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 map maps keys to values.
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, initialised and ready for use.
m := make(map[string]int)
// insert or update an element in map `m`
m["Answer"] = 42
// retrieve an element
ans := m["Answer"]
// delete an element
delete(m, "Answer")
// test that a key is present with a two-value assignment:
v, ok := m["Answer"]
A type assertion provides access to an interface value's underlying concrete value.
A type switch is a construct that permits several type assertions in series.
package main
import (
"fmt"
"time"
)
func say(s string) {
for i := 0; i < 5; i++ {
time.Sleep(100 * time.Millisecond)
fmt.Println(s)
}
}
func main() {
go say("world")
say("hello")
}
package main
import (
"fmt"
"time"
)
func say(s string) {
for i := 0; i < 5; i++ {
time.Sleep(100 * time.Millisecond)
fmt.Println(s)
}
}
func main() {
go say("world")
say("hello")
}
A lightweight thread managed by the Go runtime
ch <- v // Send v to channel ch.
v := <-ch // Receive from ch, and
// assign value to v.
// The data flows in the direction of the arrow
Channels are a typed conduit through which you can send and receive values with the channel operator, <-.