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)

原文地址:https://www.cnblogs.com/Caoxt/p/14132387.html