首页 > 其他分享 >Let's Go系列---channel的用法及原理

Let's Go系列---channel的用法及原理

时间:2022-08-16 22:25:37浏览次数:59  
标签:ch make chan --- Let wp Go main channel

基本语法

创建channel

ch1 := make(chan struct{})
ch2 := make(chan int, 10)

读写channel

从channel中读取数据叫做recv;向channel写数据叫做send

// 发送数据到channel
ch1 <- struct{}{}
ch2 <- 10
// 从channel接收数据
val1 := <-ch1
// ok可以判断channel是否已经关闭
val2, ok := <-ch2

遍历channel

该语法仅限于带缓冲区的channel

package main

import "fmt"

func main() {
	ch := make(chan int, 2)
	go func() {
		for i := 1; i < 10; i++ {
			ch <- i
		}
		close(ch)
	}()
	for val := range ch {
		fmt.Printf("%v ", val)
	}
	fmt.Println()
}

channel的状态与读写关系

操作 nil channel 正常的channel 关闭的channel
读(<- ch) 阻塞 成功或阻塞 零值
写(ch <-) 阻塞 成功或阻塞 panic
关闭(close(ch)) panic 成功 panic

惯用技法

协程池

package main

import (
	"fmt"
	"time"
)

type Worker struct {
	Name string
}

func (w *Worker) ProcessTask(data string, done chan<- *Worker) {
	time.Sleep(time.Second)
	fmt.Println(w.Name + " task done:" + data)
	done <- w
}

type WorkerPool struct {
	taskCh  chan string
	done    chan *Worker
	closeCh chan struct{}
	pool    []*Worker
}

func NewWorkerPool(workCnt int) *WorkerPool {
	wp := &WorkerPool{
		taskCh:  make(chan string),
		done:    make(chan *Worker),
		closeCh: make(chan struct{}),
		pool:    make([]*Worker, workCnt),
	}
	for i := 0; i < len(wp.pool); i++ {
		wp.pool[i] = &Worker{Name: fmt.Sprintf("worker-%v", i)}
	}
	wp.Run()
	return wp
}

func (wp *WorkerPool) AddTask(data string) {
	wp.taskCh <- data
}

func (wp *WorkerPool) Run() {
	go func() {
		for {
			select {
			case w := <-wp.done:
				wp.pool = append(wp.pool, w)
			case <-wp.closeCh:
				close(wp.done)
				close(wp.taskCh)
				return
			default:
				if len(wp.pool) > 0 {
					w := wp.pool[0]
					wp.pool = wp.pool[1:]
					go w.ProcessTask(<-wp.taskCh, wp.done)
				}
			}
		}
	}()
}

func (wp *WorkerPool) ShutDown() {
	time.Sleep(time.Second * 3)
	close(wp.closeCh)
}

func generator() chan string {
	inputCh := make(chan string)
	go func() {
		taskID := 1
		for {
			inputCh <- fmt.Sprintf("task-%v", taskID)
			taskID++
			if taskID == 21 {
				close(inputCh)
				break
			}
		}
	}()
	return inputCh
}

func main() {
	wp := NewWorkerPool(5)
	for task := range generator() {
		wp.AddTask(task)
	}
	wp.ShutDown()
	fmt.Println("all task done")
}

 

标签:ch,make,chan,---,Let,wp,Go,main,channel
From: https://www.cnblogs.com/bfstudy/p/16499015.html

相关文章

  • mongo数据同步的三种方案
    (一)直接复制data目录(需要停止源和目标的mongo服务)1.针对目标mongo服务已经存在,并正在运行的(mongo2-->mongo)。执行步骤:(1).停止源/目标服务器的mongo服务。mongod--db......
  • 2022-08-16 第六小组 张宁杰 Mysql数据库(2)
    DQL数据库查询语言重点,DQL是我们每天都要接触编写最多也是最难的SQL,该语言用来查询记录,不会修改数据库和表结构。构建数据库创建一张student表:DROPTABLEIFEXISTSst......
  • 2022-08 田龙跃 数据库学习笔记
    Mysql数据库5.7约束无法使用枚举是数据类型数据库数据库【按照数据结构来组织、存储和管理数据的仓库】。是一个长期存储在计算机内的、有组织的、可共享的、统一管......
  • mysql-3
    目录约束条件约束条件之外键ForeignKey表关系之多对多表关系之一对一约束条件1.primarykey主键 1.单从约束角度上而言主键等价于非空且唯一notnullunique cre......
  • 《GB12981-2012》PDF下载
    《GB12981-2012机动车辆制动液》PDF下载《GB12981-2012》简介本标准规定了以醇醚及醇醚硼酸酯类非石油基原料为基础液,加入多种添加剂制成的机动车辆制动液的要求和试验......
  • 2022-08-15 day28 第一小组 王鸣赫
    目录Mysql数据库数据库Mysql基本操作表SQL语言SQL分类DCL(数据库控制语言)创建用户给用户授权撤销授权查看权限删除用户DDL(数据定义语言)创建表数据类型整型浮点型字符串类型......
  • 2022-08-16 day29 第一小组 王鸣赫
    目录DQL数据库查询语言单表查询基本查询基本语法别名条件控制按条件表达式筛选:逻辑运算符模糊查询:排序特点常见函数字符函数数学函数日期函数分组函数分组查询分页查询多表......
  • el-checkbox遍历的的时候如何使用
    <template><divclass="checkBox"><templatev-for="itemincheckedCities"><el-checkbox:key="item.id"v-model="item.isCheck"@change=......
  • 239.sliding-window-maxium 滑动窗口最大值
    采用双端队列deque,并且保证deque从前往后依次递减,并且出现在deque里面的相邻两数,其在原滑动窗口中,两数中间的数一定比这两个数小。为了保证这一点,在push_back()时,如果deque......
  • docker篇:迁移备份、Dockerfile、私有仓库、docker-compose
    目录一、迁移备份二、Dockerfile2.1镜像如何获得2.2Dockerfile是什么?2.3如何构建镜像和配置dockerfile三、Docker私有仓库3.1如何将镜像传到公有仓库3.2自己搭建私有......