Introdução ao canal
O modelo de simultaneidade da linguagem Go, CSP (Communicating Sequential Processes), defende o compartilhamento da memória por meio da comunicação em vez do compartilhamento da memória.
Embora você possa usar a memória compartilhada para troca de dados, a memória compartilhada está sujeita a condições de corrida em diferentes goroutines. Para garantir a exatidão da troca de dados, um mutex deve ser usado para bloquear a memória, o que pode causar problemas de desempenho.
channel
: É o mecanismo de comunicação na linguagem Go que envia a uma goroutine um valor específico para outra goroutine.
O canal na linguagem Go é um tipo especial. Um canal é uma fila que sempre segue a regra do primeiro a entrar, primeiro a sair (Primeiro a entrar, primeiro a sair) para garantir a ordem de envio e recebimento de dados. Cada canal é um tipo específico de conduíte, ou seja, quando você declara o canal, é necessário especificar o tipo de elemento para ele.
Uso do canal
tipo de canal
- Canal é um tipo de referência. O formato para declarar um canal é o seguinte:
var 变量 chan 元素类型
-------------------------
var ch1 chan int // 声明一个传递整型的通道
var ch2 chan bool // 声明一个传递布尔型的通道
var ch3 chan []int // 声明一个传递int切片的通道
Criar canal
Uma vez que o canal é um tipo de referência, o valor padrão do canal é nulo
var ch1 chan int
fmt.Println(ch1)//<nil>
Depois que o canal é declarado, ele precisa ser inicializado com a função make antes que possa ser usado.
A sintaxe do make para inicializar o canal é:
make(chan 元素类型, [缓冲大小])
Canal de operação
O canal tem três operações: tanto o 发送,接收,关闭
envio quanto o recebimento são usados:<-
ch1 := make(chan int)
ch1 <- 10//将10发送到ch1中
x :=<-ch1 //从ch1接收值并赋给x
desligar:
close(ch1)
Nota: Não é necessário fechar o canal. O canal só precisa ser fechado quando a goroutine do receptor for notificada que todos os dados foram enviados. O canal pode ser coletado como lixo.
Enviar valores ou fechar operações para um canal fechado causará pânico.
O valor recebido de um canal fechado pode ser levado ao valor até que o canal esteja vazio, e quando o canal não tiver valor, então o valor obtido só pode ser o valor zero do tipo correspondente.
Canal sem buffer
Canais sem buffer também são chamados de canais bloqueados:
ch1 := make(chan int)
ch1 <- 10//将10发送到ch1中
Ao ch1 := make(chan int)
criar um canal sem buffer, o canal sem buffer só pode enviar valores quando o receptor existe, caso contrário, ocorrerá um erro de deadlock.
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
Existem duas soluções:
- Comece um goroutine para receber
func recvdata(c chan int) {
data :=<-c
fmt.Println("接收成功data",data)
}
func main() {
//var ch1 chan int
//fmt.Println(ch1)
ch1 := make(chan int)
go recvdata(ch1)//启动goroutine接收通道里面的值
ch1<-10//发送10
fmt.Println("发送成功")
}
同步通道
: A operação de envio no canal sem buffer será bloqueada até que outro goroutine execute a operação de recebimento no canal, então o valor pode ser enviado com sucesso e os dois goroutines continuarão a executar. Ao contrário, se a operação de recepção for executada primeiro, a goroutine do receptor será bloqueada até que outra goroutine envie um valor para o canal.
O uso de canais sem buffer para comunicação resultará na sincronização das goroutines de envio e recebimento. Portanto, os canais sem buffer também são chamados de canais síncronos.
Canal de buffer
Um canal com buffer também é uma solução para o problema de um canal sem buffer.
Contanto que a capacidade do canal seja maior que zero, o canal é um canal com buffer. A capacidade do canal indica o número de elementos que podem ser armazenados no canal.
Crie um canal em buffer:
ch := make(chan int, 1) // 创建一个容量为1的有缓冲区通道
Não haverá situação de impasse desta forma. E esses dados também existem neste canal para armazenamento em buffer.
Canal unilateral
Um canal unilateral é fornecido no idioma Go para restringir os dados a serem enviados ou recebidos apenas
1.chan<- int是一个只能发送的通道,可以发送但是不能接收;
out chan <-int
2.<-chan int是一个只能接收的通道,可以接收但是不能发送。
in <-chan int
Um canal bidirecional pode ser alterado para unilateral, mas um canal unilateral não pode ser alterado para bidirecional.