Hi,大家好,我是明哥,
在自己學習 Golang 的這段時間里,我寫了詳細的學習筆記放在我的個人微信公眾號 《Go編程時光》,對于 Go 語言,我也算是個初學者,因此寫的東西應該會比較適合剛接觸的同學,如果你也是剛學習 Go 語言,不防關注一下,一起學習,一起成長,
我的在線博客:http://golang.iswbm.com
我的 Github:github.com/iswbm/GolangCodingTime
1. 關于函式
函式是基于功能或 邏輯進行封裝的可復用的代碼結構,將一段功能復雜、很長的一段代碼封裝成多個代碼片段(即函式),有助于提高代碼可讀性和可維護性,
在 Go 語言中,函式可以分為兩種:
- 帶有名字的普通函式
- 沒有名字的匿名函式
由于 Go語言是編譯型語言,所以函式撰寫的順序是無關緊要的,它不像 Python 那樣,函式在位置上需要定義在呼叫之前,
2. 函式的宣告
函式的宣告,使用 func 關鍵字,后面依次接 函式名,引數串列,回傳值串列,用 {} 包裹的代碼邏輯體
func 函式名(形式引數串列)(回傳值串列){
函式體
}
-
形式引數串列描述了函式的引數名以及引數型別,這些引數作為區域變數,其值由引數呼叫者提供
-
回傳值串列描述了函式回傳值的變數名以及型別,如果函式回傳一個無名變數或者沒有回傳值,回傳值串列的括號是可以省略的,
舉個例子,定義一個 sum 函式,接收兩個 int 型別的引數,在運行中,將其值分別賦值給 a,b,并規定必須回傳一個int型別的值 ,
func sum(a int, b int) (int){
return a + b
}
func main() {
fmt.Println(sum(1,2))
}
3. 函式實作可變引數
上面舉的例子,引數個數都是固定的,這很好理解 ,指定什么型別的引數就傳入什么型別的變數,數量上,不能多一個,也不能少一個,(好像沒有可選引數),
在 Python 中我們可以使用 *args 和 **kw ,還實作可變引數的函式,
可變引數分為幾種:
- 多個型別一致的引數
- 多個型別不一致的引數
多個型別一致的引數
首先是多個型別一致的引數,
這邊定義一個可以對多個數值進行求和的函式,
使用 ...int,表示一個元素為int型別的切片,用來接收呼叫者傳入的引數,
// 使用 ...型別,表示一個元素為int型別的切片
func sum(args ...int) int {
var sum int
for _, v := range args {
sum += v
}
return sum
}
func main() {
fmt.Println(sum(1, 2, 3))
}
// output: 6
其中 ... 是 Go 語言為了方便程式員寫代碼而實作的語法糖,如果該函式下會多個型別的函式,這個語法糖必須得是最后一個引數,
同時這個語法糖,只能在定義函式時使用,
多個型別不一致的引數
上面那個例子中,我們的引數型別都是 int,如果你希望傳多個引數且這些引數的型別都不一樣,可以指定型別為 ...interface{},然后再遍歷,
比如下面這段代碼,是Go語言標準庫中 fmt.Printf() 的函式原型:
import "fmt"
func MyPrintf(args ...interface{}) {
for _, arg := range args {
switch arg.(type) {
case int:
fmt.Println(arg, "is an int value.")
case string:
fmt.Println(arg, "is a string value.")
case int64:
fmt.Println(arg, "is an int64 value.")
default:
fmt.Println(arg, "is an unknown type.")
}
}
}
func main() {
var v1 int = 1
var v2 int64 = 234
var v3 string = "hello"
var v4 float32 = 1.234
MyPrintf(v1, v2, v3, v4)
}
在某些情況下,我們需要定義一個引數個數可變的函式,具體傳入幾個引數,由呼叫者自己決定,但不管傳入幾個引數,函式都能夠處理,
比如這邊實作一個累加
func myfunc(args ...int) {
for _, arg := range args {
fmt.Println(arg)
}
}
4. 多個可變引數函式傳遞引數
上面提到了可以使用 ... 來接收多個引數,除此之外,它還有一個用法,就是用來解序列,將函式的可變引數(一個切片)一個一個取出來,傳遞給另一個可變引數的函式,而不是傳遞可變引數變數本身,
同樣這個用法,也只能在給函式傳遞引數里使用,
例子如下:
import "fmt"
func sum(args ...int) int {
var result int
for _, v := range args {
result += v
}
return result
}
func Sum(args ...int) int {
// 利用 ... 來解序列
result := sum(args...)
return result
}
func main() {
fmt.Println(sum(1, 2, 3))
}
5. 函式的回傳值
Go語言中的函式,在你定義的時候,就規定了此函式
-
有沒有回傳值?
當沒有指明回傳值的型別時, 函式體不能有 return,Go并不像 Python 那樣沒有return,就默認回傳None
-
回傳幾個值?
Go 支持一個函式回傳多個值
func double(a int) (int, int) { b := a * 2 return a, b } func main() { // 接收引數用逗號分隔 a, b := double(2) fmt.Println(a, b) } -
怎么回傳值?
Go支持回傳帶有變數名的值
func double(a int) (b int) { // 不能使用 := ,因為在回傳值哪里已經宣告了為int b = a * 2 // 不需要指明寫回哪個變數,在回傳值型別那里已經指定了 return } func main() { fmt.Println(double(2)) } // output: 4
6. 方法與函式
方法,在上一節《08. 面向物件編程:結構體與繼承》里已經介紹過了,它的定義與函式有些不同,你可以點擊前面的標題進行交叉學習,
那 方法和函式有什么區別? 為防會有朋友第一次接觸面向物件,這里多嘴一句,
方法,是一種特殊的函式,當你一個函式和物件/結構體進行系結的時候,我們就稱這個函式是一個方法,
7. 匿名函式的使用
所謂匿名函式,就是沒有名字的函式,它只有函式邏輯體,而沒有函式名,
定義的格式如下
func(引數串列)(回傳引數串列){
函式體
}
一個名字實際上并沒有多大區別,所有使用匿名函式都可以改成普通有名函式,那么什么情況下,會使用匿名函式呢?
定義變數名,是一個不難但是還費腦子的事情,對于那到只使用一次的函式,是沒必要擁有姓名的,這才有了匿名函式,
有了這個背景,決定了匿名函式只有擁有短暫的生命,一般都是定義后立即使用,
就像這樣,定義后立馬執行(這里只是舉例,實際代碼沒有意義),
func(data int) {
fmt.Println("hello", data)
}(100)
亦或是做為回呼函式使用
// 第二個引數為函式
func visit(list []int, f func(int)) {
for _, v := range list {
// 執行回呼函式
f(v)
}
}
func main() {
// 使用匿名函式直接做為引數
visit([]int{1, 2, 3, 4}, func(v int) {
fmt.Println(v)
})
}
系列導讀
01. 開發環境的搭建(Goland & VS Code)
02. 學習五種變數創建的方法
03. 詳解資料型別:****整形與浮點型
04. 詳解資料型別:byte、rune與string
05. 詳解資料型別:陣列與切片
06. 詳解資料型別:字典與布爾型別
07. 詳解資料型別:指標
08. 面向物件編程:結構體與繼承
09. 一篇文章理解 Go 里的函式
10. Go語言流程控制:if-else 條件陳述句
11. Go語言流程控制:switch-case 選擇陳述句
12. Go語言流程控制:for 回圈陳述句
13. Go語言流程控制:goto 無條件跳轉
14. Go語言流程控制:defer 延遲呼叫
15. 面向物件編程:介面與多型
16. 關鍵字:make 和 new 的區別?
17. 一篇文章理解 Go 里的陳述句塊與作用域
18. 學習 Go 協程:goroutine
19. 學習 Go 協程:詳解信道/通道
20. 幾個信道死鎖經典錯誤案例詳解
21. 學習 Go 協程:WaitGroup
22. 學習 Go 協程:互斥鎖和讀寫鎖
23. Go 里的例外處理:panic 和 recover
24. 超詳細解讀 Go Modules 前世今生及入門使用
25. Go 語言中關于包匯入必學的 8 個知識點
26. 如何開源自己寫的模塊給別人用?
27. 說說 Go 語言中的型別斷言?
28. 這五點帶你理解Go語言的select用法

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/6555.html
標籤:Go
上一篇:Docker scratch 無法正常運行golang二進制程式的問題
下一篇:go語言包管理
