Go中通道声明必须指定元素类型和方向,如var ch chan int(双向)、var ch

通道类型声明的语法结构
Go 里声明通道变量必须显式指定元素类型和方向,不能只写 chan。最基础的形式是 var ch chan int,这声明了一个可读可写的双向通道。但实际中更常见的是带方向限定的声明,比如 var ch (只读)或 <code>var ch chan(只写),这类限定在函数参数中特别有用,能防止误用。
- 方向关键字必须紧贴
chan,合法,<code>chan 是语法错误 - 未初始化的通道变量默认值是
nil,直接收发会 panic,必须配合make(chan T)初始化 - 类型参数不能是“未定义”类型,比如不能写
chan struct{}而不加字段(空结构体可以,但得写全chan struct{}{})
使用 make 初始化通道时的缓冲区控制
make(chan T) 创建的是无缓冲通道(同步通道),make(chan T, N) 才创建带缓冲的通道。缓冲区大小 N 必须是非负整数,传负数会编译报错:invalid argument N (constant -1) for cap。
- 缓冲为 0 时,发送和接收必须同时就绪,否则阻塞;缓冲 > 0 时,最多可缓存 N 个值,满后才阻塞发送
- 缓冲区大小在运行期不可变,也不能通过反射修改
- 如果只是做信号通知(如
done := make(chan struct{})),用无缓冲就够了,没必要设缓冲 1
短变量声明与类型推导的边界
ch := make(chan int) 是合法的,类型由 make 返回值推导出。但下面这些写法不行:
-
ch := chan int—— 缺少make,这不是声明通道变量,而是类型字面量 -
var ch = make(chan int, 0)—— 可以,但0冗余,等价于make(chan int) -
var ch chan—— 缺少元素类型,编译报错:missing type in channel declaration
注意:函数返回通道时,返回类型必须完整,比如 func NewCh() ,不能省略 <code>string。
立即学习“go语言免费学习笔记(深入)”;
通道方向在函数签名中的实际约束
函数参数声明为 或 <code>chan,调用方传入的实参会被自动转换(只要底层类型一致)。例如:
func printer(ch <-chan string) {
fmt.Println(<-ch)
}
...
c := make(chan string)
printer(c) // OK:chan string → <-chan string
但反过来不行:如果函数要求 chan(只写),你传一个 <code>(只读)就会编译失败。这种类型系统层面的约束,比注释或文档更可靠。
通道变量本身没有“运行时方向”,方向只是编译期类型标记;但一旦用错方向(比如对只读通道调 ch ),编译器立刻报错:<code>send to receive-only type 。
类型声明容易忽略的是:通道的零值是 nil,而 nil 通道在 select 中有特殊行为(永远不就绪),这点和 map、slice 的 nil 行为不完全一致,容易引发隐蔽逻辑分支。


















