関数
関数は、データ(引数)の入力、データの処理、処理結果(戻り値)の返却をするものです。
たとえば、組み込み関数len
は、データの入力、データ長の計算、データ長の返却をします。
入力 → 処理 → 出力
(引数) (戻り値)
関数の宣言と呼び出し
関数の宣言と呼び出し方法をパターン別に説明します。
基本
関数宣言の基本形は、次の通りです。
func 関数名(引数の宣言) 戻り値の宣言 {
処理
return 戻り値
}
関数呼び出しの基本形は、次の通りです。
戻り値の変数 := 関数名(引数)
では、実際のサンプルを見ていきましょう。
まずは引数と戻り値を持たない関数です。 他のプログラミング言語のようにvoidは指定しません。 また、引数と戻り値のどちらか一方だけを省略できます。
// 挨拶する関数。引数と戻り値を持たない
func sayHello() {
fmt.Println("hello")
}
// 関数呼び出し
sayHello() // hello
次に引数と戻り値を持つ関数です。
引数には変数名と型を宣言します。複数ある場合はカンマで区切ります。
// 足し算した結果を返す
func add(x int, y int) int {
return x + y
}
// 関数呼び出し
// 戻り値を変数に代入して使用
result := add(1, 2)
fmt.Println(result) // 3
引数に同じ型が並ぶ場合はまとめて宣言できます。
// 足し算した結果を返す
func add(x, y int) int {
return x + y
}
可変長引数
同じ型の可変長の引数を宣言できます。 ただし、宣言できるのは引数の末尾にひとつだけです。
可変長引数の型は...型
の形式で宣言します。
可変長引数は、宣言した型のスライスとして受け取ります。
たとえば、次のサンプルの可変長引数params
はint
型のスライスです。
また、関数呼び出し側は可変長引数にスライスをまとめて指定できます。
その場合はスライスの変数名...
の形式で指定します。
// 足し算した結果を返す
func add(params ...int) int {
var n int
for _, v := range params {
n += v
}
return n
}
// 関数呼び出し
// 引数は何個でもOK
fmt.Println(add(1, 2, 3, 4, 5)) // 15
// スライスをまとめて引数に指定できる
s := []int{3, 3, 3}
fmt.Println(add(s...)) // 9
複数の戻り値
戻り値は複数の値を返せます。戻り値の型は括弧で括って表現します。
// 指定されたスライスの長さと容量を返す
func lenCap(slice []int) (int, int) {
l := len(slice)
c := cap(slice)
return l, c
}
// 関数呼び出し
a := make([]int, 1, 3)
l, c := lenCap(a) // 1 3
名前付き戻り値
戻り値の宣言に変数名をつけることができます。
これは、戻り値に同じ型が複数並んだ際に、それぞれの戻り値が何であるかを理解する助けとなります。
return
の戻り値の指定は省略できます。
// 指定されたスライスの長さと容量を返す
func lenCap(slice []int) (l, c int) {
// 名前付き戻り値の変数を改めて宣言する必要はない
l = len(slice)
c = cap(slice)
return
}
呼び出し側で不要な戻り値はアンダースコアにすると破棄できます。
l, _ := lenCap(a) // 2つ目の戻り値は使わない
関数の型
関数を型として表現できます。
基本形はfunc(引数宣言) 戻り値宣言
です。
関数は、変数や引数や戻り値として扱うことができます。
func add(x, y int) int {
return x + y
}
func main() {
// 関数を変数の型として宣言
var f func(int, int) int
// 関数を変数に代入して実行
f = add
fmt.Println(f(1, 2)) // 3
}
無名関数
名前のない関数を扱えます。
func main() {
// その場で実行
func() {
fmt.Println("unmnamed1")
}() // unnamed1
// 変数に代入して実行
f := func() {
fmt.Println("unnamed2")
}
f() // unnamed2
}
クロージャ
関数の外にある変数を使用できます。
func getCounter() func() int {
count := 0
return func() int {
// 関数の外にある変数countを使用
count++
return count
}
}
func main() {
counter := getCounter()
fmt.Println(counter()) // 1
fmt.Println(counter()) // 2
}