golang学习笔记26-管道(Channel)【重要】

本节也是GO核心部分,很重要。
注意:Channel更准确的翻译应该是通道,管道实际上叫Pipeline。当然,在GO中,管道专指Channel。
管道本质上是一个队列,队列是数据结构的内容,这里不做赘述。管道对协程的主要作用是提供安全性:因其先进先出的特性,保证了多个协程操作同一个管道时,不会发生资源抢夺问题。
管道的语法是:var 变量名 chan 管道存放的数据类型。管道是引用类型,且和map一样,必须初始化才能写入数据,即make后才能使用。

目录

    • 一、读写数据
    • 二、管道的关闭
    • 三、管道的遍历
    • 四、协程和管道协同工作
    • 五、管道的声明
    • 六、select

一、读写数据

管道用<-取(读)数据,存(写)数据,注意,这里的”读“是取出数据,”写“是存入数据,这都会导致管道长度(不是容量)改变!在没有使用协程的情况下,若没有定义管道长度(定义了管道长度的叫缓冲管道),即空管道,这时就取数据,或满管道时放数据,则go都会报错:fatal error: all goroutines are asleep - deadlock!。这里提到了死锁,也是操作系统的概念。
例:

package main

import (
	"fmt"
)

func main() {
   
	// 定义一个容量为3的管道作为缓冲,避免阻塞
	ch := make(chan int, 3)

	// 存入数据
	ch <- 1
	ch <- 2
	ch <- 3
	fmt.Printf("存入数据后:长度 = %d, 容量 = %d\n", len(ch), cap(ch))

	// 再次存入数据,由于管道已满,这一行会阻塞程序,除非有数据被取出
	// ch <- 4 // 取消注释这一行将会导致阻塞,go会报错

	// 取出数据
	fmt.Printf("取出数据:%d\n", <-ch)
	fmt.Printf("取出数据:%d\n", <-ch)
	fmt.Printf("取出数据:%d\n", <-ch)
	fmt.Printf("取出数据后:长度 = %d, 容量 = %d\n", len(ch), cap(ch))

	// 尝试再取数据,管道已空,这会引发阻塞
	// 如果取消注释下一行,程序将会在此处阻塞,go会报错
	// fmt.Printf("尝试取出额外的数据:%d\n", <-ch)

	fmt.Println("程序结束")
}

二、管道的关闭

管道关闭后,就不能向它写数据了,但可以读数据。例:

package main

import (
	"fmt"
)

func main() {
   
	// 创建一个容量为3的缓冲管道
	ch := make(chan int, 3)

	// 向管道中写入数据
	ch <- 10
	ch <- 

你可能感兴趣的:(golang语法学习笔记,golang,学习,笔记)