Go---channel

96 阅读2分钟

channel

go中的channel是一种内置的复杂数据类型,和map、slice相似。它是一种队列结构,遵循FIFO(先进先出)原则。它主要应用于goroutine之间的通信。

向channel中存储数据

// 声明一个名为ch的chan,ch中存储的数据类型是string
var ch chan string
// 初始化ch
ch = make(chan string)
// 将"hello world"存入ch
ch <-"hello world"

将channel中的数据取出

// 将ch中的数据取出并赋值给x
x := <- ch

tip

  • channel必须初始化后才能使用。
  • 在使用make()进行初始化时,可以指定初始容量,也可以不指定,当不指定初始容量时,需要先有接收者(receiver)才能向ch中存储数据,否则会报错(goroutine死锁)。
  • 当ch中的数据全部被取出时,再取的话会返回对应数据类型的零值。
  • 可以通过v, ok := <-ch来取出ch中的数据,如果有数据,则将数据赋值给v,ok为true,否则v为对应数据类型的零值,ok为false,以此来判断ch中的数据是否被取完了。

只写channel

var ch chan<- string

表示ch是一个只写channel,即只能向ch中存储数据,不能从ch中取出数据。

只读channel

var ch <-chan string

表示ch是一个只读channel,即只能从ch中读取数据,不能向ch中存储数据。

select

适用于对多个channel做处理

var (
	ch chan string
	wg sync.WaitGroup
)

func main() {
	ch = make(chan string, 1)
	wg.Add(2)
	go slt()
	// 消耗一点时间,方便看出效果
	for i := 0; i < 1000000; i++ {
	}
	go sender()
	wg.Wait()
}

// 发送者
func sender() {
	ch <- "hello"
	ch <- "world"
	wg.Done()
}

// select
func slt() {
loop:
	for {
		select {
		// 可从ch中读出数据
		case <-ch:
			{
				fmt.Println("接收到ch中的数据,跳出循环")
				wg.Done()
				break loop
			}
		// 所有case都不通的话就走default
		default:
			fmt.Println("未接收到ch中的数据,继续循环")
		}
	}
}

end

文章仅做个人学习交流,也许并不完全正确,欢迎指正;