文章摘要
本文介绍了Go语言中通道(channel)的基本概念及其在多线程通信中的应用。通道是一种机制,允许在goroutine之间通过管道共享数据。其语法简单,使用`make(chan 数据类型)`创建通道,并通过`值 <- 通道`发送数据,`<- 通道`接收数据(阻塞或非阻塞)。文章还通过倒数示例展示了通道的实际使用场景。与Java中的线程安全机制不同,通道更类似于队列,提供了同步数据交换的机制。掌握通道可以显著提升Go程序的并发能力。
目录前言通道如何创建通道向通道发送数据从通道接收数据通道的例子
在Java中,多线程之间的通信方式有哪些?记得吗?Java多线程间通信的解决方案有很多种,比如:synchronized。使用锁来防止资源乱来,一人一个按顺序来,要么使用JDK提供的原子对象,那些Atomic关键字开头的对象,比如:AtomicInteger,这样可以在多个线程中读写值的时候保证是安全的,还有很多其他的方式,在go中,就一种:通道
go的通道我根据java的理解,它就是用来解决线程之间通信的东西,go里面的关键字叫channels
以下是搜索出来的解释:
go语言提倡使用通信的方法代替共享内存,当一个资源需要在 goroutine 之间共享时,通道在 goroutine 之间架起了一个管道,并提供了确保同步交换数据的机制。声明通道时,需要指定将要被共享的数据的类型。可以通过通道共享内置类型、命名类型、结构类型和引用类型的值或者指针。这里通信的方法就是使用通道(channel),如下图所示:

图:goroutine 与 channel 的通信
是不是和java的线程安全对象是类似?或者说是队列?总之你可以按照你自己经验去理解。
go提供了创建通道的语法:
通道变量名 :=make(chan 数据类型)
比如,我们可以这样写:
// 创建一个int型的通道
ch1 :=make(chan int)
还可以创建一个接口类型通道,比如:
ch2 :=make(chan interface{})
还能创建一个结构体的通道,比如:
// 创建一个User结构体的通道,这个通道是个指针通道
ch3 :=make(chan *User)
go向通道发送数据语法非常简单:
通道变量名 <- 值
我们向上面三个通道名发送数据,可以写成:
// 1. 给ch1通道传值0
ch1 <- 0
// 2. 给ch2通道传字符串,实际可以穿任意对象,因为前面声明了是interface对象
ch2 <- “hello, mars酱”
// 创建一个userInfo结构体并初始化值
userInfo :=User{
1, “mars酱”,
}
// 3. 发送一个结构体到通道ch3中
ch3 <- &userInfo
以上代码是无法运行的,因为go的通道有个规矩,发送和接收必须成对出现,不信邪的可以验证一下。
go从通道中接收数据的语法也简单:
data :=<- ch1
这个语句是个阻塞语句,只有当data接收到了值,才会执行后续的,非阻塞的这样写:
data, ok :=<- ch1
:接收的数据,如果没有接收到,data为0。data为0取决于之前make通道的时候,ch1是个int型通道,如果是其他类型,这个data也应该是其他类型对象;
:boolean类型的值,表示是否接收到数据
还有个奇葩的写法:
<- ch1
这样写就表示通道里有啥都与我无关,忽略掉了。
一个倒数的例子,通过通道去实现一下:
// author: mars酱
func Test_chanTest(t *testing.T) {
// 1. 创建一个通道
ch1 :=make(chan int)
// 2. 启动goroutine并发
go func() {
// 从5 到 0
for i :=5; i >=0; i– {
// 3. 发送给通道
ch1 <- i
// 发完后等1秒
time.Sleep(time.Second)
}
}()
// 4. 循环接收通道数据
for data :=range ch1 {
fmt.Println(data)
if data==0 {
break
}
}
}
运行的结果:

发射火箭的倒数计时就是这样吧~
以上就是一文带你掌握Golang基础之通道的详细内容,更多关于Golang通道的资料请关注脚本之家其它相关文章!
您可能感兴趣的文章:超实用的Golang通道指南之轻松实现并发编程浅谈golang通道类型Golang 并发以及通道的使用方式Golang实现Directional Channel(定向通道)Golang通道的无阻塞读写的方法示例