WEB DEVELOPER SITE
HTMLCSSJAVASCRIPTSQLPHPBOOTSTRAPJQUERYANGULARXML
 

Go concurrent


Go language supports concurrency, we only need to open goroutine with the go keyword.

goroutine is a lightweight thread, and goroutine scheduling is managed by the Golang runtime.

goroutine syntax format:

go function name( Parameter List )

Example:

go f(x, y, z)

Open a new goroutine:

f(x, y, z )

Go allows you to use the go statement to open a new runtime thread, goroutine, to execute a function with a different, newly created goroutine. All goroutines in the same program 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, you will see that the output of hello and world is not in a fixed order. Because they are two goroutines executing:

world
hello
hello
world
world
hello
hello
world
world
hello

channel

A channel is a data structure used to transfer data.

The

channel can be used to synchronize operations and communication between two goroutines by passing a value of the specified type. Operator<- Used to specify the direction of the channel, send or receive. If no direction is specified, it is a bidirectional channel.

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

Declaring a channel is simple. We can use the chan keyword. The channel must be created before it can be used:

ch := make(chan int)

Note: By default, the channel is without a buffer. The sender sends data and must receive the corresponding received data at the same time.

The following example uses two goroutines to calculate the sum of the numbers. After the goroutine completes the calculation, 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 the 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 // FromReceive in channel c

        fmt.Println(x, y, x+y)
}

The output is:

-5 17 12

Channel buffer

The channel can set the buffer, and the buffer size is specified by the second parameter of make :

ch := make< /span>(chan int , 100)

The channel with buffer allows the data transmission of the sender and the data acquisition of the receiver to be in an asynchronous state. That is to say, the data sent by the sender can be placed in the buffer, and the receiver can wait for the data to be acquired, instead of requiring the receiver immediately. Go to get the data.

However, since the size of the buffer is limited, there must be a receiving end to receive the data. Otherwise, the data sending end can no longer send data.

Note: If the channel is unbuffered, the sender blocks until the receiver receives a value from the channel. If the channel is buffered, the sender blocks until the value sent is copied into the buffer; if the buffer is full, it means waiting until a receiver gets a value. The receiver will block 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.
        // Buffer size is 2
        ch := make(chan int, 2)

        // Since ch is a buffered channel, we can send two numbers at the same timeśćģ
        // Without having to immediately read the data synchronously
        ch <- 1
        ch <- 2

        // Get these two data
        fmt.Println(<-ch)
        fmt.Println(<-ch)
}

Execution output is:

1
2

Go traverse channel and close channel

Go uses the range keyword to traverse the read data, similar to arrays or slices. The format is as follows:

v, ok := <-ch

If the channel does not receive data, ok is false, then the channel can be closed using the close() function.

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)
        // range The function iterates through the data received from each channel because c is sending 10
        // The channel is closed after the data, so here our range function receives 10 data.
        // Then it is over. If the above c channel is not closed, the range function is not
        // It will end, and it will block when it receives the 11th data.
        for i := range c {
                fmt.Println(i)
        }
}

Execution output is:

0
1
1
2
3
5
8
13
21
34