Golang中学习通道(Channel)及阅读官方文档的心得
Golang中学习通道(Channel)及阅读官方文档的心得 文档:
可选的 <- 操作符指定通道的方向,发送或接收。如果没有指定方向,通道是双向的。通道可以通过赋值或显式转换被限制为仅发送或仅接收。
chan T // 可用于发送和接收类型为 T 的值
chan<- float64 // 只能用于发送 float64 值
<-chan int // 只能用于接收 int 值
<- 操作符尽可能与最左边的 chan 结合:
chan<- chan int // 等同于 chan<- (chan int)
chan<- <-chan int // 等同于 chan<- (<-chan int)
<-chan <-chan int // 等同于 <-chan (<-chan int)
chan (<-chan int)
<- 操作符尽可能与最左边的 chan 结合(文档)
为什么我们使用 c <- <- input1 来接收?c 是在发送 c <- 并接收 <-input1 吗?
chan<- (<-chan int) 或 c <- (<- input1) 是等价的,但当我从左到右大声读出来时,这说不通。c 是在发送 c <- 并接收 <-input1 吗?<- <- 会相互抵消并默认最左边的通道接收吗?
我理解 c 是一个双向通道,因此它可以处理接收和发送的转换,但由于某种原因,我很难看出这里的逻辑模式。
更多关于Golang中学习通道(Channel)及阅读官方文档的心得的实战教程也可以访问 https://www.itying.com/category-94-b0.html
c <- <- input1 从 input1 读取一个值并将其写入 c。更清晰的写法是:
value := <-input
c <- value
更多关于Golang中学习通道(Channel)及阅读官方文档的心得的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在通道操作中,c <- <-input1 的语法确实需要仔细理解。这里的关键是区分通道类型声明中的 <- 和通道操作中的 <-。
通道操作解析:
c <- <-input1
实际上等价于:
c <- (<-input1)
这意味着:
- 先执行
<-input1从input1通道接收一个值 - 然后将这个值发送到通道
c
示例代码:
package main
import (
"fmt"
"time"
)
func main() {
// 创建两个通道
input1 := make(chan int)
c := make(chan int)
// 启动发送协程
go func() {
defer close(input1)
for i := 1; i <= 3; i++ {
input1 <- i
time.Sleep(100 * time.Millisecond)
}
}()
// 启动处理协程
go func() {
for {
// 这里就是 c <- <-input1 的用法
// 先从 input1 接收,然后发送到 c
value, ok := <-input1
if !ok {
close(c)
return
}
c <- value
}
}()
// 主协程从 c 接收并打印
for v := range c {
fmt.Println("Received:", v)
}
}
通道方向类型示例:
package main
import "fmt"
// 仅发送通道参数
func sendOnly(ch chan<- int, value int) {
ch <- value
// 以下代码会编译错误:不能从只发送通道接收
// v := <-ch
}
// 仅接收通道参数
func receiveOnly(ch <-chan int) int {
return <-ch
}
func main() {
ch := make(chan int, 1)
// 传递双向通道给只发送函数
sendOnly(ch, 42)
// 传递双向通道给只接收函数
result := receiveOnly(ch)
fmt.Println("Result:", result) // 输出: Result: 42
// 类型转换示例
var sendCh chan<- int = ch
var recvCh <-chan int = ch
sendCh <- 100
value := <-recvCh
fmt.Println("Value:", value) // 输出: Value: 100
}
复杂通道类型解析:
package main
import "fmt"
func process(ch <-chan <-chan int) {
// ch 是接收通道,其元素类型是 <-chan int(只接收通道)
for innerCh := range ch {
// innerCh 是 <-chan int
for v := range innerCh {
fmt.Println("Value:", v)
}
}
}
func main() {
// 创建通道的通道
ch := make(chan (<-chan int))
go func() {
defer close(ch)
// 创建内层通道
inner1 := make(chan int, 2)
inner1 <- 1
inner1 <- 2
close(inner1)
ch <- inner1
inner2 := make(chan int, 2)
inner2 <- 3
inner2 <- 4
close(inner2)
ch <- inner2
}()
process(ch)
}
在 c <- <-input1 中,第一个 <- 是发送操作符(紧挨着 c),第二个 <- 是接收操作符(紧挨着 input1)。Go 编译器会根据上下文正确解析这些操作符,不会出现 <- <- 相互抵消的情况。


