## 5.1. 函數聲明

函數聲明包括函數名、形式參數列表、返迴值列表（可省略）以及函數體。

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

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

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

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

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

```Go
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(譯者註：卽下文的_符號)可以強調某個參數未被使用。

```Go
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實現的。這樣的聲明定義了函數標識符。

```Go
package math

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