Go非缓冲/缓冲/双向/单向通道

Posted yzg-14

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go非缓冲/缓冲/双向/单向通道相关的知识,希望对你有一定的参考价值。

1. 非缓冲和缓冲

package main

import (
	"fmt"
	"strconv"
)

func main() {
	/*
	非缓冲通道:make(chan T)
		一次发送,一次接收,都是阻塞的
	缓冲通道:make(chan T , capacity)
		发送:缓冲区的数据满了,才会阻塞
		接收:缓冲区的数据空了,才会阻塞

	 */
	ch1 := make(chan int)           //非缓冲通道
	fmt.Println(len(ch1), cap(ch1)) //0 0
	//ch1 <- 100 //阻塞式的,需要有其他的goroutine解除阻塞,否则deadlock

	ch2 := make(chan int, 5)        //缓冲通道,缓冲区大小是5
	fmt.Println(len(ch2), cap(ch2)) //0 5

	ch2 <- 100
	fmt.Println(len(ch2), cap(ch2)) //1 5
	ch2 <- 200
	ch2 <- 300
	ch2 <- 400
	ch2 <- 500
	fmt.Println(len(ch2), cap(ch2)) //5 5
	//ch2 <- 600 //没有接触阻塞,满了

	ch3 := make(chan string, 4)
	go sendData(ch3)

	for {
		v, ok := <-ch3
		if !ok {
			fmt.Println("读完了。。", ok)
			break
		}
		fmt.Println("\t读取的数据是:", v)
	}
	fmt.Println("main。。over。。。。")

}

func sendData(ch chan string) {
	for i := 0; i < 10; i++ {
		ch <- "数据" + strconv.Itoa(i)
		fmt.Printf("子goroutine中写出第 %d 个数据\n", i)
	}
	close(ch)
}

2. 双向通道

package main

import "fmt"

func main() {
	/*
	双向:
		chan T
			chan <- data,发送数据,写出
			data <- chan,获取数据,读取

	单向:定向
		chan <- T,只支持写
		<- chan T,只读
	 */
	 ch1 := make(chan string)
	 done := make(chan bool)
	 go sendData(ch1,done)

	 data := <- ch1 //读取
	 fmt.Println("子goroutine传来:",data)

	 ch1 <- "我是main" //发送

	 <- done
	 fmt.Println("main..over...")
}

func sendData(ch1 chan string,done chan bool){
	ch1 <- "我是韩茹" //发送

	data := <- ch1 //读取
	fmt.Println("main goroutine传来:",data)


	done <- true

}

3. 单向通道

package main

import "fmt"

func main() {
	/*
		单向:定向
		chan <- T,只支持写
		<- chan T,只读


	定向通道:
		双向:-->函数:只读,只写
	 */
	ch1 := make(chan int)   //双向,读,写
	//ch2 := make(chan<- int) //单向,只能写,不能读
	//ch3 := make(<-chan int) //单向,只能读,不能写
	//
	//ch1 <- 100
	//data := <-ch1
	//ch2 <- 1000
	//data := <-ch2 //invalid operation: <-ch2 (receive from send-only type chan<- int)
	//data := <-ch3
	//ch3 <- 2000 //invalid operation: ch3 <- 2000 (send to receive-only type <-chan int)

	go fun1(ch1) //可读,可写
	//go fun1(ch2) //只写

	data := <-ch1
	fmt.Println("fun1函数中写出的数据是:", data)

	go fun2(ch1)
	//fun2(ch3)

	ch1 <- 200
	fmt.Println("main..over...")
}

//该函数,只能操作只写的通道
func fun1(ch chan<- int) {
	//在函数内部,对于ch1通道,只能写数据,不能读取数据
	ch <- 100
	fmt.Println("fun1函数结束。。。")
}

//该函数,只能操作只读的通道
func fun2(ch <-chan int) {
	data := <-ch
	fmt.Println("fun2函数,从ch中读取的数据是:", data)
}

  

以上是关于Go非缓冲/缓冲/双向/单向通道的主要内容,如果未能解决你的问题,请参考以下文章

使用缓冲和非缓冲通道遇到麻烦

NIO 详解

Go语言channel

Go语言channel

Go语言channel

NIO