Channel 的声明
小白表示大概可能或许应该理解了什么是 Channel.
那么接下来我们来看看如何声明 Channel.
后文中为了便于表达, 我们使用信道来代替单词 channel.
在 Go 语言中, 提供的信道原语是 chan
.
声明时 chan
后要紧跟数据类型, 表示该信道中可以承载的数据类型是什么.
如下:
// 声明一个信道变量 ch1, 其内可以承载 int 类型的数据
var ch1 chan int
// 声明一个信道变量 ch2, 其内可以承载 string 类型的数据
var ch2 chan string
同时顺带提一下, 信道通常在多个协程中读写, 所以按照读写区分, 还可以细分为:
- 只读信道
- 只写信道
- 读写信道
声明分别如下:
// 只读信道
var readonlyChannel <-chan int
// 只写信道
var writeonlyChannel chan<- int
// 读写信道
var readWriteChannel chan int
在声明信道类型时
<-chan
箭头向外表示只读chan<-
箭头向内表示只写chan
没有箭头表示读写都可行
好了, 按照一般变量的方式信道是不是声明好了呢?
我们来测试下对声明的信道变量进行操作
// channel_test.go
// test ReadWriteChannel
func TestReadWriteChannel(t *testing.T) {
var readWriteChannel chan int
t.Logf("readWriteChannel type is %T", readWriteChannel)
t.Log(readWriteChannel)
}
执行测试
go test .
不出意外的话, 输入如下
=== RUN TestReadWriteChannel
--- PASS: TestReadWriteChannel (0.00s)
channel_test.go:43: readWriteChannel type is chan int
channel_test.go:44: <nil>
PASS
输出了信道的类型, 和我们声明的类型是一致的. 而信道变量的零值为 nil
.
但是这样声明的信道变量并没有什么用, 实际应用中我们通过 make
给信道类型的分配内存空间.
我们来个测试对比看下
// channel_test.go
func TestChannel(t *testing.T) {
var ch1 chan int
t.Logf("ch1 type is %T", ch1)
t.Log(&ch1)
t.Log(ch1)
//
ch2 := make(chan int)
t.Logf("ch2 type is %T", ch2)
t.Log(&ch2)
t.Log(ch2)
}
不出意外的话, 输出如下
=== RUN TestChannel
--- PASS: TestChannel (0.00s)
channel_test.go:56: ch1 type is chan int
channel_test.go:57: 0xc000006038
channel_test.go:58: <nil>
channel_test.go:62: ch2 type is chan int
channel_test.go:63: 0xc000006040
channel_test.go:64: 0xc0000103c0
PASS
可以看到普通方式声明的信道变量与通过 make
函数声明的信道变量在初始值上是有区别的.
使用 make
函数声明的信道变量格外分配了内存空间.
这里暂时请记住, 使用 make
函数来声明信道变量.
小白表示记住 ch := make(chan int)
问题不大.
但是有什么用嘛? 然后呢?