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)
		}
	}
}
相关推荐
数据小爬虫@1 小时前
Java爬虫实战:深度解析Lazada商品详情
java·开发语言
songroom1 小时前
Rust: offset祼指针操作
开发语言·算法·rust
code04号1 小时前
C++练习:图论的两种遍历方式
开发语言·c++·图论
煤泥做不到的!2 小时前
挑战一个月基本掌握C++(第十一天)进阶文件,异常处理,动态内存
开发语言·c++
F-2H2 小时前
C语言:指针4(常量指针和指针常量及动态内存分配)
java·linux·c语言·开发语言·前端·c++
bryant_meng4 小时前
【python】OpenCV—Image Moments
开发语言·python·opencv·moments·图片矩
若亦_Royi4 小时前
C++ 的大括号的用法合集
开发语言·c++
慕城南风4 小时前
Go语言中的defer,panic,recover 与错误处理
golang·go
资源补给站5 小时前
大恒相机开发(2)—Python软触发调用采集图像
开发语言·python·数码相机
m0_748247555 小时前
Web 应用项目开发全流程解析与实战经验分享
开发语言·前端·php