A Tour of Go Introduces the concepts and usage of Go language threads, channels and mutex.

1. Go thread

$GOPATH/SRC/go_note gotour/concurrency/goroutine goroutine. Go source as follows

/** * package main import (" FMT ") func say(s string) {for I := 0; i < 2; i++ { fmt.Println(i, s) } } func main() { go say("world") say("hello") }Copy the code

Go threads (Goroutines) are lightweight threads managed by the Go runtime.

go f(x, y, z)
Copy the code

A new Go thread is started and executed

f(x, y, z)
Copy the code

Where the evaluation of f, x, y, and z takes place in the current Go thread, while the execution of F takes place in the new Go thread.

Go programs run in the same address space, so they must synchronize when accessing shared memory, which can be done by using the SYNC package or channel.

2. The channel

$GOPATH/SRC/go_note gotour/concurrency/channel/channel. Go source as follows

/** * package main import "FMT" func sum(s []int, c chan int) {sum := 0 for _, v := range s { sum += v } c < - sum } func fibonacci(n int, c chan int) { x, y := 0, 1 for i := 0; i < n; i++ { c < - x x, y = y, x + y} close (c) / / close the queue} func main () {s: int [] = {7, 2, 8, 9, 4, 0} c := make(chan int) go sum(s[:len(s)/2], c) go sum(s[len(s)/2:], c) x, y := < -c, < F := make(chan int, 10) go Fibonacci (cap(f), f) for i := range f { fmt.Println(i) } }Copy the code

Channels are typed pipes that send or receive values from the channel operator <-.

ch &lt; -v // Sends v to channel CH. v := &lt; -ch // Receives the value from ch and assigns v.Copy the code

The arrow is the direction of the data flow.

Channels must be created before use:

ch := make(chan int)
Copy the code

By default, both send and receive operations block until the other end is ready. This allows the Go program to synchronize without explicit locks or race variables.

2.1 Buffered channel

Channels can be buffered, and make initializes a buffered channel by supplying the buffer length as a second argument:

ch := make(chan int, 100)
Copy the code

Sending data to a channel blocks only when its buffer is full. When the buffer is empty, the receiver blocks.

2.2 the range and close

A sender can close a channel by closing it to indicate that there are no values to send. The receiver can test whether the channel is closed by taking the second argument to the receive expression: false if no value can be received and the channel is closed

v, ok := &lt; -ch // ok == falseCopy the code

The loop for I := range C continues to receive values from the channel until it is turned off.

Note: Only the sender can close the channel, not the receiver. Sending data to a closed channel raises a program error. Channels, unlike files, usually do not need to be closed. Closing is necessary only when the receiver must be told that there are no more values to send, such as terminating a range loop.

3. Select statement

$GOPATH/SRC/go_note/gotour/concurrency/select/select go source code is as follows:

Func Fibonacci (c, quit chan int) {x, y := 0, 1 for { select { case c&lt; -x: x, y = y, x+y case &lt; -quit: fmt.Println("quit") return default: Println(".")}}} func main() {c := make(chan int) quit := make(chan int) // go go func() {for I := 0; i &lt; 5; i++{ fmt.Println(&lt; -c) } quit&lt; -0 }() fibonacci(c, quit) }Copy the code

The SELECT statement enables a Go thread to wait for multiple communication operations.

Select blocks until a branch can continue, at which point the branch is executed. When multiple branches are ready, one is randomly selected for execution.

The default branch is executed when no other branch in the SELECT is ready. To avoid blocking when trying to send or receive, use the default branch

4. sync.Mutex

$GOPATH/SRC/go_note gotour/concurrency/mutex/mutex. Go the source code is as follows:

/** * go mutex */ package main import (" FMT ""sync" "time") // Type SafeCounter struct {v map[string]int mux Sync.mutex} // Add the counter func (c *SafeCounter) Inc(key String) {c.mux.lock () c.v[key]++ c.mux.unlock ()} // Return the current counter func (c *SafeCounter) Value(key string) int {c.mux.lock () defer C.mux.unlock () // return c.v[key]} func main() { c := SafeCounter{v: make(map[string]int)} for i := 0; i &lt; 1000; i++ { go c.Inc("somekey") } time.Sleep(time.Second) fmt.Println(c.Value("somekey")) //1000 }Copy the code

Mutual exclusion means that only one Go thread can access a shared variable at a time. Mutex is commonly used to provide this mechanism.

The SYNc. Mutex Mutex type and its two methods are provided in the Go library:

Lock()
Unlock()
Copy the code

A block of code is mutually exclusive by calling Lock() before code and Unlock() after code. You can also use the defer statement to ensure that the mutex is unlocked.

reference

  • Go Tour Chinese
  • A Tour of Go