函式
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
}- Links
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) // 10Recursion
遞迴函式,閉包也可以是遞迴的。
// 階乘
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)
}- Links
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))