用Go中的渠道实现承诺

Pie*_*Pah 10 asynchronous channel go promise

我正在尝试在Go中实现Promise,这与Javascript中的类似.

type Promise struct {
        Result chan string
        Error  chan error
}

func NewPromise() (*Promise) {
        r := make(chan string, 1)
        e := make(chan error, 1)
        return &Promise{
                Result: r,
                Error:  e,
        }
}

func main() {
        var p = NewPromise()

        go func(p *Promise) {
                time.Sleep(time.Duration(5)*time.Second)
                p.Result <- "done"
        }(p)

        if <- p.Result {
                fmt.Println(<-p.Result)
        }

        // Is it possible to do something else here while wait for 5s?

        // Once Promise is fulfilled after 5s, the Result is available.
}
Run Code Online (Sandbox Code Playgroud)

我该怎么做:

  1. 运行goroutine,立即返回Promise主goroutine.
  2. 异步地在主程序上执行某些操作,同时等待将任何内容发送到其中任何一个Promise.ResultPromise.Error

  3. 发送一些内容后,从goroutine返回并使该频道可供阅读.

One*_*One 17

不使用通道的不同方法,使其更快/更高效:

type Promise struct {
    wg  sync.WaitGroup
    res string
    err error
}

func NewPromise(f func() (string, error)) *Promise {
    p := &Promise{}
    p.wg.Add(1)
    go func() {
        p.res, p.err = f()
        p.wg.Done()
    }()
    return p
}

func (p *Promise) Then(r func(string), e func(error)) {
    go func() {
        p.wg.Wait()
        if p.err != nil {
            e(p.err)
            return
        }
        r(p.res)
    }()
}
Run Code Online (Sandbox Code Playgroud)

playground

  • 这如何与“context.Context”的取消一起使用?使用通道可以中止等待或执行。 (3认同)

bea*_*u13 5

Martin Sulzmann发表了一篇名为“From Events to Futures and Promises and back”论文(发表于 2016 年 2 月),其中涵盖了该主题。摘要说:

基于通道通信和期货/承诺的事件是强大的,但对于并发编程来说似乎是不同的概念。我们表明,一个概念可以用令人惊讶的很少努力用另一个来表达。我们的结果提供了基于轻量级库的方法来实现事件和期货/承诺。实证结果表明,我们的方法在实践中效果很好。

根据该论文,期货看起来像这样:

type Comp struct {
    value interface{}
    ok    bool
}

type Future chan Comp

func future(f func() (interface{}, bool)) Future {
    future := make(chan Comp)

    go func() {
        v, o := f()
        c := Comp{v, o}
        for {
            future <- c
        }
    }()

    return future
}
Run Code Online (Sandbox Code Playgroud)

而 promise 的实现方式如下:

type Promise struct {
    lock chan int
    ft   Future
    full bool
}

func promise() Promise {
    return Promise{make(chan int, 1), make(chan Comp), false}
}

func (pr Promise) future() Future {
    return pr.ft
}
Run Code Online (Sandbox Code Playgroud)

阅读论文以了解详细信息、组合器等。