Channels 通道 - Go 学习记录

Go Channels

基本语法和需要注意的点

  1. 语法定义
     var channel chan [type]
    • 使用 <- 传递数据
    • chan <- data 发送数据到通道,向通道中写数据
    • data <- chan 获取通道中的数据,从通道中读取数据
  2. 注意的点
    • 它是用于 goroutine 之间进行传递消息的
    • 每个 channel 都有相关联的数据类型, nil chan不能使用
    • channel 是在 goroutine 之间链接,数据接收和发送必须处于不同的 goroutine
    • 非缓冲通道发送数据和读取数据都是阻塞的,直到另一条 goroutine执行读取或写完数据才会解除阻塞
    • channel 是同步的,就意味着同一时间,只能有一条 goroutine来操作
    • 不要忘记 close(channel) 关闭通道

代码实现:

package main

import (
    "fmt"
    "strconv"
)

func main() {

    // 创建通道
    var channel chan int
    fmt.Printf("%T,%v\n", channel, channel) // chan int,<nil>
    channel = make(chan int)
    fmt.Printf("%T,%v\n", channel, channel) // chan int,0xc00008c060

    // 通道内写入数据
    go setData(channel)
    // 读取通道内的数据
    for v := range channel {
        fmt.Println("读取的数据: ", v) // 读取的数据:0,1,2,3,4
    }

    // 非缓冲通道
    var ch1 chan int
    ch1 = make(chan int)
    go func() {
        for i := 0; i < 5; i++ {
            fmt.Println("子的 goroutine 中,i", i) // 子的 goroutine 中,i 0,1,2,3,4
        }
        // 循环结束后向通道中写数据,表示结束了。
        ch1 <- 1
        fmt.Println("结束")
    }()

    data := <-ch1
    fmt.Println("main data --> ", data)

    /**
    缓冲通道(固定大小)
        接收:缓冲区数据空了会阻塞
        写入:缓冲区数据满了会阻塞
    */
    ch2 := make(chan int, 3)
    fmt.Println(len(ch2), cap(ch2)) // 0 ,3
    ch2 <- 1
    ch2 <- 2
    ch2 <- 3
    fmt.Println(len(ch2), cap(ch2)) // 3,3
    // 缓冲区满了,如果需要继续写入数据,需要有其他的 goroutine 进行读取(队列的结构来读取)
    // ch2 <- 4
    ch3 := make(chan string, 3)
    fmt.Println(len(ch3), cap(ch3)) // 0 ,3
    go setStringData(ch3, 3)
    for {
        v, ok := <-ch3
        if !ok {
            fmt.Println("读取完毕", ok) // 读取完毕 false
            break
        }
        fmt.Println("读取的数据是:", v) // 读取的数据是: 0,1,2
    }

    /**
    双向通道
        chan ch
            chan <- data 写入数据
            data <- chan 读取数据
    */
    ch4 := make(chan string)
    isDone := make(chan bool)
    go SendString(ch4, isDone)
    data1 := <-ch4        // 读取
    fmt.Println(data1)    // golang
    ch4 <- "learn golang" // 发送

    <-isDone // 判断这个来看主程序结束

    /**
    单向通道:定向
        chan <- Write 只支持写
        <- chan Read 只能读
    */
    singleChanWrite := make(chan<- int) // 只能写,不能读
    singleChanRead := make(<-chan int)  // 只能读,不能写

    fmt.Println("main over")
}

func setData(ch chan int) {
    for i := 0; i < 5; i++ {
        ch <- i
    }
    close(ch) // 通知对方,通道关闭
}

func setStringData(ch chan string, number int) {
    for i := 0; i < number; i++ {
        ch <- strconv.Itoa(i)
    }
    close(ch) // 通知对方,通道关闭
}

func SendString(ch chan string, isDone chan bool) {
    ch <- "golang"                            // 发送
    data2 := <-ch                             // 读取数据
    fmt.Println("main goroutine 传来: ", data2) // main goroutine 传来:   learn golang

    isDone <- true // 限制主程序过快的结束执行
}

*/

如想看学习记录同步的练习代码移步 GitHub

本作品采用《CC 协议》,转载必须注明作者和本文链接
微信搜索:上帝喜爱笨人
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!