Go 语言 channel通道的基础知识

Go 语言 channel通道的基础知识

通道(channel)就是一个管道,可以想象成Go 协程之间通信的管道,他是一种队列的数据结构,遵循先进先出的规则

通道的声明

每一个通道只能传递一种数据结构的数据,在我们声明的时候,就要指定管道的类型,chan Type 表示Type类型的通道,通道的零值为nil

var channel_name chan channel_type

func channel() {
	//声明了一个类型为string的通道,值为nil
	var channel chan string
    channel =make(chan string)
	fmt.Println(channel)
    
    //简单的声明方式
    ch :=make(chan string)
}
管道初始化以及使用

声明完通道之后,其值为nil,我们不能直接使用,必须先使用make函数对通道进行初始化操作

package main

import (
	"fmt"
	"time"
)

func channel() {
	//声明了一个类型为string的通道,值为nil
	var channel chan string
	fmt.Println(channel)
}

func PrintChan(c chan string) {
	c <- "第七魂技 - 武魂真身"
}
func ChanTest() {
	/**
	发送数据  channel_name <- data
	接收数据  value :=<-channel_name
	*/
	//创建一个通道
	ch := make(chan string)
	fmt.Println("第一魂技。。。")
	//开启协程
	go PrintChan(ch)
	//从通道中获取数据
	res := <-ch
	fmt.Println(res)
	fmt.Println("第九魂技。。。")
	//关闭通道
	close(ch)
	_, ok := <-ch
	//检查通道是否关闭
	fmt.Println(ok)

	/**
	无缓冲通道
	c :=make(chan int)
	c :=make(chan int,0)
	缓冲通道
	 c :=make(chan int ,3)//数值
	*/
	c := make(chan int)
	go func() {
		fmt.Println("send 1")
		c <- 1
	}()

	go func() {
		n := <-c
		fmt.Println("receive", n)
	}()
	time.Sleep(1 * time.Second)

}

/**
只读通道  <-than
只写通道 chan <-
*/
type Sender = chan<- string
type Receiver = <-chan string

func ChanTest01() {
	//创建一个双向通道
	ch := make(chan string)
	go func() {
		var sender Sender = ch
		fmt.Println("即将学习。。。")
		sender <- "第二魂技-床绕"
	}()

	go func() {
		var receiver Receiver = ch
		message := <-receiver
		fmt.Println("开始学习:", message)
	}()

	time.Sleep(1 * time.Second)
}

func RangeChan() {
	//遍历通道 for range
	var channel = make(chan int, 5)
	go LoopPrint(channel)
	for v := range channel {
		fmt.Println(v)
	}
	channel1 := make(chan bool, 1)
	var x int
	for i := 0; i < 1000; i++ {
		go increment(channel1, &x)
	}

	time.Sleep(1 * time.Second)
	fmt.Println("x=", x)
}
func LoopPrint(c chan int) {
	for i := 0; i < 10; i++ {
		c <- i
	}
	close(c)
}
func increment(ch chan bool, x *int) {
	ch <- true
	//不是原子操作,避免多协程进行操作;使用容量为1的通道,达到锁的效果
	*x = *x + 1
	<-ch
}

func funcReceiver(c chan bool) {
	fmt.Println(<-c)
}
func main() {
	RangeChan()

	ch := make(chan bool)
	//1.开启一个协程,再往管道写入数据,这样就不会产生死锁  go funcReceiver(ch)
	//2. 把无缓冲通道改为有缓冲通道  ch := make(chan bool, 1)
	//go funcReceiver(ch)
	//往通道里写数据
	ch <- true
	//通道里读数据 ---看上去没啥问题,其实会产生死锁  fatal error: all goroutines are asleep - deadlock!
	fmt.Println(<-ch)
}

你可能感兴趣的:(golang,开发语言,后端)