Golang 语言 Channel 的使用方式

发布于:2025-08-02 ⋅ 阅读:(15) ⋅ 点赞:(0)

一、无缓存 channel

        无缓冲channel 可用于两个goroutine 之间 传递信号,比如以下示例:

        顺序打印1 至 100 的奇数和偶数:

import (
	"fmt"
	"time"
)

func main() {
	block := make(chan struct{})
	go odd(block)
	go even(block)
	time.Sleep(time.Second)
	fmt.Println("done")

}

func odd(block chan struct{}) {
	for i := 1; i < 100; i++ {
		<-block
		if i%2 == 1 {
			fmt.Println("奇数:", i)
		}
	}
}

func even(block chan struct{}) {
	for i := 1; i < 100; i++ {
		<-block
		if i%2 == 0 {
			fmt.Println("偶数:", i)
		}
	}
}

上面这段代码,我们使用一个无缓冲channel  作为两个gorountie 之间的信号传递的桥梁。

主子 goroutine  之间传递信号

func main() {
	block := make(chan struct{})
	go func() {
		for i := 0; i < 10; i++ {
			fmt.Println(i)
		}
		close(block)
	}()
	<-block
	fmt.Println("done")

}

我们使用一个无缓冲channel 作为主子goroutine 之间的信号传递的桥梁,通过信号传递,主gorountine  运行结束直接再退出。

二、有缓冲 channel

        有缓冲channel  可以作用于解耦操作,模拟消息队列。“生产者”和“消费者”只需各自处理channel ,实现解耦。

        解耦生产者和消费者。

func main() {
	
	task := make(chan int, 10)
	go consumer(task)

	//生成者
	for i := 0; i < 10; i++ {
		task <- i
	}
	time.Sleep(time.Second * 2)
}

func consumer(task <-chan int) {
	for i := 0; i < 10; i++ {
		go func(id int) {
			t := <-task
			fmt.Println(id, t)
		}(i)
	}
}

我们使用一个有缓冲的channel , 将生产者,消费者做解耦操作

输出结果:

三、超时操作和定时器

       我们还可以通过select 和channel ,实现超时操作和定时器

        超时操作:


import (
	"fmt"
	"time"
)

func main() {
	c1 := make(chan string, 1)
	go func() {
		time.Sleep(2 * time.Second)
		c1 <- "result 1"
	}()

	select {
	case res := <-c1:
		fmt.Println(res)
	case <-time.After(1 * time.Second):
		fmt.Println("timeout 1")
	}

	c2 := make(chan string, 1)

	go func() {
		time.Sleep(2 * time.Second)
		c2 <- "result 2"
	}()

	select {
	case res := <-c2:
		fmt.Println(res)
	case <-time.After(3 * time.Second):
		fmt.Println("timeout 1")
	}

}

通过c1 和 c2 两个channel ,分别模拟出超时和未超时场景

定时器:

func main() {
	ticker := time.NewTicker(500 * time.Millisecond)
	done := make(chan bool)
	go func() {
		for {
			select {
			case <-done:
				return
			case t := <-ticker.C:
				fmt.Println("Tick at ", t)
			}
		}
	}()
	time.Sleep(1600 * time.Millisecond)
	ticker.Stop()
	done <- true
	fmt.Println("Ticker stopped")
}

我们定义一个打点器,每间隔500Ms执行一次操作,当打点stop时,通过一个无缓冲channel 传递退出信号

三、总结

本文我们介绍了一些关于 Channel 的使用方式,我们在阅读完本文后可以了解无缓冲 channel 作为信号传递的使用方式和有缓冲 channel 解耦操作的方式,以及 channel 与 select 配合使用的用法。


网站公告

今日签到

点亮在社区的每一天
去签到