当前位置: 首页 > news >正文

网站建设分析泽库县wap网站建设公司

网站建设分析,泽库县wap网站建设公司,wordpress商品按钮代码,临沂网站建设优化目录 Golang 并发 Channel的用法1. channel 的创建2. nil channel读写阻塞示例close示例 3. channel 的读写4. channel 只读只写5. 关闭channelchannel关闭后#xff0c;剩余的数据能否取到读取关闭的channel#xff0c;将获取零值使用ok判断#xff0c;是否关闭使用for-ran… 目录 Golang 并发 Channel的用法1. channel 的创建2. nil channel读写阻塞示例close示例 3. channel 的读写4. channel 只读只写5. 关闭channelchannel关闭后剩余的数据能否取到读取关闭的channel将获取零值使用ok判断是否关闭使用for-range退出使用close(ch)关闭所有下游协程 6. 当函数传递channel时是传递的引用还是值参考 Golang 并发 Channel的用法 1. channel 的创建 ch : make(chan int)上面是创建了无缓冲的 channel一旦有 goroutine 往 channel 发送数据那么当前的 goroutine 会被阻塞住直到有其他的 goroutine 消费了 channel 里的数据才能继续运行。 ch : make(chan int, 2)上面示例中的第二个参数表示 channel 可缓冲数据的容量。只要当前 channel 里的元素总数不大于这个可缓冲容量则当前的 goroutine 就不会被阻塞住。 2. nil channel nil是pointers, interfaces, maps, slices, channels 和 function 类型的零值,表示未初始化值。nil不是未定义状态它本身就是值。error是接口类型因此error变量可以为nil但string不能为nil。 下面我们看下nil 通道有什么特点空通道对操作的反应如下 从空通道读、写会永远阻塞关闭通道会终止程序(panic) 空通道是一种特殊通道总是阻塞。对比非空已关闭的通道仍然可以进行读取并能够读取对应类型的零值但对于已关闭的通道发送信息会终止程序。 一般 nil channel 用在 select 上让 select 不再从这个 channel 里读取数据 读写阻塞示例 示例如下 func TestNil(t *testing.T) {c : make(chan int)go sendIntegers(c)addIntegers(c) }func addIntegers(c chan int) {sum : 0t : time.NewTimer(time.Second * 5)for {select {case input : -c:sum sum inputfmt.Println(addIntegers , input : strconv.Itoa(input) , sum : strconv.Itoa(sum))case -t.C:c nilfmt.Println(addIntegers , nil channel , sum : strconv.Itoa(sum))}} }func sendIntegers(c chan int) {for {time.Sleep(time.Second * 1)c - rand.Intn(100)} } 输出如下 RUN TestNil addIntegers , input : 81 , sum : 81 addIntegers , input : 87 , sum : 168 addIntegers , input : 47 , sum : 215 addIntegers , input : 59 , sum : 274 addIntegers , nil channel , sum : 274 panic: test timed out after 30s此示例会一直阻塞下去addIntegers是程序的主协程会一直阻塞下去sendIntegers是子协程同样会一直阻塞下去。 其中输出中的panic是单元测试的Test引发的异常不需要考虑在内。 close示例 func TestCloseNil(t *testing.T) {c : make(chan int)go writeChannel(c)num : -cfmt.Println(main goroutine , read num : strconv.Itoa(num))c nilfmt.Println(main goroutine , to close channel .)close(c)time.Sleep(time.Second * 10)}func writeChannel(c chan int) {fmt.Println(writeChannel goroutine , running ...)c - 1 }输出如下 RUN TestCloseNil writeChannel goroutine , running ... main goroutine , read num : 1 main goroutine , to close channel . --- FAIL: TestCloseNil (0.00s) panic: close of nil channel [recovered]panic: close of nil channel关闭nil通道会引起程序panic 3. channel 的读写 写操作 ch : make(chan int) ch - 1读操作 data - ch当我们不再使用 channel 的时候可以对其进行关闭 close(ch)如果 channel 关闭继续读取关闭后的 channel不会产生 pannic还是可以读到数据将得到零值即对应类型的默认值。 为了能知道当前 channel 是否被关闭可以使用下面的写法来判断。 当channel关闭时ok false当channel未关闭时ok true if v, ok : -ch; !ok {fmt.Println(channel 已关闭读取不到数据)}另一种写法可以使用 for-range 使用下面的写法不断的获取 channel 里的数据直到channel关闭跳出循环执行后面的代码。 for data : range ch {// get data dosomething}4. channel 只读只写 在默认情况下管道是双向的可读可写在使用 channel 时我们还可以控制 channel 只读只写操作 声明为只写如下 var chan2 chan- int chan2 make(chan int, 3) chan2 - 20如果试着读此chan则编译报错编译错误如下 invalid operation: cannot receive from send-only channel chan2 (variable of type chan- int) compiler (InvalidReceive)声明为只读不可写否则编译报错如下 var chan3 -chan int nm2 : -chan3函数可以声明chan只读只写代码示例 // 只写操作 func send(ch chan- int, exitChan chan struct{}) {for i : 0; i 5; i {time.Sleep(time.Second * 1)ch - i}close(ch)var a struct{}exitChan - a }// 只读操作 func recv(ch -chan int, exitChan chan struct{}) {for {v, ok : -chif !ok {break}fmt.Println(recv goroutine , value : strconv.Itoa(v))}var a struct{}exitChan - a } func TestOnlyReadWrite(t *testing.T) {ch : make(chan int, 10)exitChan : make(chan struct{}, 2)go send(ch, exitChan)go recv(ch, exitChan)var total 0for _ range exitChan {totalif total 2 {break}}fmt.Println(main goroutine , 结束) }输出如下 RUN TestOnlyReadWrite recv goroutine , value : 0 recv goroutine , value : 1 recv goroutine , value : 2 recv goroutine , value : 3 recv goroutine , value : 4 main goroutine , 结束 --- PASS: TestOnlyReadWrite (5.03s)5. 关闭channel channel关闭后剩余的数据能否取到 golang channel关闭后其中剩余的数据是可以继续读取的channel关闭之后仍然可以从channel中读取剩余的数据直到数据全部读取完成。 对于关闭的channel的读写需要注意两点 如果继续向channel发送数据会引起panic如果继续读数据得到的是零值(对于int就是0)。 读取关闭的channel将获取零值 当读取已关闭的channel时如果继续读取channel获取到的是零值不会堵塞 另外即使是无缓冲的channel也将能一直获取到零值。 代码示例如下 func TestCloseDemo01(t *testing.T) {done : make(chan struct{})ch : make(chan int, 3)ch - 1ch - 2ch - 3close(ch)go func() {for {value : -ch//此处为假设判断value永远不会等于10if value 10 {break}fmt.Println(read channel , value : , value)time.Sleep(time.Second * 1)}done - struct{}{}}()select {case -done:fmt.Println(读取channel正常结束)case -time.After(time.Second * 5):fmt.Println(超时退出)} } 输出如下 RUN TestCloseDemo01 read channel , value : 1 read channel , value : 2 read channel , value : 3 read channel , value : 0 read channel , value : 0 超时退出 --- PASS: TestCloseDemo01 (5.00s)使用ok判断是否关闭 读取channel判断是否关闭 value, ok : -ch当channel关闭时okfalse当channel未关闭时oktrue 通过判断channel是否关闭当channel关闭时程序可以正常退出代码示例如下 func TestCloseDemo02(t *testing.T) {done : make(chan struct{})ch : make(chan int, 3)ch - 1ch - 2ch - 3close(ch)go func() {for {value, ok : -chif !ok {break}fmt.Println(read channel , value : , value)time.Sleep(time.Second * 1)}done - struct{}{}}()select {case -done:fmt.Println(读取channel正常结束)case -time.After(time.Second * 5):fmt.Println(超时退出)} }输出如下 RUN TestCloseDemo02 read channel , value : 1 read channel , value : 2 read channel , value : 3 读取channel正常结束 --- PASS: TestCloseDemo02 (3.03s) PASS使用for-range退出 for-range是使用频率很高的结构常用它来遍历数据range能够感知channel的关闭当channel被发送数据的协程关闭时range就会结束接着退出for循环。 它在并发中的使用场景是当协程只从1个channel读取数据然后进行处理处理后协程退出。 下面这个示例程序当通道被关闭时协程可自动退出。 func TestCloseDemo02(t *testing.T) {ch : make(chan int, 3)ch - 1ch - 2ch - 3close(ch)for v : range ch {fmt.Println(value, v)}time.Sleep(time.Second * 10) }使用close(ch)关闭所有下游协程 关闭通道可以主动通知所有协程退出的场景 当启动100个worker时只要main()执行关闭stopCh每一个worker都会都到信号进而关闭。如果main()向stopCh发送100个数据这种就低效了。 //close关闭所有子协程 func TestCloseDemo04(t *testing.T) {ch : make(chan int, 3)stopCh : make(chan struct{})for i : 1; i 6; i {worker(workerstrconv.Itoa(i), stopCh, ch)}time.Sleep(time.Second * 5)close(stopCh)time.Sleep(time.Second * 5) }func worker(workerName string, stopCh -chan struct{}, ch -chan int) {go func() {defer fmt.Println(workerName, goroutine , worker exit)// Using stop channel explicit exitfor {select {case -stopCh:fmt.Println(workerName, goroutine , Recv stop signal , return)returndefault:fmt.Println(workerName, goroutine , worker default ...)}time.Sleep(time.Second * 3)}}() }输出如下 RUN TestCloseDemo04 worker5 goroutine , worker default ... worker3 goroutine , worker default ... worker4 goroutine , worker default ... worker1 goroutine , worker default ... worker2 goroutine , worker default ... worker3 goroutine , worker default ... worker2 goroutine , worker default ... worker5 goroutine , worker default ... worker4 goroutine , worker default ... worker1 goroutine , worker default ... worker4 goroutine , Recv stop signal , return worker4 goroutine , worker exit worker2 goroutine , Recv stop signal , return worker2 goroutine , worker exit worker5 goroutine , Recv stop signal , return worker5 goroutine , worker exit worker1 goroutine , Recv stop signal , return worker1 goroutine , worker exit worker3 goroutine , Recv stop signal , return worker3 goroutine , worker exit --- PASS: TestCloseDemo04 (10.01s) PASS6. 当函数传递channel时是传递的引用还是值 golang 传递给函数chan类型时是值传递和引用传递 golang默认都是采用值传递即拷贝传递有些值天生就是指针slice、map、channel 可以看出来map和slice都是指针传递即函数内部是可以改变参数的值的。而array是数组传递不管函数内部如何改变参数都是改变的拷贝值并未对原值进行处理。 在 Go 语言中所有的函数参数传递都是值传递pass by value当将参数传递给函数时实际上是将参数的副本传递给函数。然而这并不意味着在函数内部对参数的修改都不会影响原始数据。因为在 Go 中有些数据类型本身就是引用类型比如切片slice、映射map、通道channel、接口interface和指针pointer。当这些类型作为参数传递给函数时虽然传递的是值但值本身就是一个引用。 小结 Go 语言中的参数传递总是值传递意味着传递的总是变量的副本无论是基本数据类型还是复合数据类型。由于复合数据类型如切片、映射、通道、接口和指针内部包含的是对数据的引用所以在函数内部对这些参数的修改可能会影响到原始数据。理解这一点对于编写正确和高效的Go代码至关重要。 另外即使是引用类型比如切片当长度或容量比如使用 append 函数发生变化了可能会导致分配新的底层数组。这种情况下原始切片不会指向新的数组但是函数内部的切片会。因此如果想在函数内部修改切片的长度或容量并反映到外部应该传递一个指向切片的指针。 参考 https://www.cnblogs.com/-wenli/p/12350181.htmlhttps://segmentfault.com/a/1190000017958702https://zhuanlan.zhihu.com/p/395278270https://zhuanlan.zhihu.com/p/613771870Go里面如何实现广播 https://juejin.cn/post/6844903857395335182
http://www.hkea.cn/news/14486041/

