go channel 基本解释(超简单)

channel的类型

我不认为是否有缓冲区可以作为 channel 分类的依据,所谓的无缓冲的channel,就是容量为0 的channel

//所谓无缓冲的channel 
c:= make(chan int) //等价于 c:= make(chan int,0) 

//创建有缓冲的channel
c:= make(chan int,3)

真正的类型划分为三种:

//对列类型chan 可存可取 先进先出
var queneChan chan int
//只存类型chan 只存不取
var inChan  chan<- int
//只取类型chan 只取不存
var outChan <-chan int

channel 操作引起阻塞的情况

简单来说就两句话

存而不进

容量为0 肯定存不进

//无缓冲
package main

func main() {

	c := make(chan int, 0)

	c <- 1

}


//fatal error: all goroutines are asleep - deadlock!

增加容量即可

package main

func main() {
	
	c := make(chan int, 1)
	c <- 1
	
}


// Process finished with the exit code 0

取而不得

与上面同理,通道中没有数据的时候,取数据,肯定取不到

package main

func main() {

	c := make(chan int, 0)
	<-c

}

//fatal error: all goroutines are asleep - deadlock!

有容量没数据一样取不到

package main

func main() {

	c := make(chan int, 1)
	<-c

}
//fatal error: all goroutines are asleep - deadlock!

有数据能取,则不会阻塞

package main

import "fmt"

func main() {

	c := make(chan int, 1)
	c <- 100
	fmt.Println(<-c)

}

// 100
// Process finished with the exit code 0

操作channel 的内置函数

make()

make为引用类型初始化内存空间,用户 slice、map 、chan

他们三个的共同点是他们都是引用类型的,且都需要分配容量

package main

import "fmt"

func main() {

	var c = make(chan int)
	var c1 chan int
	fmt.Println("c:", c, "c1:", c1)

}
//c: 0xc000086120 c1: <nil>

len() & cap()

len() 返回引用类型变量中数据的个数
cap() 返回引用类型变量的容量的大小

数据的个数≤ 容量

package main

import "fmt"

func main() {

	var c = make(chan int, 3)
	fmt.Println("初始:")
	fmt.Printf("len(c)=%d cap(c)=%d\n", len(c), cap(c))
	c <- 1
	c <- 2
	fmt.Println("存了两个以后:")
	fmt.Printf("len(c)=%d cap(c)=%d\n", len(c), cap(c))
	<-c
	fmt.Println("取出一个以后:")
	fmt.Printf("len(c)=%d cap(c)=%d\n", len(c), cap(c))

}
初始:
len(c)=0 cap(c)=3
存了两个以后:   
len(c)=2 cap(c)=3
取出一个以后:   
len(c)=1 cap(c)=3

Process finished with the exit code 0

可以发现len()随存取数据变化,而cap 一直没有变化

close() --重要

先来看官方定义

// The close built-in function closes a channel, which must be either
// bidirectional or send-only. It should be executed only by the sender,
// never the receiver, and has the effect of shutting down the channel after
// the last sent value is received. After the last value has been received
// from a closed channel c, any receive from c will succeed without
// blocking, returning the zero value for the channel element. The form
//
//	x, ok := <-c
//
// will also set ok to false for a closed and empty channel.
func close(c chan<- Type)

注意看close 方法参数接受的类型 chan<- 说明可以接受的类型是chan<- 和 chan
注: chan、chan<- 、<-chan 三种类型的关系是 chan = <-chan ∩ chan<-, (∩–交集)

所以close()只能影响可以存数据的channel

1、影响 chan<- (只存channel)

被关闭的channel,不能存数据

package main

func main() {

	c := make(chan<- int, 10)
	close(c)
	c <- 20

}

//panic: send on closed channel

2、影响 chan (只取channel)

刚才说了对 存的影响 ,现在来看取的影响:

从已关闭的channel中取数据不会引起阻塞,与chaneel 的容量,channel中有无数据都没有关系

x,ok := <-c

如果c中有数据 x 是正常取得的数据,ok 是 true
如过c中没有数据 x 是对应类型的零值,ok 是 false

package main

import "fmt"

func main() {

	//无容量
	c := make(chan int)
	close(c)
	v, ok := <-c
	fmt.Println(v, ok) //0,false

	//有容量
	c1 := make(chan int, 10)
	c1 <- 20
	c1 <- 10
	close(c1)
	for v1, ok1 := <-c1; ok1; v1, ok1 = <-c1 {
		fmt.Println(v1, ok1)
	}

    //20,true
    //10,true
}

形如 x,ok := <-c 何时返回false 官方的解释是:

The form

x, ok := <-c

will also set ok to false for a closed and empty channel.

意思是ok 为false 的条件是:被关闭的channel& 空的channel(缓冲区中无数据),二者缺一不可

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值