go抽象的生产者消费者模型

这是一个单一生产者,多个消费者的模型。对之前的代码做了改进。

目标:

  1. 包装成包的形式。包的名子叫pc, producer/consumer的简写。
  2. 使用者只需要写自己实际的生产逻辑和消费逻辑即可。

1. 实现

package pc

import (
	"sync"
)

type Task interface {
}

type AbstructPC struct {
	ConsumerNum int
	ChanLen     int
	Tasks       chan Task
	Consumer    func(Task)
	Producer    func(chan Task)
	wg          sync.WaitGroup
}

func (a *AbstructPC) Init(cl int, cn int, p func(chan Task), c func(Task)) {
	a.ChanLen = cl
	a.ConsumerNum = cn
	a.Tasks = make(chan Task, a.ConsumerNum)
	a.Producer = p
	a.Consumer = c
}

func (a *AbstructPC) producerDispatch() {
	defer close(a.Tasks)

	a.Producer(a.Tasks)
}

func (a *AbstructPC) consumerDispatch() {
	for i := 0; i < a.ConsumerNum; i++ {
		a.wg.Add(1)
		go func() {
			defer a.wg.Done()
			for task := range a.Tasks {
				a.Consumer(task)
			}
		}()
	}

	a.wg.Wait()
}

func (a *AbstructPC) Run() {
	go a.producerDispatch()
	a.consumerDispatch()
}

思路:

想实现类似抽象类的功能,于是在AbstructPC中预置了两个空函数

	Consumer    func(Task)
	Producer    func(chan Task)

使用者需要实现这两个方法,并在初始化时(Init)将其以参数形式传入。如果使用者未实现这两个方法,运行时会报错。

这个实现也许这不是最佳的方式,但对于初学者的我,目前只能想到这样的方式了>_<|||

2. 使用

2.1 安装

代码放到了github, 所以可以这样安装:

go get -u github.com/qmhball/gopc

当然也可以直接将上面代码放到$GOPATH/gopc/下,注意不同的方式,import时的写法会有点区别。

2.2 需要自定的内容

  1. 实际task的数据结构
  2. 实际生产函数
func Producer(Tasks chan pc.Task) {}
  1. 实际消费函数
func Consumer(task pc.Task) {}
  1. 消费者个数,通道长度

2.3 示例

该示例自定义实际数据格式

type Person struct {}

生产者生产了10条数据,将其json encode后放入通道,消费者取出后json decode输出。main中的几行代码是pc的调用demo。

package main

import (
	"fmt"
	"pc"
	"strconv"
)

type Person struct {
	Name string
	Age  int
}

//实际生产逻辑
func Producer(Tasks chan pc.Task) {
	p := Person{}
	for i := 0; i < 10; i++ {
		p.Name = "Person" + strconv.Itoa(i)
		p.Age = i + 10
		//Task是空接口,Person默认实现了它,自然可以直接放入Task类型的通道
		Tasks <- p
	}
}

//实际消费数据逻辑
func Consumer(task pc.Task) {
    //通过断言将task转为Person类型,不能直接使用task.Name, task,Age
	p := task.(Person)
	fmt.Printf("consum task:%s, %d\n", p.Name, p.Age)
}

func main() {
	var mypc pc.AbstructPC
	chanLen := 50
	consumerNum := 20
	mypc.Init(chanLen, consumerNum, Producer, Consumer)
	mypc.Run()
}

使用时,唯一需要注意的是Consumer中取到task数据后,要使用断言将其转为你真实的数据类型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值