Go concurrent


Release date:2023-09-20 Update date:2023-10-13 Editor:admin View counts:365

Label:

Go concurrent

Go language supports concurrency, we just need to pass the go keyword to open goroutine that’s it.

goroutine is a lightweight thread, and the scheduling of goroutine is determined by the Golang managed at run time.

goroutine syntax format:

Go function name (parameter list)

For example:

go f(x, y, z)

Open a new goroutine :

f(x, y, z)

Go allow to use go statement to start a new runtime thread, that is, goroutine with a different, newly created goroutine to execute a function. Everything in the same program goroutine share the same address space.

Example

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")
}

Execute the above code and you will see the output hello and world , there is no fixed order. Because they’re two goroutine in the execution:

world
hello
hello
world
world
hello
hello
world
world
hello

Channel

A channel is a data structure used to transmit data.

The channel can be used for two goroutine run and communicate synchronously by passing a value of a specified type between. Operator <- used to specify the direction of the channel, send or receive. A two-way channel if no direction is specified.

ch <- v    // Send v to channel ch
v := <-ch  // Receive data from ch
           // And assign the value to v

Declaring a channel is simple, and we use the chan keyword, and the channel must be created before it is used:

ch := make(chan int)

Note: by default, channels do not have buffers. The sender sends data, and there must be corresponding received data at the receiving end.

The following example uses two goroutine to calculate the sum of the numbers, in goroutine when the calculation is complete, it calculates the sum of the two results:

Example

package main
import "fmt"
func sum(s []int, c chan int) {
        sum := 0
        for \_, v := range s {
                sum += v
        }
        c <- sum // Send sum to channel c
}
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, <-c // Received from channel c
        fmt.Println(x, y, x+y)
}

The output is as follows:

-5 17 12

Channel buffer

The channel can set a buffer through the make specifies the buffer sizeas the second parameter:

ch := make(chan int, 100)

The channel with buffer allows the data sent by the sender and the data acquisition by the receiver to be in an asynchronous state, that is, the data sent by the sender can be placed in the buffer and can wait for the receiver to obtain the data. Instead of needing the receiver to get the dataimmediately.

However, because the size of the buffer is limited, there must be a receiverto receive the data, otherwise the buffer is full and the data sender can no longer send data.

Note: if the channel is not buffered, the sender blocks until the receiver receives the value from the channel. If the channel is buffered, the sender blocks until the sent value is copied into the buffer; if the buffer is full, it means you need to wait until a receiver gets a value. The receiver blocks until it has a value to receive.

Example

package main
import "fmt"
func main() {
    // Here we define a buffered channel that can store integer types
        // The buffer size is 2
        ch := make(chan int, 2)
        // Because ch is a buffered channel, we can send two data simultaneously
        // Without the need to synchronize data reading immediately
        ch <- 1
        ch <- 2
        // Obtain these two data
        fmt.Println(<-ch)
        fmt.Println(<-ch)
}

The output of the execution is:

1
2

Go ergodic and closed channel

Go pass through range keyword to traverse the read data, similar toan array or slice. The format is as follows:

v, ok := <-ch

If the channel cannot receive the data, ok just for false at whichpoint the channel can be used close() function to close.

Example

package main
import (
        "fmt"
)
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)
}
func main() {
        c := make(chan int, 10)
        go fibonacci(cap(c), c)
        // The range function traverses each data received from the channel,
        as c completes sending 10
        // After the data, the channel was closed, so here our range function receives 10
        data
        // And then it ended. If the c channel above is not closed,
        then the range function will not
        // It will end, thus blocking when receiving the 11th data.
        for i := range c {
                fmt.Println(i)
        }
}

The output of the execution is:

0
1
1
2
3
5
8
13
21
34

Powered by TorCMS (https://github.com/bukun/TorCMS).