在go中封裝future物件處理非同步結果
阿新 • • 發佈:2019-02-04
在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),
}
}