6. 函數(Function)
函數是什么?
函數是一塊執行特定任務的代碼。一個函數是在輸入源基礎上,通過執行一系列的算法,生成預期的輸出。
函數的聲明
在 Go 語言中,函數聲明通用語法如下:
func functionname(parametername type) returntype {
// 函數體(具體實現的功能)
}
函數的聲明以關鍵詞 func
開始,后面緊跟自定義的函數名 functionname (函數名)
。函數的參數列表定義在 (
和 )
之間,返回值的類型則定義在之后的 returntype (返回值類型)
處。聲明一個參數的語法采用 參數名 參數類型 的方式,任意多個參數采用類似 (parameter1 type, parameter2 type) 即(參數1 參數1的類型,參數2 參數2的類型)
的形式指定。之后包含在 {
和 }
之間的代碼,就是函數體。
函數中的參數列表和返回值並非是必須的,所以下面這個函數的聲明也是有效的
func functionname() {
// 譯注: 表示這個函數不需要輸入參數,且沒有返回值
}
示例函數
我們以寫一個計算商品價格的函數為例,輸入參數是單件商品的價格和商品的個數,兩者的乘積為商品總價,作為函數的輸出值。
func calculateBill(price int, no int) int {
var totalPrice = price * no // 商品總價 = 商品單價 * 數量
return totalPrice // 返回總價
}
上述函數有兩個整型的輸入 price
和 no
,返回值 totalPrice
為 price
和 no
的乘積,也是整數類型。
如果有連續若干個參數,它們的類型一致,那么我們無須一一羅列,只需在最后一個參數后添加該類型。 例如,price int, no int
可以簡寫為 price, no int
,所以示例函數也可寫成
func calculateBill(price, no int) int {
var totalPrice = price * no
return totalPrice
}
現在我們已經定義了一個函數,我們要在代碼中嘗試着調用它。調用函數的語法為 functionname(parameters)
。調用示例函數的方法如下:
calculateBill(10, 5)
完成了示例函數聲明和調用后,我們就能寫出一個完整的程序,並把商品總價打印在控制台上:
package main
import (
"fmt"
)
func calculateBill(price, no int) int {
var totalPrice = price * no
return totalPrice
}
func main() {
price, no := 90, 6 // 定義 price 和 no,默認類型為 int
totalPrice := calculateBill(price, no)
fmt.Println("Total price is", totalPrice) // 打印到控制台上
}
該程序在控制台上打印的結果為
Total price is 540
多返回值
Go 語言支持一個函數可以有多個返回值。我們來寫個以矩形的長和寬為輸入參數,計算並返回矩形面積和周長的函數 rectProps
。矩形的面積是長度和寬度的乘積, 周長是長度和寬度之和的兩倍。即:
面積 = 長 * 寬
周長 = 2 * ( 長 + 寬 )
package main
import (
"fmt"
)
func rectProps(length, width float64)(float64, float64) {
var area = length * width
var perimeter = (length + width) * 2
return area, perimeter
}
func main() {
area, perimeter := rectProps(10.8, 5.6)
fmt.Printf("Area %f Perimeter %f", area, perimeter)
}
如果一個函數有多個返回值,那么這些返回值必須用 (
和 )
括起來。func rectProps(length, width float64)(float64, float64)
示例函數有兩個 float64 類型的輸入參數 length
和 width
,並返回兩個 float64 類型的值。該程序在控制台上打印結果為
Area 60.480000 Perimeter 32.800000
命名返回值
從函數中可以返回一個命名值。一旦命名了返回值,可以認為這些值在函數第一行就被聲明為變量了。
上面的 rectProps 函數也可用這個方式寫成:
func rectProps(length, width float64)(area, perimeter float64) {
area = length * width
perimeter = (length + width) * 2
return // 不需要明確指定返回值,默認返回 area, perimeter 的值
}
請注意, 函數中的 return 語句沒有顯式返回任何值。由於 area 和 perimeter 在函數聲明中指定為返回值, 因此當遇到 return 語句時, 它們將自動從函數返回。
空白符
_ 在 Go 中被用作空白符,可以用作表示任何類型的任何值。
我們繼續以 rectProps
函數為例,該函數計算的是面積和周長。假使我們只需要計算面積,而並不關心周長的計算結果,該怎么調用這個函數呢?這時,空白符 _ 就上場了。
下面的程序我們只用到了函數 rectProps
的一個返回值 area
package main
import (
"fmt"
)
func rectProps(length, width float64) (float64, float64) {
var area = length * width
var perimeter = (length + width) * 2
return area, perimeter
}
func main() {
area, _ := rectProps(10.8, 5.6) // 返回值周長被丟棄
fmt.Printf("Area %f ", area)
}
在程序的
area, _ := rectProps(10.8, 5.6)
這一行,我們看到空白符_
用來跳過不要的計算結果。