当前位置:网站首页>Go concurrency and channel

Go concurrency and channel

2022-04-23 15:41:00 The end of the world and you

Go Concurrency and channels

1.Go Concurrent

Go Languages support concurrency , We just need to pass go Keyword to open goroutine that will do .

goroutine It's a lightweight thread ,goroutine The dispatch of is made by Golang Managed at run time .

goroutine Grammar format :

go  Function name (  parameter list  )

Go Allow to use go Statement to open a new runtime thread , namely goroutine, With a different 、 The newly created goroutine To execute a function . All in the same program goroutine Share the same address space .

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")
}
---------------------------------
 Output :
hello
world
world
hello
hello
world
world
hello
hello

Execute the above code , You'll see the output hello and world There is no fixed order . Because they are two goroutine In execution


2. passageway (channel)

passageway (channel) Is a data structure used to transfer data .

Channels can be used for two goroutine By passing a value of the specified type to synchronize operation and communication between . The operator <- Used to specify the direction of the channel , To send or receive . If no direction is specified , It's a two-way channel .

ch <- v    //  hold  v  Send to channel  ch
v := <-ch  //  from  ch  receive data 
           //  And assign values to  v

Be careful : By default , The channel is unbuffered . The sender sends data , At the same time, there must be corresponding receiving data at the receiving end .

example 1: Through two goroutine To sum up the numbers , stay goroutine After the calculation , It calculates the sum of the two results

package main

import "fmt"

func sum(s []int, c chan int) {
    
        sum := 0
        for _, v := range s {
    
                sum += v
        }
        c <- sum //  hold  sum  Send 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 //  From the tunnel  c  In the receiving 

        fmt.Println(x, y, x+y)
}
-------------------------------------
 Output :-5 17 12

Channel buffer

Channels can set buffers , adopt make The second parameter of specifies the buffer size :

ch := make(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 , In other words, the data sent by the sender can be put in the buffer , You can wait for the receiver to get the data , Instead of requiring the receiver to get the data immediately .

But because the size of the buffer is limited , So there must be a receiver to receive data , Otherwise the buffer is full , The data sender can't send any more data .

Be careful : 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 value 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 2: Using buffers

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  It's a buffered channel , We can send two data at the same time 
        //  Instead of having to synchronize reading data immediately 
        ch <- 1
        ch <- 2

        //  Get these two data 
        fmt.Println(<-ch)
        fmt.Println(<-ch)
}
-----------------------------
 Output :
1
2

Go Traversing channels and closing channels

Go adopt range Keyword to traverse the read data , Similar to array or slice . The format is as follows :

v, ok := <-ch

If the channel does not receive data ok for false, Then the channel can be used close() Function to close .

example 3:

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  Function traverses each data received from the channel , because  c  After sending  10  individual 
        //  After the data, the channel is closed , So here we are  range  Function is receiving  10  Data 
        //  And then it's over . If the top  c  The channel doesn't close , that  range  Functions don't 
        //  It's over , So in the receiving section  11  It's blocked when it comes to data .
        for i := range c {
    
                fmt.Println(i)
        }
}
-----------------------------------------
 Output :
0
1
1
2
3
5
8
13
21
34

Copyright notice : This tutorial is based on the rookie tutorial

版权声明
本文为[The end of the world and you]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204231533523936.html