1.无缓冲Channel
package main

import (
	"fmt"
	"time"
)

// 子goroutine,主goroutine结束,子也结束
func NewTask() {
	i := 0
	for {
		i++
		fmt.Println("new Goroutine: i =", i)
		time.Sleep(1 * time.Second)
	}
}

func main() {
	//定义一个无缓冲的channel
	c := make(chan int)

	go func() {
		defer fmt.Println("go goroutine 结束")
		fmt.Println("go goroutine 正在进行....")
		c <- 66 // 将66写的chan中
	}()

	// 从channel中读取数据,复制给num
	num := <-c
	fmt.Println("num is ", num)
}

// 结果:
go goroutine 正在进行....
go goroutine 结束
num is  66

注意:

  • 有没有可能main方法先执行完,sub go还没发送给c信息?

不会,当main从chan中拿不到数据,会阻塞等待

  • sub go把66放到chan中,main还没来得及读,defer会执行吗?

不会,因为是无缓冲channel,子sub go会阻塞等待main 获取数据

在这里插入图片描述

2.有缓冲Channel
package main

import (
	"fmt"
	"time"
)

// 子goroutine,主goroutine结束,子也结束
func NewTask() {
	i := 0
	for {
		i++
		fmt.Println("new Goroutine: i =", i)
		time.Sleep(1 * time.Second)
	}
}

func main() {
	//定义一个有缓冲的channel
	c := make(chan int, 3)

	fmt.Println("c的length =", len(c), "c的cap =", cap(c))

	go func() {
		defer fmt.Println("go goroutine 结束")
		for i := 0; i < 4; i++ {
			c <- i // 将i写的chan中
			fmt.Println("go goroutine 正在进行....,发送的元素:", i, "length =", len(c), "cap = ", cap(c))
		}
	}()

	time.Sleep(3 * time.Second)
	// 从channel中读取数据,复制给num
	for i := 0; i < 3; i++ {
		num := <-c
		fmt.Println("num is ", num)
	}

	fmt.Println("main 结束 ")

}

// 结果:
go goroutine 正在进行....,发送的元素: 0 length = 1 cap =  3
go goroutine 正在进行....,发送的元素: 1 length = 2 cap =  3
go goroutine 正在进行....,发送的元素: 2 length = 3 cap =  3
num is  0
num is  1
num is  2
main 结束 
go goroutine 正在进行....,发送的元素: 3 length = 3 cap =  3
go goroutine 结束

注意:

  • 当go goroutine中channel的元素满了,将会被阻塞,直到获取完一个num即继续运行
  • 当channel为空,从里面取数据也会阻塞

3.关闭channel
  1. 关闭channel不用像关闭文件一样,经常去关闭
  2. 关闭channel后无法再向channel中发送数据(引发panic error)
  3. 关闭channel后,可以继续从channel中获取数据
  4. 对于nil channel,一定发送阻塞错误,记住一定要make
    感觉兴趣的小伙伴可以加好友一起交流!!
4.Channel与range的使用
for data := range c {
	fmt.Println(data)
}
5.Channel与select的使用

单个流程下go只能监控一个Channel状态,select可以完成多个Channel监控状态

package main

import (
	"fmt"
)

func feibonicii(c, quit chan int) {
	x, y := 1, 1
	for {
		select {
		case c <- x: //如果c可写,将x写入c中
			x = y
			y = x + y
		case <-quit: // 如果quit可读,则sub go已执行完任务
			fmt.Println("quit....")
			return
		}
	}
}

func main() {
	c := make(chan int)
	quit := make(chan int)

	// sub go
	go func() {
		for i := 0; i < 16; i++ {
			fmt.Println(<-c)
		}
		quit <- 0
	}()

	// main go
	feibonicii(c, quit)
}

在这里插入图片描述