相关文章:

  • 织梦网站栏目调用济南市住房建设网站
  • 一个网站怎么做pc和移动端网页内容
  • 动态交互图网站做国外零售做什么网站
  • 建立网站该怎样做2016网站建设总结
  • 网站建设制作细节大型网站的标准
  • 常营网站建设凡科做的网站如何绑定域名
  • 黑龙江做网站的公司有哪些后台做网站的题
  • 中江网站建设深圳网站设计 三把火科技
  • 网站策划书基本项目自己做淘宝客登录网站
  • seo网站优化对象wordpress插件免费
  • 计算机网站建设论文总结淘宝客网站如何做推广方案
  • 一些建筑设计网站wordpress前台发文积分
  • 南京电商网站开发网络策划营销方案
  • 做社交网站要注册哪类商标临邑网页设计
  • 郑州专业的网站建设服务专业建设
  • 增加网站点击量网站开发亿玛酷给力5
  • 屏蔽右键网站百度收录量
  • 小牛门户网站网页设计实训报告格式
  • 太原网站建设方案服务代理网址上网
  • 多少钱网站设计长沙有什么好玩的
  • 苏州大学网站建设目标养老网站建设方案
  • 四川省建设监理协会网站如何建立一个自己的网址
  • 国外游戏代码网站中山网站建设解决方案
  • 建设银行网站怎么短信转账江苏建设集团公司官网
  • 网站更换空间教程7网站建设1
  • 郑州代理记账网站建设山东住房城乡建设厅网站
  • 自主建设网站的意义中国建设网站
  • 个人网站模板h5湖北建站
  • 网站手册永久免费自助建站源代码
  • 携程做旅游的网站可以免费发广告的网站有哪些