一文帶你熟悉Go語言中函數(shù)的使用
函數(shù)
函數(shù)的英文單詞是 Function,這個單詞還有著功能的意思。在 Go 語言中,函數(shù)是實現(xiàn)某一特定功能的代碼塊。函數(shù)代表著某個功能,可以在同一個地方多次使用,也可以在不同地方使用。因此使用函數(shù),可以提高代碼的復用性,減少代碼的冗余。
函數(shù)的聲明
通過案例了解函數(shù)的聲明有哪幾部分:
定義一個函數(shù),實現(xiàn)兩個數(shù)相加的功能,并將相加之后的結果返回。
func Add(num1 int, num2 int) int {
var sum int
sum += num1
sum += num2
return sum
}通過案例可以發(fā)現(xiàn),函數(shù)的聲明有5部分:
1、關鍵字
函數(shù)的關鍵字是 func,聲明函數(shù)必須以 func 關鍵字開始。
2、函數(shù)名
Go 推薦使用駝峰命名的方式,和變量的命名規(guī)則一樣,首字母大寫的函數(shù)名可以在包外訪問,小寫的只能在包內訪問。
3、參數(shù)列表
參數(shù)列表中聲明了在函數(shù)體里所使用到的變量。參數(shù)列表位于函數(shù)名后面,用括號包裹著,多個參數(shù)使用逗號分隔開。
4、返回值列表
返回值為函數(shù)執(zhí)行后的一個結果,上述代碼只有一個返回值,如果有多個返回值,需要用括號包裹著,返回值之間用逗號分隔開。
少數(shù)情況下,我們會聲明返回值的的名稱如 func Add(num1 int, num2 int) sum int {},多數(shù)情況下是不用聲明返回值的名稱的。
5、函數(shù)體
大括號內就是函數(shù)體,存放著函數(shù)的具體實現(xiàn)。 函數(shù)的第 3 第 4 部分可有可無,也就是說一個函數(shù)可以沒有參數(shù)和返回值。
Go 函數(shù)支持變長參數(shù)
在上面的案例中,實現(xiàn)的功能是對兩數(shù)求和,如果我們需要對多個數(shù)求和,但又不知道具體的數(shù)量,函數(shù)的參數(shù)該怎么聲明呢?這時可以聲明變長參數(shù)去接收多個參數(shù)。
func main() {
sum := Add(1, 2, 3, 4)
println(sum) // 10
}
func Add(nums ...int) int {
var sum int
for _, num := range nums {
sum += num
}
return sum
}變長參數(shù)作為形式參數(shù)可以接收不定的實際參數(shù),聲明變長參數(shù)需要在類型面前加上 ... ??勺儏?shù)實際上是一個切片,可以通過 for-range 去操作。
匿名函數(shù)
通常情況下,如果一個函數(shù)只使用一次,我們就可以定義成匿名函數(shù)。
func main() {
// 定義匿名函數(shù),直接調用
result := func(num1, num2 int) int {
return num1 + num2
}(1, 2)
println(result)
// 2、將匿名函數(shù)賦值給一個變量,由變量調用
resultFunc := func(num1, num2 int) int {
return num1 + num2
}
println(resultFunc(1, 2))
}聲明函數(shù)時,不指定函數(shù)名的函數(shù),叫做匿名函數(shù)。匿名函數(shù)可以直接調用,也可以通過賦值給變量,由變量調用。
閉包
閉包就是一個函數(shù)和其相關引用環(huán)境組合的一個整體。
import "fmt"
// 返回值為一個匿名函數(shù)
func getSum() func(int) int {
var sum int = 0
// 匿名函數(shù)
result := func(num int) int {
sum += num
return sum
}
return result
}
func main() {
f := getSum()
fmt.Println(f(1)) // 1
fmt.Println(f(2)) // 3
}- 閉包的本質就是一個匿名函數(shù),匿名函數(shù)里使用了定義它的函數(shù)(
getSum)里面的變量sum,就組成了閉包。 - 由上述代碼可知,匿名函數(shù)中所引用的變量
sum會一直保存在內存中。
init 函數(shù)
每個 go 文件都可以包含一個 init 函數(shù),它是一個初始化函數(shù),用于進行初始化的操作。
var print = getNum()
func getNum() int {
println("初始化變量")
return 1
}
func main() {
println("main...")
}
func init() {
println("init...")
}執(zhí)行結果:
初始化變量
init...
main...
- 根據(jù)執(zhí)行結果可知,它們的執(zhí)行順序為:全局變量 →
init函數(shù) →main函數(shù)。 - 多個
go文件都有init函數(shù)時,執(zhí)行順序為:先執(zhí)行所導入的模塊的init函數(shù),再執(zhí)行本文件的init函數(shù)。
函數(shù)參數(shù)詳解
形式參數(shù)與實際參數(shù)
在函數(shù)聲明的地方,參數(shù)列表中的參數(shù)被稱為形式參數(shù),簡稱形參;而在函數(shù)調用的時候所傳遞的參數(shù)被稱為實際參數(shù),簡稱實參。舉例說明:
func main() {
sum := Add(1, 2)
println(sum) // 3
}
func Add(num1 int, num2 int) int {
var sum int
sum += num1
sum += num2
return sum
}Add 后面的參數(shù)被稱為形參,而在 main 方法里,1 和 2 被稱為實參。
值傳遞
基本數(shù)據(jù)類型和數(shù)組作為實參時,默認是按 值傳遞,即進行值拷貝,在函數(shù)內修改它們的值,原來的值不會改變。舉例說明:
func main() {
num1, num2 := 1, 2
Swap(1, 2)
fmt.Printf("main 函數(shù)體內打?。簄um1: %d, num2: %d", num1, num2)
}
func Swap(num1 int, num2 int) {
num2, num1 = num1, num2
fmt.Printf("Swap 函數(shù)體內打?。簄um1: %d, num2: %d\n", num1, num2)
}執(zhí)行結果:
Swap 函數(shù)體內打?。簄um1: 2, num2: 1
main 函數(shù)體內打?。簄um1: 1, num2: 2
在 Swap 函數(shù)內,num1 和 num2 的值已經(jīng)相互交換,但是在 main 函數(shù)里,num1 和 num2 的值沒有發(fā)生變化。
func main() {
nums := [3]int{0, 1, 2}
Swap(nums)
fmt.Println("main 函數(shù)體內打?。簄ums: ", nums)
}
func Swap(nums [3]int) {
nums[0] = 1
fmt.Println("Swap 函數(shù)體內打?。簄ums: ", nums)
}同樣傳遞數(shù)組,在函數(shù)內修改數(shù)組的值,原數(shù)組的值并不會改變。 前面的文章有對指針進行了介紹,指出了通過 * 操作符,可以對指針所指向的變量的值進行修改,因此如果我們想要在函數(shù)內改變外部傳過來的參數(shù)的值,函數(shù)聲明時,形參類型指定為指針類型。
func main() {
num1, num2 := 1, 2
Swap(&num1, &num2)
fmt.Printf("main 函數(shù)體內打?。簄um1: %d, num2: %d", num1, num2)
}
func Swap(num1 *int, num2 *int) {
*num2, *num1 = *num1, *num2
fmt.Printf("Swap 函數(shù)體內打?。簄um1: %d, num2: %d\n", *num1, *num2)
}執(zhí)行結果:
Swap 函數(shù)體內打?。簄um1: 2, num2: 1
main 函數(shù)體內打?。簄um1: 2, num2: 1
通過結果可知,使用指針變量作為形參,在函數(shù)里是可以改變外部的參數(shù)的值的。
函數(shù)是一種數(shù)據(jù)類型
在 Go 里面,函數(shù)是一種數(shù)據(jù)類型,因此函數(shù)還可以有很多用法,如創(chuàng)建一個函數(shù)變量、將函數(shù)作為函數(shù)的形參,將函數(shù)作為函數(shù)的返回值等。
創(chuàng)建函數(shù)變量
func main() {
// 創(chuàng)建函數(shù)變量
hl := Hello
fmt.Printf("%T\n", hl) // func(string)
hl("cmy")
}
func Hello(name string) {
fmt.Printf("Hello %s", name)
}創(chuàng)建一個函數(shù)變量 hl,打印 hl 的類型 → func(string),通過 hl 變量調用函數(shù)。
作為函數(shù)的形參
import "fmt"
func main() {
Print("cmy", Hello)
}
func Hello(name string) {
fmt.Printf("Hello %s", name)
}
func Print(name string, f func(string)) {
f(name)
}定義函數(shù) Print ,聲明兩個參數(shù),一個參數(shù)是 name,為 string 類型的,另一個參數(shù)是 f,為函數(shù)類型。傳入 cmy 和 Hello 函數(shù),由 Print 函數(shù)去執(zhí)行 Hello 函數(shù)。
作為函數(shù)的返回值
import "fmt"
func main() {
f := Print()
f()
}
func Print() func() {
return func() {
fmt.Println("Hello,World!")
}
}通過Print 函數(shù)返回一個匿名函數(shù)函數(shù),這個匿名函數(shù)的功能是輸出 Hello,World!,使用 f 變量接收這個函數(shù)并調用。
基于函數(shù)自定義類型
type AddHandleFunc func(num1, num2 int) int
func main() {
sum := GetSum(1, 2, Add)
println(sum)
}
func Add(num1, num2 int) int {
return num1 + num2
}
func GetSum(num1, num2 int, handleFunc AddHandleFunc) int {
return handleFunc(num1, num2)
}基于函數(shù) func(num1, num2 int) int 自定義一個類型 AddHandleFunc,將它聲明為 GetSum 的形參,然后調用 GetSum 時,因為 Add 函數(shù)和 AddHandleFunc 是等價的,因此可以將 Add 當做實參傳進去。
小結
本文對函數(shù)的聲明進行介紹,根據(jù)一個案例了解了其組成的5部分。然后介紹了其一些特點如支持變長參數(shù)、傳遞參數(shù)時,實參按值傳遞等,最后根據(jù)函數(shù)在Go中是一種數(shù)據(jù)類型的特點,說明了其一些特別用法。
以上就是一文帶你熟悉Go語言中函數(shù)的使用的詳細內容,更多關于Go語言函數(shù)的資料請關注腳本之家其它相關文章!
相關文章
Go/C語言LeetCode題解997找到小鎮(zhèn)法官
這篇文章主要為大家介紹了Go語言LeetCode題解997找到小鎮(zhèn)的法官示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-12-12
使用go net實現(xiàn)簡單的redis通信協(xié)議
本文主要介紹了go net實現(xiàn)簡單的redis通信協(xié)議,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-12-12

