一、大体思路
把所有要处理的方法放在同一个切片当中,然后循环去开启多个协程处理这些方法
二、具体做法
1.定义两个结构体 用来存储要处理的方法和存储它下一个要多协程处理的方法,主要目的是要链式的连接下去
//定义一个接口 起到一个连接作用
type job interface {
doItJob() error
}
//多个协程一次做的事情 并且实现job这个接口
type JustDoIt struct {
fn []func() //多协程要处理的方法
nextFunc job //下一次要处理的方法
wg sync.WaitGroup //这个包可以等待上面的协程都处理完毕之后再执行下面的代码
}
//这个结构体起到连接的作用 实现对外的方法
type JobChain struct {
start *JustDoIt //上面的结构体的地址类型
end *JustDoIt //上面的结构体的地址类型
}
***注意:JobChain 这个结构体 start存的是一条链的地址,end是存的最后一个job 的地址 ***
2.JobChain 提供对外的3个方法
//返回JobChain 对象的地址
func New() *JobChain {
return &JobChain{}
}
//加入要处理的方法
func (j *JobChain) Next(fn ...func()) *JobChain{
//引用传递 重要
jab:=&JustDoIt{
fn: fn,
nextFunc: nil,
wg: sync.WaitGroup{},
}
if j.start==nil{
j.start=jab
}
if j.end!=nil{
j.end.nextFunc = jab //这里改变了start里面最后一个jab里面的nextFunc
}
j.end=jab //存的始终是上一个jab的地址
return j
}
//执行
func (j *JobChain) DoItJob() error {
if j.start==nil{
return errors.New("no start job")
}
return j.start.doItJob()
}
3.开启多个协程处理事情
func (j *JustDoIt) doItJob() error {
fmt.Println("start job")
for _,v:=range j.fn{
j.wg.Add(1) //要处理的事情加一
go func(f func()) {
defer j.wg.Done() //滞后执行要处理的事情减一
f()
}(v)
}
fmt.Println("run over job") //所有的方法都加入了开启协程处理的池子里,当循环结束了就开始处理方法
j.wg.Wait() //等池子里面的额方法处理完再执行下面代码
//下面是一个递归算法 结束条件是后面没有要处理的方法
if j.nextFunc!=nil{
fmt.Println("job: do next")
return j.nextFunc.doItJob()
}
return nil
}
三、min函数测试
package main
import (
"fmt"
"github.com/xxx/testApi/Controller"
"strconv"
)
func main(){
var fns []func()
var fns1 []func()
var fns2 []func()
var fns3 []func()
for i:=0;i<10;i++{
t:=i
fns=append(fns, func() {
aPrint(t)
})
}
for i:=0;i<10;i++{
t:=i
fns1=append(fns1, func() {
bPrint(t)
})
}
for i:=0;i<10;i++{
t:=i
fns2=append(fns2, func() {
cPrint(t)
})
}
for i:=0;i<10;i++{
t:=i
fns3=append(fns3, func() {
dPrint(t)
})
}
fmt.Println(len(fns))
_=Controller.New().Next(fns...).Next(fns1...).Next(fns2...).Next(fns3...).DoItJob()
}
func aPrint(f int) {
a:="a:"+strconv.Itoa(f)
fmt.Println(a)
}
func bPrint(f int) {
a:="b:"+strconv.Itoa(f)
fmt.Println(a)
}
func cPrint(f int) {
a:="c:"+strconv.Itoa(f)
fmt.Println(a)
}
func dPrint(f int) {
a:="d:"+strconv.Itoa(f)
fmt.Println(a)
}
方法的源代码
package Controller
import (
"errors"
"fmt"
"sync"
)
//定义一个接口 起到一个连接作用
type job interface {
doItJob() error
}
//多个协程一次做的事情
type JustDoIt struct {
fn []func()
nextFunc job
wg sync.WaitGroup
}
type JobChain struct {
start *JustDoIt
end *JustDoIt
}
func New() *JobChain {
return &JobChain{}
}
func (j *JobChain) Next(fn ...func()) *JobChain{
jab:=&JustDoIt{
fn: fn,
nextFunc: nil,
wg: sync.WaitGroup{},
}
if j.start==nil{
j.start=jab
}
if j.end!=nil{
j.end.nextFunc = jab
}
j.end=jab
return j
}
func (j *JobChain) DoItJob() error {
if j.start==nil{
return errors.New("no start job")
}
return j.start.doItJob()
}
func (j *JustDoIt) doItJob() error {
fmt.Println("start job")
for _,v:=range j.fn{
j.wg.Add(1)
go func(f func()) {
defer j.wg.Done()
f()
}(v)
}
fmt.Println("run over job")
j.wg.Wait()
if j.nextFunc!=nil{
fmt.Println("job: do next")
return j.nextFunc.doItJob()
}
return nil
}
四、执行结果
