Quantcast
Channel: いろいろ備忘録日記
Viewing all articles
Browse latest Browse all 170

Goメモ-384 (Future/Promiseパターン)

$
0
0

関連記事

GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ

概要

以下、自分用のメモです。

書籍「実用Go言語」にFuture/Promiseパターンの例が記載されていたので、ついでなのでここにもメモメモ。。。

Goの場合は、チャネルなどがあるので他の言語のように大活躍とはならないかもしれませんが、同じような概念が必要な場合は多いです。

下記のおすすめ書籍にもリンクしていますが、オライリーから出ている「初めてのGo言語」と「実用Go言語」は、本当にとても良い本です。読みやすいし。

サンプル

package main

import (
    "log""sync""time"
)

type (
    // Future[T] は、「今はまだ得られていないが将来得られるはずの入力」を表します。
    Future[T any] struct {
        value T
        wait  chanstruct{}
    }

    // Promise[T] は、「将来値を提供するという約束」を表します。
    Promise[T any] struct {
        f *Future[T]
    }
)

func (me *Future[T]) IsDone() bool {
    select {
    case<-me.wait:
        returntruedefault:
        returnfalse
    }
}

func (me *Future[T]) set(v T) {
    if me.IsDone() {
        return
    }

    me.value = v
    close(me.wait)
}

func (me *Future[T]) Get() T {
    <-me.wait
    return me.value
}

func (me *Promise[T]) Submit(v T) {
    me.f.set(v)
}

func NewPromise[T any]() (*Future[T], *Promise[T]) {
    f := &Future[T]{wait: make(chanstruct{})}
    p := &Promise[T]{f: f}

    return f, p
}

func init() {
    log.SetFlags(log.Ltime)
}

func main() {
    log.Println("START")
    defer log.Println("END  ")

    var (
        f1, p1 = NewPromise[int]()
        f2, p2 = NewPromise[string]()
        wg     sync.WaitGroup
    )

    wg.Add(3)

    // f1に依存する処理//// f2の状態に関係なく、f1が完了したら完了するgofunc(f *Future[int]) {
        defer wg.Done()
        log.Printf("f1=%v", f1.Get())
    }(f1)

    // f2に依存する処理//// f1の状態に関係なく、f2が完了したら完了するgofunc(f *Future[string]) {
        defer wg.Done()
        log.Printf("f2=%v", f2.Get())
    }(f2)

    // f1とf2に依存する処理//// f1, f2の2つのFutureが完了しないと処理が完了しないgofunc(f1 *Future[int], f2 *Future[string]) {
        defer wg.Done()
        log.Printf("f1=%v\tf2=%v", f1.Get(), f2.Get())
    }(f1, f2)

    // 1秒後にf1に値を提供する//// このPromiseが値を提供するまで対応するFuture(f1)は結果を返さないgofunc(p *Promise[int]) {
        time.Sleep(1 * time.Second)
        p.Submit(999)
    }(p1)

    // 3秒後にf2に値を提供する//// このPromiseが値を提供するまで対応するFuture(f2)は結果を返さないgofunc(p *Promise[string]) {
        time.Sleep(3 * time.Second)
        p.Submit("hello world")
    }(p2)

    wg.Wait()
}

実行すると以下のようになります。

      $ task -d examples/singleapp/future_promise/
       task: [default] go run main.go
       08:19:13 START
       08:19:14 f1=999
       08:19:16 f2=hello world
       08:19:16 f1=999f2=hello world
       08:19:16 END

try-golang/examples/singleapp/future_promise at main · devlights/try-golang · GitHub

gomy/promise at main · devlights/gomy · GitHub

参考情報

Goのおすすめ書籍


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。


Viewing all articles
Browse latest Browse all 170

Trending Articles