天天看點

Golang入門專題-Function

Function

函數定義的方式:func plus(a int, b int) int {}

package main

import "fmt"

func plus(a int, b int) int {

    return a + b
}
// 相同類型的入參可以這樣定義
func plusPlus(a, b, c int) int {
    return a + b + c
}

func main() {

    res := plus(1, 2)
    fmt.Println("1+2 =", res)

    res = plusPlus(1, 2, 3)
    fmt.Println("1+2+3 =", res)
}           

多傳回值

多傳回值是Go的一大特色之一,非常有用。

package main

import "fmt"

func vals() (int, int) {
    return 3, 7
}

func main() {

    a, b := vals()
    fmt.Println(a)
    fmt.Println(b)

    _, c := vals()
    fmt.Println(c)
}           

可變參數函數

這裡的可變是指入參長度可變。可變參數函數的入參類型為:...類型:

package main

import "fmt"

// 傳入之後,nums的實際類型就是[]int
func sum(nums ...int) {
    fmt.Print(nums, " ")
    total := 0

    for _, num := range nums {
        total += num
    }
    fmt.Println(total)
}

func main() {
    // 調用時隻需要按正常方式調用
    sum(1, 2)
    sum(1, 2, 3)
  
    // 也可以将已經是slice的結構傳入,但要在其後面加...(真神奇)
    nums := []int{1, 2, 3, 4}
    sum(nums...)
}           

上面的程式輸出:

$ go run variadic-functions.go 
[1 2] 3
[1 2 3] 6
[1 2 3 4] 10           

Closure閉包

這個翻譯實在拗口。Go 支援可以形成閉包的匿名函數。當你想内聯定義一個函數而不必命名時,匿名函數很有用。有些朋友已經想到了,沒錯,跟lambda有點像。閉包本質上是一個結構體,包含了函數入口和函數内定義的變量。

package main

import "fmt"

func intSeq() func() int {
    i := 0
    return func() int {
        i++
        return i
    }
}

func main() {

    nextInt := intSeq()

    fmt.Println(nextInt())
    fmt.Println(nextInt())
    fmt.Println(nextInt())

    newInts := intSeq()
    fmt.Println(newInts())
}           

上面的程式輸出:

$ go run closures.go
1
2
3
1           

閉包,到底包住了什麼呢?比如上面的例子,包住了一個“函數變量i”,每個intSeq函數都捕捉着自己的i,在每次調用函數時,i都實作有狀态變化。神奇,這搞出了類成員變量的感覺。

遞歸

遞歸兩要素:1. 自己調自己;2. 有終止條件。

package main

import "fmt"

func fact(n int) int {
    // 遞歸終止條件
    if n == 0 {
        return 1
    }
    return n * fact(n-1)
}

func main() {
    fmt.Println(fact(7))

    var fib func(n int) int
    // 閉包也可以是遞歸的,但這需要var在定義閉包之前用類型顯式聲明閉包
    fib = func(n int) int {
        if n < 2 {
            return n
        }

        return fib(n-1) + fib(n-2)
    }
    // 在main内部來說,fib就是一個閉包
    fmt.Println(fib(7))
}           

上面的程式輸出:

$ go run recursion.go 
5040
13           

每日一Tip

Go的函數非常靈活,結合閉包的使用,可以實作類似Java的lambda效果。

繼續閱讀