博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Go语言管道
阅读量:4669 次
发布时间:2019-06-09

本文共 2671 字,大约阅读时间需要 8 分钟。

Channel概念

Channel 是Go中的一个核心类型,你可以把它看成一个管道Channel是引用类型,操作符是箭头 <- 

Channel 是 CSP 模式的具体实现,用于多个 goroutine 通讯。其内部实现了同步,确保并发安全。

Channel 是线程安全的先进先出,多个goroutine同时访问,不需要加锁,channel是有类型的,一个整数的channel只能存放整数。

 

Channel定义

第一种,channel声明

声明int类型的chan

var ch chan int

声明string类型的chan

var ch chan string

声明map类型chan

var ch chan map[int]string

第二种,使用make定义,无缓冲channel

var ch1 chan int = make(chan int)var ch2 = make(chan int)ch3 := make(chan int)

第三种,使用make定义,有缓冲channel

var ch1 chan int = make(chan int, 10)var ch2 = make(chan int, 10)ch3 := make(chan int, 10)

第四种,只读channel

var ch1 <-chan intvar ch2 <-chan int = make(<-chan int, 10)var ch3 = make(<-chan int, 10)ch4 := make(<-chan int, 10)

第五种,只写channel

var ch1 chan<- intvar ch2 chan<- int = make(chan<- int, 10)var ch3 = make(chan<- int, 10)ch4 := make(chan<- int, 10)

Channel特点

无缓冲的与有缓冲channel有着重大差别,那就是一个是同步的 一个是非同步的。

比如

无缓冲chan:ch1:=make(chan int)

有缓冲chan:ch2:=make(chan int,1)

无缓冲: ch1<-1 不仅仅是向 c1 通道放 1,而是一直要等有别的携程 <-ch1 接手了这个参数,那么ch1<-1才会继续下去,要不然就一直阻塞着。

有缓冲: ch2<-1 则不会阻塞,因为缓冲大小是1(其实是缓冲大小为0),只有当放第二个值的时候,第一个还没被人拿走,这时候才会阻塞。

缓冲区是内部属性,并非类型构成要素。

普通 channel 可以隐式转为只读channel或只写channel。

package mainvar ch = make(chan int, 3)var send chan<- int = chvar recv <-chan int = chfunc main() {}

只读channel或只写channel不能转为普通 channel。

package mainfunc main() {    var send chan<- int    var recv <-chan int    ch1 := (chan int)(send)    ch2 := (chan int)(recv)}

编译错误:

./main.go:7:19: cannot convert send (type chan<- int) to type chan int./main.go:8:19: cannot convert recv (type <-chan int) to type chan int

Channel操作

使用内置函数 len() 返回未被读取的缓冲元素数量,使用内置函数 cap() 返回缓冲区大小。

package mainimport "fmt"func main() {    ch1 := make(chan int)    ch2 := make(chan int, 3)    ch2 <- 1    fmt.Printf("ch1 缓冲元素数量:%v,缓冲区大小:%v\n", len(ch1), cap(ch1))    fmt.Printf("ch2 缓冲元素数量:%v,缓冲区大小:%v\n", len(ch2), cap(ch2))}

运行结果:

ch1 缓冲元素数量:0,缓冲区大小:0ch2 缓冲元素数量:1,缓冲区大小:3

channel 写入、读取操作:

package mainimport "fmt"func main() {    ch := make(chan int, 1)    // 写入chan    ch <- 99    // 读取chan    value, ok := <-ch    if ok {        fmt.Printf("读取chan:%v\n", value)    }}

channel 关闭操作

1、使用内置函数 close() 进行关闭 chan。

2、chan关闭之后,for range遍历chan中已经存在的元素后结束。
3、没有使用for range的写法需要使用,val, ok := <- ch进行判断chan是否关闭。

package mainimport "fmt"func main() {    ch := make(chan int, 5)    ch <- 1    ch <- 2    ch <- 3    close(ch)    for {        val, ok := <-ch        if ok == false {            fmt.Println("chan is closed")            break        }        fmt.Println(val)    }

注意:向已经关闭的 channel 发送数据会引发 panic 错误。

package mainfunc main() {    ch := make(chan int, 1)    close(ch)    ch <- 100}

运行错误:

panic: send on closed channel

 

转载于:https://www.cnblogs.com/jiangchunsheng/p/10753371.html

你可能感兴趣的文章
github新项目挂历模式
查看>>
编写jquery插件
查看>>
敏捷开发笔记
查看>>
神秘海域:顶级工作室“顽皮狗”成长史(下)
查看>>
C++指针、引用知多少?
查看>>
services 系统服务的启动、停止、卸载
查看>>
Fiddler 网页采集抓包利器__手机app抓包
查看>>
Number and String
查看>>
java中的值传递和引用传递2<原文:http://blog.csdn.net/niuniu20008/article/details/2953785>...
查看>>
css实现背景图片模糊
查看>>
什么是runtime?什么是webgl?
查看>>
秋季学习总结
查看>>
categorical_crossentropy VS. sparse_categorical_crossentropy
查看>>
强引用,弱引用,4种Java引用浅解(涉及jvm垃圾回收)
查看>>
多线程如何确定线程数
查看>>
UGUI RectTransform
查看>>
学前班
查看>>
手把手教您扩展虚拟内存
查看>>
android-samples-mvp
查看>>
oracle 11g r2安装
查看>>