使用频道

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 然后通道将允许交换的数据类型。

这是向通道发送值的代码块,需要使用 <- operator:

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函数等待所有项目完成。