Caution

お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。

可変長引数

Goの可変長引数(variadic)を使うと、任意の数の引数を受け取る関数を定義できます。最後の引数の型の前に『...』を付けることで、0個以上の引数をスライスとして受け取ります。

構文
// 可変長引数の関数定義です(最後の引数にのみ使えます)
func 関数名(固定引数 型, args ...型) {
    // args はスライスとして扱えます。
    for _, v := range args {
        // 各要素を処理します。
    }
}

// 呼び出し方:値を直接渡します。
関数名(固定, 値1, 値2, 値3)

// スライスを展開して渡します(... を付けます)。
slice := []int{1, 2, 3}
関数名(固定, slice...)
可変長引数の特徴
特徴概要
最後の引数のみ可変長引数は関数の最後のパラメータにのみ指定できます。
スライスとして受け取る関数内では可変長引数はスライスとして扱われます(引数なしの場合はnilスライス)。
スライスの展開既存のスライスを渡す場合は『slice...』と書いて展開します。
0個もOK引数を1つも渡さなくてもエラーになりません。
サンプルコード
package main

import "fmt"

// 整数の合計を求める可変長引数関数です。
func sum(nums ...int) int {
    total := 0
    for _, n := range nums {
        total += n
    }
    return total
}

// 固定引数と可変長引数を組み合わせます。
func logMessage(level string, messages ...string) {
    for _, msg := range messages {
        fmt.Printf("[%s] %s\n", level, msg)
    }
}

// 可変長引数を別の可変長引数関数に渡します。
func printAll(args ...interface{}) {
    fmt.Println(args...) // fmt.Println自体も可変長引数です。
}

func main() {
    // 直接値を渡します。
    fmt.Println("合計(引数なし):", sum())
    fmt.Println("合計(1つ):", sum(5))
    fmt.Println("合計(複数):", sum(1, 2, 3, 4, 5))

    fmt.Println()

    // スライスを展開して渡します。
    nums := []int{10, 20, 30}
    fmt.Println("スライスから:", sum(nums...))

    fmt.Println()

    // 固定引数と可変長引数の組み合わせです。
    logMessage("INFO", "サーバーを起動しました", "ポート8080で待機中")
    logMessage("WARN") // メッセージなしでも動きます。

    fmt.Println()

    // interface{}の可変長引数
    printAll("Go言語", 42, true, 3.14)
}
概要

可変長引数は標準ライブラリでも広く使われており、『fmt.Println()』や『fmt.Printf()』も内部的に可変長引数を使っています。関数内で受け取った可変長引数(スライス)をそのまま別の可変長引数関数に渡すには、『args...』のように展開する必要があります。

可変長引数関数に何も引数を渡さなかった場合、関数内のスライスはnilになります。len()は0を返すため通常は問題ありませんが、スライス操作(インデックスアクセスなど)を行う前にnilチェックを行うと安全です。

関数の基本については『関数定義 / 複数戻り値』、クロージャについては『クロージャ / 無名関数』を参照してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。