Go提供了一种称为通道的机制,该机制用于在goroutine之间共享数据。当您将并行活动作为goroutine执行时,需要在goroutine之间共享资源或数据,通道充当goroutine之间的管道(管道),并提供了保证同步交换的机制。
在声明通道时需要指定数据类型。我们可以共享内置,命名,结构和引用类型的值和指针。数据在通道中传递:在任何给定时间只有一个goroutine可以访问数据项:因此,设计不会发生数据争用。
根据通道的数据交换行为,有两种类型的通道:非缓冲通道和缓冲通道。未缓冲的通道用于执行goroutine之间的同步通信,而缓冲的通道用于执行异步通信。无缓冲通道可确保在发送和接收发生的瞬间执行两个goroutine之间的交换。缓冲通道没有这种保证。
通过make函数创建通道,该函数指定chan关键字和通道的元素类型。
Unbuffered := 使(chan int) // Unbuffered channel of integer type buffered := 使(chan int, 10) // Buffered channel of integer type
内置功能的使用 使 创建无缓冲和缓冲通道。第一个论点 使 需要关键字 chan 然后通道将允许交换的数据类型。
goroutine1 := 使(chan string, 5) // Buffered channel of strings. goroutine1 <- "Australia" // Send a string through the channel.
字符串类型的goroutine1通道,其中包含5个值的缓冲区。然后,通过通道发送字符串“ Australia”。
data := <-goroutine1 // Receive a string from the channel.
的 <- operator is attached to the left side of the channel variable(goroutine1), to receive a value from a channel.
在无缓冲通道中,没有能力在接收任何值之前保存任何值。在这种类型的通道中,发送和接收goroutine都必须在任何发送或接收操作可以完成之前的同一时刻准备就绪。如果两个goroutine尚未同时准备就绪,则通道会先等待执行各自发送或接收操作的goroutine。同步是通道上发送和接收之间交互的基础。一个没有其他就不可能发生。
在缓冲通道中,可以容纳一个或多个值,然后再接收它们。在这种类型的通道中,请勿强制goroutine在同一时刻准备就绪以执行发送和接收。发送或接收何时阻止也有不同的条件。仅当通道中没有值时,接收才会阻塞 接受。仅当没有可用缓冲区放置要发送的值时,发送才会阻塞。
// Simple program to demonstrate use of Buffered Channel package main import ( "fmt" "math/rand" "sync" "time" ) var goRoutine sync.WaitGroup func main(){ rand.Seed(time.Now().Unix()) // Create a buffered channel to manage the employee vs project load. projects := 使(chan string,10) // Launch 5 goroutines to handle the projects. goRoutine.Add(5) for i :=1; i <= 5; i++ { go employee(projects, i) } for j :=1; j <= 10; j++ { projects <- fmt.Sprintf("Project :%d", j) } // Close the channel so the goroutines will quit close(projects) goRoutine.Wait() } func employee(projects chan string, employee int) { defer goRoutine.Done() for { // Wait for project to be assigned. project, result := <-projects if result==false { // This means the channel is empty and closed. fmt.Printf("Employee : %d : Exit\n", employee) return } fmt.Printf("Employee : %d : Started %s\n", employee, project) // Randomly wait to simulate work time. sleep := rand.Int63n(50) time.Sleep(time.Duration(sleep) * time.Millisecond) // Display time to wait fmt.Println("\nTime to sleep",sleep,"ms\n") // Display project completed by employee. fmt.Printf("Employee : %d : Completed %s\n", employee, project) } }
每次您运行该程序时,该程序的输出都会不同,这是由于该程序和Go调度程序的随机性所致。
在上面的程序中,创建了一个字符串类型的缓冲通道,容量为10。WaitGroup的计数为5,每个goroutine一个。将10个字符串发送到通道中,以模拟或复制goroutine的项目。一旦最后一个字符串发送到通道中,通道将关闭,并且main函数等待所有项目完成。