👻

【Golang】仮引数に「...」でnilのデフォルト引数を実現

2022/07/15に公開

【zenn初投稿】
というかこういう系の記事を書くの初

golangでサーバサイドの実装を進めていく中で、学んだことを残します。
駆け足で書いたのでかなり雑です・・ お許しください

結論

仮引数で初期値nilとしたいときは

func NewSample(id int64, attribute ...string)

とすると、NewSample関数内でattribute == nil扱いにできる

やりたかったこと

以下のように

  • 関数の定義は1つ、
  • その関数の呼び出し元は2箇所以上

だった時に、「仮引数 = nil」みたいにして呼び出し側は引数を渡しても渡さなくても問題ないようにしたかった

function JoinStrFunc($str1, $str2 = "") {
    echo $str1 . $str2;
}

JoinStrFunc("初投稿");                             
=> // 初投稿
JoinStrFunc("初投稿なので", "書き方悪いですが許して下さい")   
=> // 初投稿なので 書き方悪いですが許して下さい

でもGolangには$str2 = ""のように仮引数にデフォルト引数を指定出来ない

じゃあどうするか?

Golangには「... string」のようにピリオド3つで「pack 演算子」というものが存在する
https://zenn.dev/mikankitten/articles/cfa2ef834e338e
こちらの記事を参考にめっちゃざっくり説明すると
... typeA
でtypeA型の引数が詰め込まれたsliceのようなもの

また、もう1つの性質として、... typeAのような可変長引数を仮引数として定義したときに呼び出し元で値を渡さないとnil扱いになる
でもコンパイルエラーにならない
⇨これの性質を使って関数の仮引数に実装する

実際のコード

func JoinStrFunc(str1 string, str2 ...string) string {
	if len(str2) != 0 {
	    return fmt.Sprintf("%s %s", str1, str2[0])
	}
	return str1
}

JoinStrFunc("初投稿"); // 第二引数なくても問題ない                         
=> // 初投稿
JoinStrFunc("初投稿なので", "書き方悪いですが許して下さい")   
=> // 初投稿なので 書き方悪いですが許して下さい

注意点としてはif len(str2) != 0 {でstr2に要素があるかのチェックを入れているところです。
理由は呼び出し元の第二引数で何も指定してないとstr2はnilなので文字列結合が出来ないからです。

所感

GolangではPHPやPythonとかみたく仮引数でデフォルト引数を指定出来ないのでちょっと不便に思った。
「Golang デフォルト引数」で検索すると他にもやり方あるみたい

Discussion