golang學習筆記9:函數參數與返回值

按值傳遞和按引用傳遞

Go 默認使用按值傳遞來傳遞參數,也就是傳遞參數的副本。函數接收參數副本之後,在使用變量的過程中可能對副本的值進行更改,但不會影響到原來的變量,比如 Function(arg1)。

如果你希望函數可以直接修改參數的值,而不是對參數的副本進行操作,你需要將參數的地址(變量名前面添加&符號,比如 &variable)傳遞給函數,這就是按引用傳遞,比如 Function(&arg1),此時傳遞給函數的是一個指針。如果傳遞給函數的是一個指針,指針的值(一個地址)會被複制,但指針的值所指向的地址上的值不會被複制;我們可以通過這個指針的值來修改這個值所指向的地址上的值。(譯者注:指針也是變量類型,有自己的地址和值,通常指針的值指向一個變量的地址。所以,按引用傳遞也是按值傳遞。)

幾乎在任何情況下,傳遞指針(一個32位或者64位的值)的消耗都比傳遞副本來得少。

在函數調用時,像切片(slice)、字典(map)、接口(interface)、通道(channel)這樣的引用類型都是默認使用引用傳遞(即使沒有顯式的指出指針)。

傳遞變長參數

如果函數的最後一個參數是採用 ...type 的形式,那麼這個函數就可以處理一個變長的參數,這個長度可以爲 0,這樣的函數稱爲變參函數。

func myFunc(a, b, arg ...int) {}

這個函數接受一個類似某個類型的 slice 的參數 ,該參數可以通過for 循環結構迭代。

示例函數和調用:

func Greeting(prefix string, who ...string)
Greeting("hello:", "Joe", "Anna", "Eileen")

在 Greeting 函數中,變量 who 的值爲 []string{"Joe", "Anna", "Eileen"}。

如果參數被存儲在一個數組 arr 中,則可以通過 arr... 的形式來傳遞參數調用變參函數。

defer 和追蹤

關鍵字 defer 允許我們推遲到函數返回之後(或任意位置執行 return 語句之後)一刻才執行某個語句或函數(爲什麼要在返回之後才執行這些語句?因爲 return 語句同樣可以包含一些操作,而不是單純地返回某個值)。關鍵字 defer 的用法類似於面向對象編程語言 Java 和 C# 的 finally 語句塊,它一般用於釋放某些已分配的資源。

package mainimport "fmt"func main() {
    function1()
}func function1() {
    fmt.Printf("In function1 at the top\n")    
defer function2()
    fmt.Printf("In function1 at the bottom!\n")}
func function2() {
    fmt.Printf("function2: Deferred until the end of the calling function!")
}

輸出:

In Function1 at the top
In Function1 at the bottom!
Function2: Deferred until the end of the calling function!

當有多個 defer 行爲被註冊時,它們會以逆序執行(類似棧,即後進先出):

func f() {    for i := 0; i < 5; i++ {
        defer fmt.Printf("%d ", i)
    }
}

上面的代碼將會輸出:4 3 2 1 0。

將函數作爲參數

package main
import ("fmt")
func main() {
    callback(1, Add)
}
func Add(a, b int) {
    fmt.Printf("The sum of %d and %d is: %d\n", a, b, a+b)
}
func callback(y int, f func(int, int)) {
    f(y, 2) // this becomes Add(1, 2)
}

閉包

當我們不希望給函數起名字的時候,可以使用匿名函數,例如:func(x, y int) int { return x + y }。

這樣的一個函數不能夠獨立存在(編譯器會返回錯誤:non-declaration statement outside function body),但可以被賦值於某個變量,即保存函數的地址到變量中:fplus := func(x, y int) int { return x + y },然後通過變量名對函數進行調用:fplus(3,4)。

當然,也可以直接對匿名函數進行調用:func(x, y int) int { return x + y } (3, 4)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章