5.1. 函數聲明

函數聲明包括函數名、形式參數列表、返回值列表(可省略)以及函數體。

func name(parameter-list) (result-list) {
    body
}

形式參數列表描述了函數的參數名以及參數類型。這些參數作為局部變量,其值由參數調用者提供。返回值列表描述了函數返回值的變量名以及類型。如果函數返回一個無名變量或者沒有返回值,返回值列表的括號是可以省略的。如果一個函數聲明不包括返回值列表,那麼函數體執行完畢後,不會返回任何值。在hypot函數中:

func hypot(x, y float64) float64 {
    return math.Sqrt(x*x + y*y)
}
fmt.Println(hypot(3,4)) // "5"

x和y是形參名,3和4是調用時的傳入的實參,函數返回了一個float64類型的值。 返回值也可以像形式參數一樣被命名。在這種情況下,每個返回值被聲明成一個局部變量,並根據該返回值的類型,將其初始化為該類型的零值。 如果一個函數在聲明時,包含返回值列表,該函數必須以 return語句結尾,除非函數明顯無法運行到結尾處。例如函數在結尾時調用了panic異常或函數中存在無限循環。

正如hypot一樣,如果一組形參或返回值有相同的類型,我們不必為每個形參都寫出參數類型。下面2個聲明是等價的:

func f(i, j, k int, s, t string)                 { /* ... */ }
func f(i int, j int, k int,  s string, t string) { /* ... */ }

下面,我們給出4種方法聲明擁有2個int型參數和1個int型返回值的函數.blank identifier(譯者注:即下文的_符號)可以強調某個參數未被使用。

func add(x int, y int) int   {return x + y}
func sub(x, y int) (z int)   { z = x - y; return}
func first(x int, _ int) int { return x }
func zero(int, int) int      { return 0 }

fmt.Printf("%T\n", add)   // "func(int, int) int"
fmt.Printf("%T\n", sub)   // "func(int, int) int"
fmt.Printf("%T\n", first) // "func(int, int) int"
fmt.Printf("%T\n", zero)  // "func(int, int) int"

函數的類型被稱為函數的簽名。如果兩個函數形式參數列表和返回值列表中的變量類型一一對應,那麼這兩個函數被認為有相同的類型或簽名。形參和返回值的變量名不影響函數簽名,也不影響它們是否可以以省略參數類型的形式表示。

每一次函數調用都必須按照聲明順序為所有參數提供實參(參數值)。在函數調用時,Go語言沒有默認參數值,也沒有任何方法可以通過參數名指定形參,因此形參和返回值的變量名對於函數調用者而言沒有意義。

在函數體中,函數的形參作為局部變量,被初始化為調用者提供的值。函數的形參和有名返回值作為函數最外層的局部變量,被存儲在相同的詞法塊中。

實參通過值的方式傳遞,因此函數的形參是實參的拷貝。對形參進行修改不會影響實參。但是,如果實參包括引用類型,如指針,slice(切片)、map、function、channel等類型,實參可能會由於函數的間接引用被修改。

你可能會偶爾遇到沒有函數體的函數聲明,這表示該函數不是以Go實現的。這樣的聲明定義了函數簽名。

package math

func Sin(x float64) float //implemented in assembly language