Fumiのブログ

【Golang】可変長引数をもつ関数のラッピング

はじめに

今プライベートで作っているサービスをGo言語で作っています。
そこで、ちょっと可変長引数をもつ関数のラッピングがしたくなったので、どうやったかの備忘録。
今回はginというWebフレームワークのRun関数をラッピングしました。

ginのRun関数は以下のように定義されています。

func (engine *Engine) Run(addr ...string) (err error) {
    defer func() { debugPrintError(err) }()

    address := resolveAddress(addr)
    debugPrint("Listening and serving HTTP on %s\n", address)
    err = http.ListenAndServe(address, engine)
    return
}

github.com

内容

書いたコードは、次のようなコードです。
※記事用のサンプルコードです。

package main

import (
    "github.com/gin-gonic/gin"
    "log"
)

func main() {
    if err := runServer(); err != nil {
        log.Fatal(err)
    }
}

func runServer(addr ...string) error  {
    router := gin.Default()
    return router.Run(addr...)
}

ポイントは、addr...のところ。

これについては、公式ドキュメントの言語リファレンスに書かれている下記の文章が該当。

If the final argument is assignable to a slice type T, it may be passed unchanged as the value for a ...T parameter if the argument is followed by .... In this case no new slice is created.

[https://golang.org/ref/spec#Passing_arguments_to...parameters:embed:cite]

以下、Google翻訳先生の日本語訳。

最後の引数がスライスタイプ Tに代入可能である場合、引数の後に...が続くと、... Tパラメータの値としてそのまま渡されることがあります。この場合、新しいスライスは作成されません。