1. 程式人生 > >在go中封裝future物件處理非同步結果

在go中封裝future物件處理非同步結果

在go中,有了協程和chan,就能輕鬆而優雅的實現很多模式。

而引入future的思想可以解放思維。future是一個物件,擁有SetResult和GetResult兩個方法。在呼叫GetResult的時候,會阻塞並等待SetResult,一定時間後超時返回nil。
此時程式設計模型變為三段式:啟動並行任務傳入future,做點其它的事,收集future的結果。嗨的飛起。
其它的不說了,看註釋吧。

package utils

import (
    "sync"
    "time"
)

/*
Future 是一個未來的任務的抽象。和python裡的那個有點類似。
在非同步任務中SetResult,在GetResult的時候會等待result生成,或者超時。
使用姿勢:
tasks := make([]*utils.Future, 0)
for i := 0; i < 10; i++ {
    future := utils.NewFuture()
    tasks = append(tasks, future)
    go func(result int) {
        time.Sleep(time.Second * time.Duration(rand.Int63n(10)))
        future.SetResult(result)
    }(i)
}

for _, item := range tasks {
    ret, ok := item.GetResult().(int)
    if ok {
        fmt.Println(ret)
    } else {
        fmt.Println("failed")
    }
}
*/
type Future struct { isfinished bool result interface{} resultchan chan interface{} l sync.Mutex } func (f *Future) GetResult() interface{} { f.l.Lock() defer f.l.Unlock() if f.isfinished { return f.result } select { // timeout case <-time.Tick(time.Second * 6
): f.isfinished = true f.result = nil return nil case f.result = <-f.resultchan: f.isfinished = true return f.result } } func (f *Future) SetResult(result interface{}) { if f.isfinished == true { return } f.resultchan <- result close
(f.resultchan) } func NewFuture() *Future { return &Future{ isfinished: false, result: nil, resultchan: make(chan interface{}, 1), } }