关于select和channel数组的配合使用

4SecondaryNone · 2016-01-22 03:29:39 · 7025 次点击

嗯,多谢,刚刚了解了一下reflect。

#2
更多评论

可以用标准包reflect中的reflect.Select()函数来处理。给你写了个简单的例子:

package main

import (
    "fmt"
    "math/rand"
    "reflect"
    "time"
)

type (
    product struct {
        id  int // 生产者序号
        val int // 产品
    }
    producer struct {
        id   int // 序号
        chnl chan *product
    }
)

var (
    producerList []*producer
    notifynew    chan int
    updatedone   chan int
)

func main() {

    rand.Seed(time.Now().Unix())
    notifynew = make(chan int, 1)
    updatedone = make(chan int, 1)
    ticker := time.NewTicker(time.Second)

    cases := update(ticker)

    for {
        chose, value, _ := reflect.Select(cases)
        switch chose {
        case 0: // 有新的生产者
            cases = update(ticker)
            updatedone <- 1
        case 1:
            // 创建新的生产者
            if len(producerList) < 5 {
                go newproducer()
            }
        default:
            item := value.Interface().(*product)
            fmt.Printf("消费: 值=%d 生产者=%d\n", item.val, item.id)
        }
    }
}

func update(ticker *time.Ticker) (cases []reflect.SelectCase) {

    // 新生产者通知
    selectcase := reflect.SelectCase{
        Dir:  reflect.SelectRecv,
        Chan: reflect.ValueOf(notifynew),
    }
    cases = append(cases, selectcase)

    // 定时器
    selectcase = reflect.SelectCase{
        Dir:  reflect.SelectRecv,
        Chan: reflect.ValueOf(ticker.C),
    }
    cases = append(cases, selectcase)

    // 每个生产者
    for _, item := range producerList {
        selectcase = reflect.SelectCase{
            Dir:  reflect.SelectRecv,
            Chan: reflect.ValueOf(item.chnl),
        }
        cases = append(cases, selectcase)
    }
    return
}

func newproducer() {
    newitem := &producer{
        id:   len(producerList) + 1,
        chnl: make(chan *product, 100),
    }
    producerList = append(producerList, newitem)
    notifynew <- 1
    <-updatedone
    go newitem.run()
}

func (this *producer) run() {
    for {
        time.Sleep(time.Duration(int(time.Millisecond) * (rand.Intn(1000) + 1)))
        item := &product{
            id:  this.id,
            val: rand.Intn(1000),
        }
        fmt.Printf("生产: 值=%d 生产者=%d\n", item.val, item.id)
        this.chnl <- item
    }
}
#1

很感谢,非常有用。

#3