• go 学习之 管道


    注意事项:

     1、channel智能存放指定的数据类型

     2、channel的数据放满后不能再存放了

     3、如果从channel取出数据后可以继续存放

       4、在没有使用协程的情况下,channel数据取完了再去,报deadlock

    可以声明管道只读和只写: int <- inChan;  intChan <- int

    使用select可以解决从管道取数据的阻塞问题(不知道什么时候退出管道时使用)

    select语句包含的候选分支中的case表达式都会在该语句执行开始时先被求值,并且求值的顺序是依从代码编写的顺序从上到下的。结合上一条规则,在select语句开始执行时,排在最上边的候选分支中最左边的表达式会最先被求值,然后是它右边的表达式。仅当最上边的候选分支中的所有表达式都被求值完毕后,从上边数第二个候选分支中的表达式才会被求值,顺序同样是从左到右,然后是第三个候选分支、第四个候选分支,以此类推。

    仅当select语句中的所有case表达式都被求值完毕后,它才会开始选择候选分支。这时候,它只会挑选满足选择条件的候选分支执行。如果所有的候选分支都不满足选择条件,那么默认分支就会被执行。如果这时没有默认分支,那么select语句就会立即进入阻塞状态,直到至少有一个候选分支满足选择条件为止。一旦有一个候选分支满足选择条件,select语句(或者说它所在的 goroutine)就会被唤醒,这个候选分支就会被执行。

    对于每一个case表达式,如果其中的发送表达式或者接收表达式在被求值时,相应的操作正处于阻塞状态,那么对该case表达式的求值就是不成功的。在这种情况下,我们可以说,这个case表达式所在的候选分支是不满足选择条件的。

    仅当select语句中的所有case表达式都被求值完毕后,它才会开始选择候选分支。这时候,它只会挑选满足选择条件的候选分支执行。如果所有的候选分支都不满足选择条件,那么默认分支就会被执行。如果这时没有默认分支,那么select语句就会立即进入阻塞状态,直到至少有一个候选分支满足选择条件为止。一旦有一个候选分支满足选择条件,select语句(或者说它所在的 goroutine)就会被唤醒,这个候选分支就会被执行。

    如果select语句发现同时有多个候选分支满足选择条件,那么它就会用一种伪随机的算法在这些分支中选择一个并执行。注意,即使select语句是在被唤醒时发现的这种情况,也会这样做。

    一条select语句中只能够有一个默认分支。并且,默认分支只在无候选分支可选时才会被执行,这与它的编写位置无关。

    单向通道:

    单向通道最主要的用途就是约束其他代码的行为

    func SendInt(ch chan<- int) {
      ch <- rand.Intn(1000)
    }
    type Notifier interface {
     SendInt(ch chan<- int)
    }
    
    intChan1 := make(chan int, 3)
    SendInt(intChan1)
    

     这种约束一般会出现在接口类型声明中的某个方法定义上,尤其是在我们编写模板代码或者可扩展的程序库的时候。只需要把一个元素类型匹配的双向通道传给它就行了,没必要用发送通道,因为 Go 语言在这种情况下会自动地把双向通道转换为函数所需的单向通道

    func getIntChan() <-chan int {
      num := 5
      ch := make(chan int, num)
      for i := 0; i < num; i++ {
        ch <- i
      }
      close(ch)
      return ch
    }
    

      在另一个方面,我们还可以在函数声明的结果列表中使用单向通道

    声明写入读取

    var intChan chan int
            intChan = make(chan int, 5)
            intChan <- 5
            intChan <- 6
            intChan <- 7
            f1 := <- intChan
            f2 := <- intChan
            f3 := <- intChan
            fmt.Println(f1, f2, f3)
            fmt.Println(intChan, &intChan) 

    //存放map

            var mapChan chan map[string]string

            mapChan = make(chan map[string]string, 5)

     

            map1 := make(map[string]string, 2)

            map1["name"] = "caoxt"

            map1["age"] = "26"

            map2 := make(map[string]string, 2)

            map2["name"] = "caoxt2"

            map2["age"] = "27"

     

            mapChan <- map1

            mapChan <- map2

            f1 := <- mapChan

            f2 := <- mapChan

            f3 := <- mapChan

            fmt.Println(f1["name"], f2["age"])

    //存放结构体

      

            var perChan chan Person

            perChan = make(chan Person, 5)

            p1 := Person{"caoxt", 21}

            p2 := Person{"caoxt2", 22}

            p3 := Person{"caoxt3", 23}

     

            perChan <- p1

            perChan <- p2

            perChan <- p3

     

            f1 := <- perChan

            f2 := <- perChan

            f3 := <- perChan

            fmt.Println(f1.name, f2.age, f3.name)

    //存放指针类型

            var perChan chan *Person

            perChan = make(chan *Person, 5)

            p1 := Person{"caoxt", 31}

            p2 := Person{"caoxt2", 32}

            p3 := Person{"caoxt3", 33}

     

            perChan <- &p1

            perChan <- &p2

            perChan <- &p3

     

            f1 := <- perChan

            f2 := <- perChan

            f3 := <- perChan

            fmt.Println(f1.name, f2.age, f3.name)

  • 相关阅读:
    python增加 删除列表元素
    Fildder2
    Appscan使用第三方浏览器
    Appscan的下载安装
    http状态码
    python学习资料
    Fiddler抓包工具
    性能测试的一些资料
    Jmeter分布式测试
    内存溢出的原因及解决办法(转)
  • 原文地址:https://www.cnblogs.com/Caoxt/p/14132387.html
Copyright © 2020-2023  润新知