一文帶你熟悉Go語(yǔ)言中函數(shù)的使用
函數(shù)
函數(shù)的英文單詞是 Function
,這個(gè)單詞還有著功能的意思。在 Go 語(yǔ)言中,函數(shù)是實(shí)現(xiàn)某一特定功能的代碼塊。函數(shù)代表著某個(gè)功能,可以在同一個(gè)地方多次使用,也可以在不同地方使用。因此使用函數(shù),可以提高代碼的復(fù)用性,減少代碼的冗余。
函數(shù)的聲明
通過(guò)案例了解函數(shù)的聲明有哪幾部分:
定義一個(gè)函數(shù),實(shí)現(xiàn)兩個(gè)數(shù)相加的功能,并將相加之后的結(jié)果返回。
func Add(num1 int, num2 int) int { var sum int sum += num1 sum += num2 return sum }
通過(guò)案例可以發(fā)現(xiàn),函數(shù)的聲明有5部分:
1、關(guān)鍵字
函數(shù)的關(guān)鍵字是 func
,聲明函數(shù)必須以 func
關(guān)鍵字開(kāi)始。
2、函數(shù)名
Go
推薦使用駝峰命名的方式,和變量的命名規(guī)則一樣,首字母大寫(xiě)的函數(shù)名可以在包外訪問(wèn),小寫(xiě)的只能在包內(nèi)訪問(wèn)。
3、參數(shù)列表
參數(shù)列表中聲明了在函數(shù)體里所使用到的變量。參數(shù)列表位于函數(shù)名后面,用括號(hào)包裹著,多個(gè)參數(shù)使用逗號(hào)分隔開(kāi)。
4、返回值列表
返回值為函數(shù)執(zhí)行后的一個(gè)結(jié)果,上述代碼只有一個(gè)返回值,如果有多個(gè)返回值,需要用括號(hào)包裹著,返回值之間用逗號(hào)分隔開(kāi)。
少數(shù)情況下,我們會(huì)聲明返回值的的名稱(chēng)如 func Add(num1 int, num2 int) sum int {}
,多數(shù)情況下是不用聲明返回值的名稱(chēng)的。
5、函數(shù)體
大括號(hào)內(nèi)就是函數(shù)體,存放著函數(shù)的具體實(shí)現(xiàn)。 函數(shù)的第 3
第 4
部分可有可無(wú),也就是說(shuō)一個(gè)函數(shù)可以沒(méi)有參數(shù)和返回值。
Go 函數(shù)支持變長(zhǎng)參數(shù)
在上面的案例中,實(shí)現(xiàn)的功能是對(duì)兩數(shù)求和,如果我們需要對(duì)多個(gè)數(shù)求和,但又不知道具體的數(shù)量,函數(shù)的參數(shù)該怎么聲明呢?這時(shí)可以聲明變長(zhǎng)參數(shù)去接收多個(gè)參數(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 }
變長(zhǎng)參數(shù)作為形式參數(shù)可以接收不定的實(shí)際參數(shù),聲明變長(zhǎng)參數(shù)需要在類(lèi)型面前加上 ...
??勺儏?shù)實(shí)際上是一個(gè)切片,可以通過(guò) for-range
去操作。
匿名函數(shù)
通常情況下,如果一個(gè)函數(shù)只使用一次,我們就可以定義成匿名函數(shù)。
func main() { // 定義匿名函數(shù),直接調(diào)用 result := func(num1, num2 int) int { return num1 + num2 }(1, 2) println(result) // 2、將匿名函數(shù)賦值給一個(gè)變量,由變量調(diào)用 resultFunc := func(num1, num2 int) int { return num1 + num2 } println(resultFunc(1, 2)) }
聲明函數(shù)時(shí),不指定函數(shù)名的函數(shù),叫做匿名函數(shù)。匿名函數(shù)可以直接調(diào)用,也可以通過(guò)賦值給變量,由變量調(diào)用。
閉包
閉包就是一個(gè)函數(shù)和其相關(guān)引用環(huán)境組合的一個(gè)整體。
import "fmt" // 返回值為一個(gè)匿名函數(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 }
- 閉包的本質(zhì)就是一個(gè)匿名函數(shù),匿名函數(shù)里使用了定義它的函數(shù)(
getSum
)里面的變量sum
,就組成了閉包。 - 由上述代碼可知,匿名函數(shù)中所引用的變量
sum
會(huì)一直保存在內(nèi)存中。
init 函數(shù)
每個(gè) go
文件都可以包含一個(gè) init
函數(shù),它是一個(gè)初始化函數(shù),用于進(jìn)行初始化的操作。
var print = getNum() func getNum() int { println("初始化變量") return 1 } func main() { println("main...") } func init() { println("init...") }
執(zhí)行結(jié)果:
初始化變量
init...
main...
- 根據(jù)執(zhí)行結(jié)果可知,它們的執(zhí)行順序?yàn)椋喝肿兞?→
init
函數(shù) →main
函數(shù)。 - 多個(gè)
go
文件都有init
函數(shù)時(shí),執(zhí)行順序?yàn)椋合葓?zhí)行所導(dǎo)入的模塊的init
函數(shù),再執(zhí)行本文件的init
函數(shù)。
函數(shù)參數(shù)詳解
形式參數(shù)與實(shí)際參數(shù)
在函數(shù)聲明的地方,參數(shù)列表中的參數(shù)被稱(chēng)為形式參數(shù),簡(jiǎn)稱(chēng)形參;而在函數(shù)調(diào)用的時(shí)候所傳遞的參數(shù)被稱(chēng)為實(shí)際參數(shù),簡(jiǎn)稱(chēng)實(shí)參。舉例說(shuō)明:
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ù)被稱(chēng)為形參,而在 main
方法里,1
和 2
被稱(chēng)為實(shí)參。
值傳遞
基本數(shù)據(jù)類(lèi)型和數(shù)組作為實(shí)參時(shí),默認(rèn)是按 值傳遞,即進(jìn)行值拷貝,在函數(shù)內(nèi)修改它們的值,原來(lái)的值不會(huì)改變。舉例說(shuō)明:
func main() { num1, num2 := 1, 2 Swap(1, 2) fmt.Printf("main 函數(shù)體內(nèi)打?。簄um1: %d, num2: %d", num1, num2) } func Swap(num1 int, num2 int) { num2, num1 = num1, num2 fmt.Printf("Swap 函數(shù)體內(nèi)打?。簄um1: %d, num2: %d\n", num1, num2) }
執(zhí)行結(jié)果:
Swap 函數(shù)體內(nèi)打?。簄um1: 2, num2: 1
main 函數(shù)體內(nèi)打印:num1: 1, num2: 2
在 Swap
函數(shù)內(nèi),num1
和 num2
的值已經(jīng)相互交換,但是在 main
函數(shù)里,num1
和 num2
的值沒(méi)有發(fā)生變化。
func main() { nums := [3]int{0, 1, 2} Swap(nums) fmt.Println("main 函數(shù)體內(nèi)打印:nums: ", nums) } func Swap(nums [3]int) { nums[0] = 1 fmt.Println("Swap 函數(shù)體內(nèi)打?。簄ums: ", nums) }
同樣傳遞數(shù)組,在函數(shù)內(nèi)修改數(shù)組的值,原數(shù)組的值并不會(huì)改變。 前面的文章有對(duì)指針進(jìn)行了介紹,指出了通過(guò) *
操作符,可以對(duì)指針?biāo)赶虻淖兞康闹颠M(jìn)行修改,因此如果我們想要在函數(shù)內(nèi)改變外部傳過(guò)來(lái)的參數(shù)的值,函數(shù)聲明時(shí),形參類(lèi)型指定為指針類(lèi)型。
func main() { num1, num2 := 1, 2 Swap(&num1, &num2) fmt.Printf("main 函數(shù)體內(nèi)打印:num1: %d, num2: %d", num1, num2) } func Swap(num1 *int, num2 *int) { *num2, *num1 = *num1, *num2 fmt.Printf("Swap 函數(shù)體內(nèi)打?。簄um1: %d, num2: %d\n", *num1, *num2) }
執(zhí)行結(jié)果:
Swap 函數(shù)體內(nèi)打?。簄um1: 2, num2: 1
main 函數(shù)體內(nèi)打印:num1: 2, num2: 1
通過(guò)結(jié)果可知,使用指針變量作為形參,在函數(shù)里是可以改變外部的參數(shù)的值的。
函數(shù)是一種數(shù)據(jù)類(lèi)型
在 Go
里面,函數(shù)是一種數(shù)據(jù)類(lèi)型,因此函數(shù)還可以有很多用法,如創(chuàng)建一個(gè)函數(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)建一個(gè)函數(shù)變量 hl
,打印 hl
的類(lèi)型 → func(string)
,通過(guò) hl
變量調(diào)用函數(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
,聲明兩個(gè)參數(shù),一個(gè)參數(shù)是 name
,為 string
類(lèi)型的,另一個(gè)參數(shù)是 f
,為函數(shù)類(lèi)型。傳入 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!") } }
通過(guò)Print
函數(shù)返回一個(gè)匿名函數(shù)函數(shù),這個(gè)匿名函數(shù)的功能是輸出 Hello,World!
,使用 f
變量接收這個(gè)函數(shù)并調(diào)用。
基于函數(shù)自定義類(lèi)型
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
自定義一個(gè)類(lèi)型 AddHandleFunc
,將它聲明為 GetSum
的形參,然后調(diào)用 GetSum
時(shí),因?yàn)?Add
函數(shù)和 AddHandleFunc
是等價(jià)的,因此可以將 Add
當(dāng)做實(shí)參傳進(jìn)去。
小結(jié)
本文對(duì)函數(shù)的聲明進(jìn)行介紹,根據(jù)一個(gè)案例了解了其組成的5部分。然后介紹了其一些特點(diǎn)如支持變長(zhǎng)參數(shù)、傳遞參數(shù)時(shí),實(shí)參按值傳遞等,最后根據(jù)函數(shù)在Go中是一種數(shù)據(jù)類(lèi)型的特點(diǎn),說(shuō)明了其一些特別用法。
以上就是一文帶你熟悉Go語(yǔ)言中函數(shù)的使用的詳細(xì)內(nèi)容,更多關(guān)于Go語(yǔ)言函數(shù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Go語(yǔ)言實(shí)現(xiàn)RSA加解密算法詳解
隨著互聯(lián)網(wǎng)的高速發(fā)展,人們對(duì)安全的要求也越來(lái)越高,加解密也變得越來(lái)越重要,本文主要為大家介紹了Go語(yǔ)言中實(shí)現(xiàn)RSA加解密與簽名驗(yàn)證算法,希望對(duì)大家有所幫助2023-06-06golang實(shí)現(xiàn)http server提供文件下載功能
這篇文章主要介紹了golang實(shí)現(xiàn)http server提供文件下載功能,本文給大家簡(jiǎn)單介紹了Golang的相關(guān)知識(shí),非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-02利用Golang生成整數(shù)隨機(jī)數(shù)方法示例
這篇文章主要介紹了利用Golang生成整數(shù)隨機(jī)數(shù)的相關(guān)資料,文中給出了詳細(xì)的介紹和完整的示例代碼,相信對(duì)大家具有一定的參考價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-04-04Go關(guān)鍵字defer的使用和底層實(shí)現(xiàn)
defer是Go語(yǔ)言的關(guān)鍵字,一般用于資源的釋放和異常的捕捉,defer語(yǔ)句后將其后面跟隨的語(yǔ)句進(jìn)行延遲處理,就是說(shuō)在函數(shù)執(zhí)行完畢后再執(zhí)行調(diào)用,也就是return的ret指令之前,本文給大家介紹了Go關(guān)鍵字defer的使用和底層實(shí)現(xiàn),需要的朋友可以參考下2023-11-11Go語(yǔ)言結(jié)構(gòu)化日志slog的用法解析
go?1.21.0?版本引入了一個(gè)新的包?log/slog,該包提供了結(jié)構(gòu)化日志的功能,本文小編就來(lái)和大家聊聊log/slog?包的使用,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-10-10GoLang channel底層代碼實(shí)現(xiàn)詳解
Channel和goroutine的結(jié)合是Go并發(fā)編程的大殺器。而Channel的實(shí)際應(yīng)用也經(jīng)常讓人眼前一亮,通過(guò)與select,cancel,timer等結(jié)合,它能實(shí)現(xiàn)各種各樣的功能。接下來(lái),我們就要梳理一下GoLang channel底層代碼實(shí)現(xiàn)2022-10-10golang協(xié)程與線程區(qū)別簡(jiǎn)要介紹
這篇文章主要介紹了golang協(xié)程與線程區(qū)別簡(jiǎn)要介紹,進(jìn)程是操作系統(tǒng)資源分配的基本單位,是程序運(yùn)行的實(shí)例,線程是操作系統(tǒng)調(diào)度到CPU中執(zhí)行的基本單位2022-06-06Go語(yǔ)言轉(zhuǎn)換所有字符串為大寫(xiě)或者小寫(xiě)的方法
這篇文章主要介紹了Go語(yǔ)言轉(zhuǎn)換所有字符串為大寫(xiě)或者小寫(xiě)的方法,實(shí)例分析了ToLower和ToUpper函數(shù)的使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-02-02