使用Golang實現Futures 和 Promises

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

其它語言中Future和Promise的概念大量存在, 比如Node.js、Scala、Java、C#、C++ 11、Scheme、Swift等,可以方便的實現非同步執行和回調。但是在Go語言的世界裡,我們是通過goroutine/channel實現這種類似的功能呢,goroutine之間可以通過channel進行通訊, 但是,如果我們還是想使用Future/Promise的功能的話,該如何?呢?

Future,Promise或Delay是用於並發編程的一種設計模式。它們表示一個對象,這個對象用來作為一次計算結果的代理,而該結果開始的時候是未知的,因為計算還沒有完成。Promise與Future的區別在於,Future是Promise的一個唯讀視圖,也就是說Future沒有設定任務結果的方法,只能擷取任務執行結果或者為Future添加回呼函數。

下面示範了實現一個Go Future的實現。因為Go目前還沒有泛型的概念,所以為了使代碼更通用,我會使用interface{}代表一個通用的對象。

首先定義一個Future結構,

gotype Future struct { result interface{} //計算結果 err error //錯誤 signal chan struct{} //等待完成的訊號 IsCompleted bool //計算是否完成}

這個Future可以執行下面的計算func() (interface{}, error),所以計算方法應該實現為FutureFunc類型的函數,它會返回結果或者返回error:
go type FutureFunc func() (interface{}, error)

然後定義擷取結果的GetGetOrTimeout方法,它會阻塞直到獲得結果或者逾時(GetOrTimeout)。
`go
// GetOrTimeout is similar to Get(), but GetOrTimeout will not block after timeout.
func (f *Future) GetOrTimeout(d time.Duration) (result interface{}, err error, timeout bool) {
select {
case <-time.After(d):
return nil, nil, true
case <-f.signal:
return f.result, f.err, false
}
}

// Get is used to get future result
func (f *Future) Get() (result interface{}, err error) {
<-f.signal
return f.result, f.err
}
`

然後定義NewFuture就可以了:
`go
func NewFuture(fun FutureFunc) *Future {
f := new(Future)

f.signal = make(chan struct{}, 1)go func() {    defer close(f.signal)    result, err := fun()    f.result = result    f.err = err    f.IsCompleted = true}()return f

}
`

一個使用的例子:
`go
func ExampleRequestFuture() {
requestFunc := func() (body interface{}, err error) {
url := "http://www.baidu.com"
var resp *http.Response
resp, err = http.Get(url)
if err != nil {
return
}
defer resp.Body.Close()
bodyBytes, err := ioutil.ReadAll(resp.Body)
return string(bodyBytes), err
}

requestFuture := NewFuture(FutureFunc(requestFunc))body, err, timeout := requestFuture.GetOrTimeout(10 * time.Second)if timeout {    fmt.Println("timeout")} else {    if err != nil {        fmt.Printf("error: %v\n", err)    } else {        fmt.Printf("body: %v\n", body)    }}

}
`

如果你是一個Java程式了,可以發現這個Future類似Java中的Future介面。

當然這個Future實現的還是非常的簡陋,至少還應該實現回調介面比如OnSuccessOnFailureOnComplete等方法,另外一些方法如Cancel也應該加上。
為了組合多個Future,避免掉入"回調陷阱",還應該實現Future的組合方法。

為了實現SetResultSetError的功能,可以實現一個類似的Promise的功能。

但是,目前我不會去實現這個功能,一是目前我沒有這方面的需求,而是 @fanliao已經實現了這樣的一個架構,名字叫go-promise,代碼放在了github上,我們不必再重複造輪子了。

這個架構提供了豐富的功能:

  • Future and Promise

    • NewPromise()
    • promise.Future
  • Promise and Future callbacks

    • .OnSuccess(v interface{})
    • .OnFailure(v interface{})
    • .OnComplete(v interface{})
    • .OnCancel()
  • Get the result of future

    • .Get()
    • .GetOrTimeout()
    • .GetChan()
  • Set timeout for future

    • .SetTimeout(ms)
  • Merge multiple promises

    • WhenAll(func1, func2, func3, ...)
    • WhenAny(func1, func2, func3, ...)
    • WhenAnyMatched(func1, func2, func3, ...)
  • Pipe

    • .Pipe(funcWithDone, funcWithFail)
  • Cancel the future

    • .Cancel()
    • .IsCancelled()
  • Create future by function

    • Start(func() (r interface{}, e error))
    • Start(func())
    • Start(func(canceller Canceller) (r interface{}, e error))
    • Start(func(canceller Canceller))
  • Immediate wrappers

    • Wrap(interface{})
  • Chain API

    • Start(taskDone).Done(done1).Fail(fail1).Always(alwaysForDone1).Pipe(f1, f2).Done(done2)

使用例子可以看他的項目文檔。

參考資料

  1. https://en.wikipedia.org/wiki/Futures_and_promises
  2. http://labs.strava.com/blog/futures-in-golang/
  3. https://github.com/fanliao/go-promise

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.