channel
时间:2019-08-17
本文章向大家介绍channel,主要包括channel使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
channel
Go语言在语言级别提供的goroutine间的通信方式,让他们之间可以进行数据交互。
声明方式:
var chanName chan ElementType
// 如:
var ch1 chan int
// 也可以使用make函数创建
ch2 := make(chan string)
上面创建了两个channel,ch1只能用来存储int类型的数据,ch2只能用来存储string类型的数据。
channel的写与读
channel的写与读也非常简单,使用<-
符号实现,<-
在channel变量名右边表示写入值,<-
在左边表示读取值。
如:
ch := make(chan int)
ch <- 10 // 向ch中写入10
res := <-ch // 读取ch中的值并赋值给res
案例:
package main
import (
"fmt"
"time"
"strconv"
)
func Read(ch chan int){
for {
value := <-ch
fmt.Println("value:" + strconv.Itoa(value))
}
}
func Write(ch chan int){
ch <- 10
}
func main(){
ch := make(chan int)
go Read(ch)
go Write(ch)
time.Sleep(10)
}
输出:
value:10
上面的代码中分别有两个函数,函数Read用来从channel中读取值,函数Write用来往channel里面写值,注意value := <-ch
在读取值时可能存在channel中无数据存在的情况,如果没有数据可读就会阻塞,直到从channel中读取到数据。因为会不断从channel中读取可能存在的数据,所以一般都会使用一个死循环来读取channel数据,避免写入channel中的数据会丢失。
channel的操作
channel都有3中操作:send、receive和close
- send:表示向channel中投放数据
- receive:表示从channel中读取数据
- close:表示关闭channel
注意:
- 关闭channel后,send操作将导致painc(抛出异常)。
- 关闭channle后,receive操作将返回对应类型的0值以及一个状态码false。
- close并非强制需要使用,在某些时候可以自动被关闭。
- 如果使用了close(). 建议条件允许的情况下加上defer
- 只在send端上显式使用close()关闭channel。因为关闭通道意味着没有数据需要发送。
案例,判断channel是否被关闭:
val, ok := <-ch
if ok{
fmt.Println(val)
}
缓冲channel
在对channel写入数据后,如果没有读取的操作,程序就会阻塞着不运行,这个时候我们想要程序不阻塞,就可以设置一个缓冲区大小,如果写入值数量超过缓冲区大小时再进行阻塞,声明channel时,可以再跟一个参数,代表缓冲区大小。
声明,如:
c := make(chan int, n) // n代表缓冲区大小
c := make(chan int) // 没写参数,代表0 等价于c := make(chan int, 0)
案例:
func test(ch chan int){
ch <- 10
fmt.Println("come to goroutine")
}
func main(){
ch := make(chan int)
go test(ch)
time.Sleep(time.Second * 3)
fmt.Println("runing end")
}
输出结果为:
runing end
因为创建的channel没有设置缓冲区大小,而且在写入值之后也没有读取值的操作,所以程序阻塞,没有打印"come to goroutine"。
修改缓冲区大小,如:
func test(ch chan int){
ch <- 10
fmt.Println("come to goroutine")
}
func main(){
ch := make(chan int,1)
go test(ch)
time.Sleep(time.Second * 3)
fmt.Println("runing end")
}
输出结果为:
come to goroutine
runing end
原文地址:https://www.cnblogs.com/louyefeng/p/11367766.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 在VS2010里快要疯掉的hello world
- gh0st源码分析与远控的编写(三)
- Android自定义View实现五星好评效果
- Android通过ViewModel保存数据实现多页面的数据共享功能
- Android自定义View实现炫酷进度条
- OpenSSL的VC编程 - MD5
- 详解AndroidStudio中代码重构菜单Refactor功能
- Android自定义View仿QQ运动步数效果
- Kotlin类型安全构建器的一次运用记录
- 两个surfaceView实现切换效果
- AndroidStudio4.0 New Class的坑(小结)
- Android日历控件的实现方法
- GetDiskFreeSpaceEx函数的一点处理
- Flutter轮播图效果的实现步骤
- Android自定义View实现五子棋游戏