goroutine和channel是Golang之所以被称之为“天生并发”的两个核心原因。
channel是goroutine之间进行通信的一种方式。与Unix中的管道功能非常类似。
猫哥说:其实就是数据结构里面的队列嘛~ 先进先出~
channel声明:
ChannelType = ( "chan" | "chan" "<-" | "<-" "chan" ) ElementType
channel是类型相关的,换言之:一个channel只能传递一种类型。例如:
var ch chan int #ch只能传递int。
举个栗子:
package main
import "fmt"
func justequal(a int, c chan int) {
c <- a
}
func main() {
c := make(chan int)
go justequal(100,c)
go justequal(200,c)
// c <- 100 // 这样是肯定报错的!
x, y:= <-c, <-c // 从 c 中接收
fmt.Println(x,y)
}
首先,定义一个channel,整型;
其次,用goroutine开个线程给channel塞进个内容;
然后,打印出来;(其实直接 fmt.Println( <-c, <-c)也是可以的,只是看起来总觉得哪里不对劲...)
最后,因为定义是 make(chan int),所以必须走goroutine方式给赋值。后面会说为什么。
================华丽丽的分割线===================
上面例子是最简单粗暴的channel——直肠子,存不住内容。实际上的channel,还是可以有“内涵”的。当然,IT行话,这个叫“缓冲”。
重新定义有“内涵”的channel:
ch := make(chan int, 10)
LOOK~ 内涵真的可以有,有10个捏~
这样一来,操作简单多了。再来个“栗子”:
package main
import "fmt"
func main() {
c := make(chan int,10)
c <- 100
c <- 200
c <- 300
x,y,z := <-c, <-c, <-c
fmt.Println(x,y,z)
}
结果:
100 200 300
是不是很清晰?先进先出。
定义channel时候,不写缓存大小,或者缓存数写成“0”,都表示无缓存。
有没有缓冲的区别,用个生活中收快递的情况对比一下。
快递到了~
1)快递员一直等你,你不来他不走(当然你不签收,他不能继续下一单),这个是没缓存的;
2)快递员不管你在不在,把快递包裹放在传达室,人就走了,忙下一单去了,这个是有缓存。