1、channel的声明形式:

var ch chan int
ch := make(chan int)

2、channel的写入与读取:

// 将一个数据value写入至channel,这会导致阻塞,直到有其他goroutine从这个channel中读取数据

ch <- value

// 从channel中读取数据,如果channel之前没有写入数据,也会导致阻塞,直到channel中被写入数据为止

value := <-ch

3、带缓冲的channel:

c := make(chan int, 1024)

// 从带缓冲的channel中读数据

for i:=range c {

...

}

此时,创建一个大小为1024的int类型的channel,即使没有读取方,写入方也可以一直往channel里写入,在缓冲区被填完之前都不会阻塞。

示例:

func Count(ch chan int) {
   ch <- 1
    fmt.Println("Counting")
 }
 
 func main() {
 
     chs := make([] chan int, 10)
 
    for i:=0; i<10; i++ {
        chs[i] = make(chan int)
        go Count(chs[i])
    }

    for _, ch := range(chs) {
        <-ch
    }
}

在这个例子中,定义了一个包含10个channel的数组,并把数组中的每个channel分配给10个不同的goroutine。在每个goroutine完成后,向goroutine写入一个数据,在这个channel被读取前,这个操作是阻塞的。在所有的goroutine启动完成后,依次从10个channel中读取数据,在对应的channel写入数据前,这个操作也是阻塞的。这样,就用channel实现了类似锁的功能,并保证了所有goroutine完成后main()才返回。

4、单向channel:

Go中channel可以是只读、只写、同时可读写的。

//定义只读的channel

read_only := make (<-chan int)

//定义只写的channel

write_only := make (chan<- int)

//可同时读写

read_write := make (chan int)

定义只读和只写的channel意义不大,一般用于在参数传递中,见示例:

package main

import (
    "fmt"
    "time"
)

func main() {
    c := make(chan int)
    go send(c)
    go recv(c)
    time.Sleep(3 * time.Second)
}
//只能向chan里写数据
func send(c chan<- int) {
    for i := 0; i < 10; i++ {
        c <- i
    }
}
//只能取channel中的数据
func recv(c <-chan int) {
    for i := range c {
        fmt.Println(i)
    }
}