go chan
一、设计原理
go中最常提及的就是通过通信的方式共享内存,而不要通过共享内存的方式通信。通常对于并发控制共享变量时,都会采用加锁的手段,但是对于go 而言设计了一种不同的并发模型,通信顺序进程,csp。Goroutine 和 Channel 分别对应 CSP 中的实体和传递信息的媒介,Goroutine 之间会通过 Channel 传递数据。
二、创建chan
//无缓冲的chan
func main() {
ch := make(chan int)
go func () {
v := <- ch
fmt.Println("receive data", v)
}()
ch <- 5
fmt.Println("send :", 5)
time.Sleep(1 * time.Second)
}
//读写对称 写阻塞 同步chan
//下面这种方式会提示
func main() {
ch := make(chan int)
ch <- 5
fmt.Println("send :", 5)
go func () {
v := <- ch
fmt.Println("receive data", v)
}()
time.Sleep(1 * time.Second)
}
//fatal error: all goroutines are asleep - deadlock!
//带缓冲的chan 异步chan
func main() {
ch := make(chan int,1)
ch <- 5
fmt.Println("send ", v)
go func() {
v := <-ch
fmt.Println("receive data", v)
}()
}
三、go并发实现
3.1 for rang 使用for rang 最后一定要关闭chan ,如果chan 不关闭,for range 循环无法结束。
func main() {
ch := make(chan int, 1)
defer close(ch)
go func() {
for i := 1; i <= 10; i++ {
ch <- i
fmt.Println("send ", i)
}
}()
go func() {
for v := range ch {
fmt.Println("recv ", v)
}
}()
time.Sleep(1 * time.Second)
}
3.2 使用select 模型
func main() {
ch := make(chan int, 1)
go func() {
for i := 1; i <= 10; i++ {
ch <- i
fmt.Println("send ", i)
}
}()
go func() {
flag := true
for flag {
select {
case v, ok := <-ch:
if !ok {
flag = false
break
}
if ok {
fmt.Println("recv ", v)
}
}
}
}()
time.Sleep(1 * time.Second)
}