Go/func
表示
< Go
Goのfuncキーワードは、関数を定義するために使用される予約語です。関数はGoのプログラミングにおける基本的な構成要素であり、再利用可能なコードブロックを表します。
1. 基本的な関数宣言
[編集]func 関数名(パラメータリスト) (戻り値の型) { // 関数の本体(処理内容) return 戻り値 }
- 例
func add(x int, y int) int { return x + y }
2. パラメータと戻り値のバリエーション
[編集]同一型の複数パラメータの省略形
[編集]func add(x, y int) int { return x + y }
複数の戻り値
[編集]// 標準的な複数戻り値 func divide(x, y float64) (float64, error) { if y == 0.0 { return 0.0, errors.New("division by zero") } return x / y, nil }
名前付き戻り値
[編集]// 名前付き戻り値を使用 func divide(x, y float64) (value float64, err error) { if y == 0.0 { err = errors.New("division by zero") // value には代入していないのでゼロ値の 0.0 となる } else { value = x / y // err には代入していないのでゼロ値の nil となる } return // 空のreturnでも名前付き変数の値が返される }
3. 型パラメータを持つ関数(ジェネリクス)
[編集]Go 1.18から導入されたジェネリクス機能により、型パラメータを持つ関数が定義可能になりました:
通常の関数
[編集]func Max(a, b int) int { if a > b { return a } return b } // int型に限定される
ジェネリック関数
[編集]func Max[T constraints.Ordered](a, b T) T { if a > b { return a } return b } // 比較可能な任意の型に対応
- 使用例
maxInt := Max[int](10, 20) // 明示的に型を指定 maxFloat := Max(10.5, 20.5) // 型推論により自動的にfloat64型と判断
4. レシーバを持つ関数(メソッド)
[編集]func (レシーバ レシーバの型) メソッド名(パラメータリスト) 戻り値の型 { // メソッドの本体 }
値レシーバを使用したメソッド
[編集]type Rectangle struct { width, height float64 } func (r Rectangle) Area() float64 { return r.width * r.height } // 元の構造体は変更されない
ポインタレシーバを使用したメソッド
[編集]func (r *Rectangle) Scale(factor float64) { r.width *= factor r.height *= factor } // 元の構造体が変更される
5. 型のメソッドとジェネリック型のメソッドの比較
[編集]通常の型のメソッド
[編集]type IntList []int func (l IntList) Sum() int { total := 0 for _, v := range l { total += v } return total } // int型のスライスにしか対応できない
ジェネリック型のメソッド
[編集]type List[T constraints.Ordered] []T func (l List[T]) First() (T, bool) { var zero T if len(l) == 0 { return zero, false } return l[0], true } // 様々な型のスライスに対応可能
6. 関数型と高階関数
[編集]関数型の宣言
[編集]type Operation func(int, int) int
関数を引数として受け取る関数
[編集]func applyFunc(fn func(int, int) int, a, b int) int { return fn(a, b) } // 使用例 result := applyFunc(func(x, y int) int { return x + y }, 10, 20)
関数を返す関数
[編集]func makeAdder(x int) func(int) int { return func(y int) int { return x + y } } // 使用例 add5 := makeAdder(5) result := add5(3) // 8
7. 無名関数とクロージャ
[編集]単純な無名関数
[編集]add := func(x, y int) int { return x + y } result := add(3, 4) // 7
クロージャとして機能する無名関数
[編集]func makeCounter() func() int { count := 0 return func() int { count++ // 外部スコープの変数countを参照・変更 return count } } // 使用例 counter1 := makeCounter() fmt.Println(counter1()) // 1 fmt.Println(counter1()) // 2
8. 標準引数と可変長引数の比較
[編集]標準的な引数リスト
[編集]func average(a, b, c int) float64 { return float64(a+b+c) / 3 } avg := average(10, 20, 30) // 正確に3つの引数が必要
可変長引数
[編集]func average(nums ...int) float64 { total := 0 for _, num := range nums { total += num } return float64(total) / float64(len(nums)) } avg1 := average(10, 20, 30) // 3つの引数 avg2 := average(10, 20, 30, 40, 50) // 5つの引数も可能
9. その他の特殊なパターン
[編集]defer文との組み合わせ
[編集]func readFile(filename string) error { file, err := os.Open(filename) if err != nil { return err } defer file.Close() // 関数終了時に実行される // ファイル処理... return nil }
インターフェース定義でのメソッドシグネチャ
[編集]type Writer interface { Write([]byte) (int, error) }
init関数とmain関数
[編集]// パッケージ初期化時に自動的に実行される func init() { // 初期化コード } // プログラムのエントリーポイント func main() { // メインコード }
10. funcキーワードの特記事項
[編集]- Goでは関数はファーストクラスオブジェクトです(変数に代入可能、引数や戻り値として使用可能)。
- 関数のオーバーロード(同名で引数の異なる複数の関数を定義すること)はサポートされていません。
- すべての関数に対して型パラメータを使用できるわけではなく、main関数などは型パラメータを持てません。
- メソッドレシーバに型パラメータを持つ型を使用可能です。
- 関数の型パラメータはメソッドやフィールドを持つインターフェースで制約できます。
- 標準ライブラリの
constraintsパッケージには、よく使われる型制約が定義されています(Ordered, Integersなど)。
Goのfuncキーワードはこのように多様な形式で使用され、特にGo 1.18以降のジェネリクス機能の追加により、より柔軟な関数とメソッドの定義が可能になりました。