美文网首页
2021/4/7关于Seletc规则和单向通道

2021/4/7关于Seletc规则和单向通道

作者: 温岭夹糕 | 来源:发表于2021-04-07 16:18 被阅读0次

1.单向通道

单向通道常用于函数做函数的约束或接口

//只写通道
func Test1(ch chan<- int){
     //在函数体中无法进行读取
      ch<-1
}
//只读通道
func Test2() <-chan int {
     ch :=make(chan int,3)
     ch<-1
     close(ch)
     return ch
}


type OnlyWriteChannel interface {
    WriteChannelData(ch<- int)
}

2.Select分支规则

先执行一段demo

package main

import "fmt"

var channels = [3]chan int{
    nil,
    make(chan int),  //【1】注意这里创建了一个无缓冲通道
    nil,
}

var numbers = []int{1, 2, 3}

func main() {
    select {
    case getChan(0) <- getNumber(0):
        fmt.Println("The first candidate case is selected.")
    case getChan(1) <- getNumber(1):
        fmt.Println("The second candidate case is selected.")
    case getChan(2) <- getNumber(2):
        fmt.Println("The third candidate case is selected")
    default:
        fmt.Println("No candidate case is selected!")
    }
}

func getNumber(i int) int {
    fmt.Printf("numbers[%d]\n", i)
    return numbers[i]
}

func getChan(i int) chan int {
    fmt.Printf("channels[%d]\n", i)
    return channels[i]
}

执行结果为选择了默认分支

channels[0]
numbers[0]
channels[1]
numbers[1]
channels[2]
numbers[2]
No candidate case is selected!

作为我这个初学者来说很好奇,select不是按理来说应该返回分支2的结果吗,怎么选择了默认分支?
这要从select选择分支的规则开始说起
首先要明白:仅当select语句中的所有case表达式都被求值完毕后,它才开始选择分支
规则:

  1. select语句的每一个case表达式都会至少包含一个发送或接收操作
  2. 分支中的case表达式都会在该语句执行开始时先被求值,并且求值顺序是从上到下,从左到右。

因此不难理解 先输出channel再输出numbers

3.对于每一个case表达式,如果在被求值时相应的操作处于阻塞状态,那么对该case表达式的求值就是不成功的,即不满足选择条件

因为demo中的channel是无缓冲的,所以分支二在求值时被阻塞

4.所有表达式求值完毕,选择分支,当有多个分支满足条件即成功,就用一种伪随机的算法选择分支执行

因此不能依赖select的case顺序 来确定业务语句的执行顺序
当没有分支时就会阻塞select直到有一个满足条件

5.只能有一个默认分支

  1. 每次select执行,包含的case表达式求值 和 分支选择都是独立的

如何修改?
方法1. 去掉默认分支
方法2. 使用缓冲通道

3.select与For联用如何跳出最外层循环

利用break flag机制

package main

import (
    "fmt"
    "time"
)

func main(){
    ch :=make(chan int , 3 )
    go sleep(ch)
    myloop:
    for {
        select {
        case el :=<-ch:
            fmt.Printf("get data %d\n",el)
        case <-time.After(time.Second) :
            fmt.Println("timeout")
            break myloop;
        }
    }
}



func sleep(ch chan int){
    for {
        ch<-1
        time.Sleep(time.Second)
    }
}

本文内容及代码参考:

  1. GO核心36讲

相关文章

  • 2021/4/7关于Seletc规则和单向通道

    1.单向通道 单向通道常用于函数做函数的约束或接口 2.Select分支规则 先执行一段demo 执行结果为选择了...

  • <>

    通道的高级玩法 单向通道 单向通道是只允许写或者读的通道,定义方式如下: 通道的读写 for语句读写 select...

  • 闪电网络核心--HTLC简介

    无论是单向支付通道和RSMC双向支付通道,交易双方都需要一个建立通道和关闭通道的过程,这对于需要频繁持续进行交易支...

  • golang通道channel高级

    单向通道   only_read := make(<-chan int,1) //只能发送通道  only_w...

  • 02 塞尔曼

    2021-12-18 儿童友谊发展阶段 3-7岁:无友谊阶段 不存在友谊,知识单纯的游戏同伴。 4-9岁:单向帮助...

  • Java NIO(五):Pipe

    Pipe Pipe(管道)可用于线程之间的数据传输,它是单向的,它有一个 source 通道和 sink 通道,数...

  • Java NIO 通道(Channel)

    Java NIO 通道(Channels )与流类似但也有一些区别: 您可以读取和写入通道,流通常是单向的(读或写...

  • java nio Pipe

    Java NIO Pipe是2个线程之间的单向数据连接,Pipe有一个source通道和一个sink通道。可以将数...

  • Java NIO Pipe(管道)

    Java NIO 中的管道时两个线程之间的单向数据连接。Pipe有一个Source通道和一个Sink通道。数据会被...

  • 鉴峰丨昨晚

    [连续签到第1184天] 2021-4-7 周二 昨晚有梦 关于理想 关于生活 关于穿越世界的旅行 如今 我们相聚...

网友评论

      本文标题:2021/4/7关于Seletc规则和单向通道

      本文链接:https://www.haomeiwen.com/subject/mhsukltx.html