日頃の行い

個人的な日頃の行いをつらつら書いてます\\\\ ٩( 'ω' )و ////

今更ながらRetryするGolangのpackage書いてみた

何番煎じかわからないですが、かいてみました。
呼び出し方がretry.Retryってなってなんかびみょ・・・

github.com

使い方

retry.Retryの第三引数の実装にリトライがありえる処理を書く感じです。
errorが返った場合にはretry.Retryの第一引数に与えた回数分だけリトライします。
リトライの間の待ち時間は第二引数で設定できます。
第二引数の関数は、今のリトライ回数と前回の結果を受け取って待ち時間を返す関数にする必要があります。
retry.Retryの返り値は、第三引数に与えた関数の返り値と一致します。
第一引数分リトライをしてもerrorが返った場合はerrorが返ります。

main.go

package main

import (
    "fmt"
    "log"
    "time"

    "github.com/ara-ta3/retry"
)

func main() {
    c := someClient{
        n: 0,
    }
    // retry.Retry returns the return values of "func" at third args
    r, err := retry.Retry(
        10,
        func(n int, r interface{}) time.Duration {
            // waiting time
            return 0 * time.Second
        },
        func() (interface{}, error) {
            // your codes
            // if this returns error, this will retry this "func"
            return c.DoSomething()
        },
    )
    if err != nil {
        log.Fatalln(err)
    }

    res, ok := r.(*result)

    if !ok {
        log.Fatalf("result cannot be cast to Result struct. r: %+v", r)
    }

    fmt.Printf("%+v\n", res)
}

type someClient struct {
    n int
}

type result struct {
    Message string
}

func (c *someClient) DoSomething() (*result, error) {
    if c.n >= 5 {
        return &result{
            Message: fmt.Sprintf("some message. n: %d", c.n),
        }, nil
    }
    c.n++
    fmt.Printf("count: %d\n", c.n)
    return nil, fmt.Errorf("return error for retry")
}

これを実行すると下記のような感じになります。
待ち時間は0秒にしているので一瞬で終わります。

$time go run main.go
count: 1
count: 2
count: 3
count: 4
count: 5
&{Message:some message. n: 5}
go run main.go  0.14s user 0.08s system 98% cpu 0.231 total

感想

  • retry色んな所でやりたくなったりするので、書いてみました。
  • 便利なので使っていきたい。