golang , chan学习

管道是阻塞的,管道的写法,管道内容读取,和写入

go 复制代码
package main

import "fmt"

func main() {
	// 管道声明 chan是关键字 int是类型
	// var chan1 chan int
	chan1 := make(chan int)
	fmt.Println(chan1)

	// 无缓冲通道,不会存储数据,会直接流入管道
	// 它的容量是 0,不能存储任何数据
	// 数据并不会在 channel 中做任何停留。这也意味着,无缓冲 channel 的发送和接收操作是同时进行的,它也可以称为同步 channel
	c := make(chan int)
	go func() {
		defer fmt.Println("goroutine over")
		fmt.Println("goroutine正在运行...")
		c <- 666 // 流入管道
	}()

	// 管道的读取是会被阻塞的
	// 接收:receive
	num, ok := <-c
	if ok {
		println("the chan is ok and num is ", num)
	}
	fmt.Println("main goroutine over")

}

带容量的chain,如果满了,那么发送的时候会阻塞,如果空了,那么接受的时候会阻塞

go 复制代码
package chandemo

import (
	"fmt"
	"time"
)

func bufferChannel() {
	// 带容量的chan
	c := make(chan int, 3)

	// len是实际的,cap是客观的容量
	fmt.Println("len(c) = , cap(c) = ", len(c), cap(c))

	go func() {
		defer fmt.Println("子go结束")

		// 轮询向管道发送数据
		// 如果队列已满,则阻塞等待,直到另一个 goroutine 执行,接收操作释放队列的空间
		for i := 0; i < 3; i++ {
			c <- i
			fmt.Println("子go程正在运行,发送的元素=i", i, " len(C) = ", len(c), "cap(c)", cap(c))
		}
	}()

	// 保证先发送完成
	time.Sleep(2 * time.Second)

	// 循环接收数据
	// 接收操作是从队列的头部获取元素并把它从队列中删除,如果队列为空,则阻塞等待,直到另一个 goroutine 执行,发送操作插入新的元素
	for i := 0; i < 3; i++ {
		num := <-c
		fmt.Println("num of i is ", num)
	}

	fmt.Println("main 结束")
}

单向管道,

  • 只能由发送方关闭管道:

    由发送方负责关闭管道,接收方不能关闭管道。

    如果接收方尝试关闭管道,会引发运行时错误。

  • 重复关闭会导致 panic:

    如果对同一个管道调用多次 close,会导致 panic。

    因此,关闭操作应确保在逻辑上只调用一次。

  • 关闭后的管道可以继续接收数据

    但不能再向关闭的管道发送数据,否则会引发 panic。

go 复制代码
package chandemo

import "fmt"

// onlySend
func counter(out chan<- int) {
	for i := 0; i < 100; i++ {
		out <- i
	}
	// 发送完成后,关闭管道
	// 关闭管道可以向接收方表明,管道中不会再有新的数据。
	close(out)
}

// out是只能发送,in是只能接受
func squarer(out chan<- int, in <-chan int) {
	for i := range in {
		out <- i * i
	}
	close(out)
}

// 只能接收数据的管道
// in 为单向接收管道,用于从上游接收数据并打印
func printer(in <-chan int) {
	// 当管道关闭且数据读取完毕时,会自动退出循环
	for val := range in {
		fmt.Printf("收到数据: %d\n", val)
	}
}

func testSingleChan() {
	ch1 := make(chan int)
	ch2 := make(chan int)
	// ch1 -> ch2 -> printer
	// 启动counter,将数据发送给ch1
	go counter(ch1)
	// 启动squarer,将ch1的数据平方后发送给ch2
	go squarer(ch2, ch1)
	// 启动printer,从ch2接收数据并打印
	printer(ch2)
}

// 管道避免死锁
func main() {
    ch := make(chan int)

    go func() {
        ch <- 42 // 发送数据
        close(ch) // 关闭管道
    }()

    val, ok := <-ch
    fmt.Println(val, ok) // 42 true
    
	// 检查管道是否关闭
    val, ok = <-ch
    fmt.Println(val, ok) // 0 false (管道已关闭,没有数据)
}

select + chan实现多路复用

go 复制代码
func main() {

   //声明三个存放结果的channel
   firstCh := make(chan string)
   secondCh := make(chan string)
   threeCh := make(chan string)

   //同时开启3个goroutine下载
   go func() {
      firstCh <- downloadFile("firstCh")
   }()

   go func() {
      secondCh <- downloadFile("secondCh")
   }()

   go func() {
      threeCh <- downloadFile("threeCh")
   }()

   //开始select多路复用,哪个channel能获取到值,
   //就说明哪个最先下载好,就用哪个。
   select {
      case filePath := <-firstCh:
         fmt.Println(filePath)
      case filePath := <-secondCh:
         fmt.Println(filePath)
      case filePath := <-threeCh:
         fmt.Println(filePath)
   }
}

func downloadFile(chanName string) string {

   //模拟下载文件,可以自己随机time.Sleep点时间试试
   time.Sleep(time.Second)
   return chanName+":filePath"
}

// channel来退出
func testselectclose() {
	ch := make(chan int)

	go func() {
		for i := 1; i <= 3; i++ {
			ch <- i
		}
		close(ch)
		// ch <- 1// panic: send on closed channel
	}()

	for {
		select {
		case val, ok := <-ch:
			// 检测到false,因为close了,那么就会推出
			if !ok {
				fmt.Println("Channel closed, exiting.")
				return
			}
			fmt.Println("Received:", val)
		}
	}
}
相关推荐
码叔义4 分钟前
Jsonpath 使用说明
android·开发语言·javascript
行十万里人生18 分钟前
Qt 对象树详解:从原理到运用
开发语言·数据库·qt·华为od·华为·华为云·harmonyos
原来是猿24 分钟前
蓝桥备赛(四)- 数组(下)
开发语言·数据结构·c++·算法
心流时间27 分钟前
[Java基础] JVM常量池介绍(BeanUtils.copyProperties(source, target)中的属性值引用的是同一个对象吗)
java·开发语言·jvm
网络安全Ash30 分钟前
Python网络安全脚本
开发语言·python·web安全
前端熊猫1 小时前
排序算法学习笔记
笔记·学习·排序算法
.猫的树1 小时前
Java集合List快速实现重复判断的10种方法深度解析
java·开发语言·list·集合
刀客1231 小时前
C++ STL(三)list
开发语言·c++
auspark1 小时前
macos下cocoapods的学习
学习·macos·cocoapods
朔北之忘 Clancy2 小时前
2022 年 12 月青少年软编等考 C 语言五级真题解析
c语言·开发语言·c++·学习·算法·青少年编程·题解