channel一篇全搞定

什么是channel

channel是一个数据管道,可以往里面写数据,可以从里面读数据,channel是goroutine之间数据通信的桥梁,而且是线程安全的,channel遵循先进先出的原则,写入数据和读出数据都会加锁。

channel的分类

从读写的角度来区分

  • 只读channel,单向channel
  • 只写channel,单向channel
  • 可读可写channel

从是否带有缓冲区来区分

  • 带缓冲区的channel,定义了缓冲区的大小,可以存储多个数据
  • 不带缓冲区的channel,只能存一个数据,并且只有当该数据被取出的时候才能存下一个数据
channel定义和声明

channel 按照声明和定义的方式可以从读写的方式上划分为只读的channel、只写的channel、可读可写的channel; 从带不带缓存区的角度又可以划分为带缓存区的channel和不带缓存区的channel。

readOnlyChan := make(<- chan int)
writeOnlyChan := make(chan <- int)
readAndWriteChan := make(chan int)


readOnlyChan := make(<- chan int,1)
writeOnlyChan := make(chan <- int,1)
readAndWriteChan := make(chan int,1)
对channel的操作方式

针对channel的操作有下面的几种方式,从channel 中读取数据、将数据写入channel、关闭channel

  • 实践一
    ch := make(chan int)
    go func() {
        ch <- 10
    }()
    fmt.Println(<-ch)
  • 实践二
{
	ch := make(chan int)
	go store(ch)
	for i := 0; i < 10; i++ {
		fmt.Println("received ", <-ch)
	}
}

func store(ch chan int) {
	for i := 0; i < 10; i++ {
		fmt.Println("send ", i)
		ch <- i
	}
}
  • 实践三
// 带缓存的channel
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
fmt.Println(<-ch)
fmt.Println(<-ch)
fmt.Println(<-ch)

实践四

{
	s := []int{1, 2, 4, 5, 9}
	ch := make(chan int)
	go sums(s[:len(s)/2], ch)
	go sums(s[len(s)/2:], ch)
	x, y := <-ch, <-ch
	fmt.Println(x, y, x+y)
}

func sums(s []int, c chan int) {
	sum := 0
	for _, v := range s {
		sum += v
	}
	c <- sum
}
判断channel是否关闭

判断一个channel是否关闭的语法如下:如果ok为true则能够读到数据,说明channel没有关闭;如果ok为false,说明不能够读到数据,channel已关闭。

v, ok := <- ch

实践一

{
	ch := make(chan int)
	go test(ch)

	for {
		if v, ok := <-ch; ok {
			fmt.Println("get value: ", v)
		} else {
			break
		}
	}
}

func test(ch chan int) {
	for i := 0; i < 5; i++ {
		ch <- i
	}
	close(ch)
}
channel超时处理

channel 可以结合time实现超时处理功能,当从channel中读取数据超过一定的时间的时候如果还没有数据到来,那么就可以认为当前的读取操作已经超时,防止goroutine一直处于阻塞状态。

// 读取ch中的数据,然后一直等待,直到超时后推出

{
    ch := make(chan int)
	quit := make(chan bool)
	go func() {
		for {
			select {
			case v := <-ch:
				fmt.Println(v)
			case <-time.After(time.Second * 3):
				quit <- true
				fmt.Println("timeout send notice")
				return
			}
		}
	}()

	for i := 0; i < 4; i++ {
		ch <- i
	}

	<-quit
	fmt.Println("main exit")
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值