関数

Go 言語げんご関数かんすう:クロージャ、高階こうかい関数かんすう再帰さいき

Closures

クロージャは外部がいぶスコープの変数へんすうをキャプチャしてアクセスできる無名むめい関数かんすう

func counter() func() int {
    count := 0
    return func() int {
        count++
        return count
    }
}

func main() {
    c := counter()
    fmt.Println(c()) // 1
    fmt.Println(c()) // 2
    fmt.Println(c()) // 3
}

High Order Function

高階こうかい関数かんすう関数かんすう引数ひきすうとしてる、または関数かんすうかえす。

// 関数を引数として受け取る
func apply(nums []int, fn func(int) int) []int {
    result := make([]int, len(nums))
    for i, v := range nums {
        result[i] = fn(v)
    }
    return result
}

// 使用例
double := func(n int) int { return n * 2 }
nums := []int{1, 2, 3, 4}
doubled := apply(nums, double) // [2, 4, 6, 8]

Filter の例

func filter(nums []int, fn func(int) bool) []int {
    var result []int
    for _, v := range nums {
        if fn(v) {
            result = append(result, v)
        }
    }
    return result
}

// 使用例
isEven := func(n int) bool { return n%2 == 0 }
evens := filter([]int{1, 2, 3, 4, 5, 6}, isEven) // [2, 4, 6]

Reduce の例

func reduce(nums []int, fn func(int, int) int, initial int) int {
    result := initial
    for _, v := range nums {
        result = fn(result, v)
    }
    return result
}

// 使用例
sum := reduce([]int{1, 2, 3, 4}, func(a, b int) int { return a + b }, 0) // 10

Recursion

再帰さいき関数かんすう、クロージャも再帰さいきにできる。

// 階乗
func factorial(n int) int {
    if n <= 1 {
        return 1
    }
    return n * factorial(n-1)
}

// フィボナッチ数列
func fibonacci(n int) int {
    if n <= 1 {
        return n
    }
    return fibonacci(n-1) + fibonacci(n-2)
}

クロージャの再帰

var fib func(n int) int
fib = func(n int) int {
    if n <= 1 {
        return n
    }
    return fib(n-1) + fib(n-2)
}

Methods

メソッドはかた付加ふかされた関数かんすう

Receiver Type

種類しゅるい特性とくせい使用しよう場面ばめん
Value Receiverあたいをコピー、もとあたい影響えいきょうしない操作そうさちいさい struct
Pointer Receiverもとのメモリアドレスを操作そうさ変更へんこう操作そうさおおきい struct
type Rectangle struct {
    Width, Height float64
}

// Value Receiver - 元の値を変更しない
func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

// Pointer Receiver - 元の値を変更できる
func (r *Rectangle) Scale(factor float64) {
    r.Width *= factor
    r.Height *= factor
}

func main() {
    rect := Rectangle{10, 5}
    fmt.Println(rect.Area()) // 50

    rect.Scale(2)
    fmt.Println(rect.Area()) // 200
}

Defer

遅延ちえん実行じっこう、LIFO(後入あといれ先出さきだし)順序じゅんじょ実行じっこう、リソースのクリーンアップによく使つかわれる。

func readFile(filename string) error {
    f, err := os.Open(filename)
    if err != nil {
        return err
    }
    defer f.Close() // 関数終了時に自動的にクローズ

    // ファイルを読み取り...
    return nil
}

複数の Defer

func main() {
    defer fmt.Println("1")
    defer fmt.Println("2")
    defer fmt.Println("3")
    // 出力順序: 3, 2, 1 (LIFO)
}

Defer とエラー処理

func doSomething() (err error) {
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("recovered: %v", r)
        }
    }()

    // panic を起こす可能性のある操作...
    return nil
}

Variadic Functions

可変かへんちょう引数ひきすう関数かんすう任意にんいかず引数ひきすうる。

func sum(nums ...int) int {
    total := 0
    for _, n := range nums {
        total += n
    }
    return total
}

func main() {
    fmt.Println(sum(1, 2))          // 3
    fmt.Println(sum(1, 2, 3, 4, 5)) // 15

    // slice を展開
    nums := []int{1, 2, 3}
    fmt.Println(sum(nums...)) // 6
}

Sorting

sort パッケージを使用しようしてソート。

import "sort"

// 基本ソート
nums := []int{3, 1, 4, 1, 5, 9}
sort.Ints(nums) // [1, 1, 3, 4, 5, 9]

strs := []string{"banana", "apple", "cherry"}
sort.Strings(strs) // ["apple", "banana", "cherry"]

カスタムソート

type Person struct {
    Name string
    Age  int
}

people := []Person{
    {"Alice", 30},
    {"Bob", 25},
    {"Charlie", 35},
}

// 年齢でソート
sort.Slice(people, func(i, j int) bool {
    return people[i].Age < people[j].Age
})

sort.Interface の実装

type ByAge []Person

func (a ByAge) Len() int           { return len(a) }
func (a ByAge) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }

sort.Sort(ByAge(people))

関連トピック