Go 語言 15 個內置函數詳解
大家好,我是 frank。
歡迎大家關注「Golang 語言開發棧」公衆號。
01 介紹
Go 語言爲了方便我們開發,提供了 15 個內置函數,比如 len、cap、make 和 new 等。
本文我們結合 Go 內置函數官方文檔 [1],介紹一下 Go 語言中的內置函數。
02 內置函數
內置函數append:
內置函數 append 可以將元素追加到切片的末尾。
func append(slice []Type, elems ...Type) []Type
當我們使用 append 向切片中追加元素時,切片的底層數組必須具有足夠的容量,否則,將會分配一個新的底層數組。
func main() {
s := []int{1, 2, 3}
fmt.Printf("%p %d\n", s, s)
s = append(s, 4)
fmt.Printf("%p %d\n", s, s)
}
輸出結果:
0xc0000b2018 [1 2 3]
0xc0000ae030 [1 2 3 4]
所以,我們需要注意的是,append 之後的切片賦值給_同一個變量_。
除了使用 append 向切片中追加元素之外,我們還可以向切片中追加另一個切片,例如:
s1 := []int{5, 6, 7}
s = append(s, s1...)
此外,還可以使用 append 將字符串追加到字節切片中,例如:
str := "hello "
bs := append([]byte(str), "world"...)
內置函數copy:
內置函數 copy 可以將源切片中的元素拷貝到目標切片。
func main() {
src := []string{"go", "vue"}
dst := make([]string, 2)
n := copy(dst, src)
fmt.Printf("%s %d\n", dst, n)
}
輸出結果:
[go vue] 2
copy 的返回值是拷貝元素的個數,返回值是 len(src) 和 len(dst) 的最小值。
需要注意的是,源切片和目標切片中的元素可能會重疊。
此外,還可以使用 copy 將一個字符串中的字節拷貝到一個字節切片中,例如:
func main() {
str := "hello"
bs := make([]byte, 5)
n := copy(bs, str)
fmt.Printf("%s %d\n", bs, n)
}
內置函數delete:
內置函數 delete 通過指定鍵 m[key] 刪除 map 中的元素。
如果 map 是 nil 或沒有元素,delete 不做任何操作。
func main() {
var m map[int]string
fmt.Println(m)
delete(m, 0)
fmt.Println(m)
m1 := make(map[int]string)
fmt.Println(m1)
delete(m1, 0)
fmt.Println(m1)
m2 := make(map[int]string, 2)
m2[0] = "hello"
m2[1] = "world"
fmt.Println(m2)
delete(m2, 0)
fmt.Println(m2)
}
輸出結果:
map[]
map[]
map[]
map[]
map[0:hello 1:world]
map[1:world]
內置函數 len:
內置函數 len 返回值的長度,值的類型不同,值的長度含義也不同。
-
array數組中元素的個數。 -
*array數組指針中元素的個數,即使數組指針的值是nil。 -
slice和map切片或映射中元素的個數,如果切片或映射的值是nil,len(v)值的長度是 0。 -
string字符串中字節的個數。 -
channel通道緩衝區中未讀元素的個數,如果緩衝通道的值是nil,len(v)值的長度是 0。
func main() {
arr := [3]int{1, 2, 3}
fmt.Println(arr)
fmt.Println(len(arr))
var arr1 *[3]int
fmt.Println(arr1)
fmt.Println(len(arr1))
var s []int
fmt.Println(len(s))
s = []int{1, 2, 3}
fmt.Println(len(s))
var m map[int]string
fmt.Println(len(m))
m = make(map[int]string)
m[0] = "hello"
fmt.Println(len(m))
str := "frank"
fmt.Println(len(str))
var c chan int
fmt.Println(c)
fmt.Println(len(c))
c = make(chan int)
fmt.Println(len(c))
}
輸出結果:
[1 2 3]
3
<nil>
3
0
3
0
1
5
<nil>
0
0
需要注意的是,slice、map 和 channel 必須先使用內置函數 make 初始化後,該類型的值纔可以使用。
內置函數 cap:
內置函數 cap 返回值的容量,值的類型不同,值的容量含義也不同。
-
array數組中元素的個數,數組的cap(v)與len(v)相等。 -
*array數組指針中元素的個數,數組指針的cap(v)和len(v)相等。 -
slice切片可以容納元素的最大長度,如果切片的值是nil,該切片cap(v)值的容量是 0。 -
channel通道緩衝區的容量,如果通道的值是nil,該通道cap(v)值的容量是 0。
func main() {
var arr [3]int
fmt.Println(arr)
fmt.Println(cap(arr))
var arr1 *[3]int
fmt.Println(arr1)
fmt.Println(cap(arr1))
var s []string
fmt.Println(s)
fmt.Println(cap(s))
s = make([]string, 1)
s[0] = "go"
fmt.Println(s)
fmt.Println(cap(s))
var c chan int
fmt.Println(c)
fmt.Println(cap(c))
}
輸出結果:
[0 0 0]
3
<nil>
3
[]
0
[go]
1
<nil>
0
內置函數 make:
內置函數 make 僅限爲 slice、map 和 channel 分配內存並初始化。
func make(t Type, size ...IntegerType) Type
make 第一個參數是類型,而不是值;第二個參數是可選(變長)參數,整型類型的值,返回值是該類型的值本身。
需要注意的是,第一個參數不同(不同類型),第二個參數的含義不同。
-
slice第一個參數是切片類型,第二個參數的含義是指定切片的長度。如果沒有傳遞第三個參數(整型類型的值),切片的容量等同於切片的長度,否則,切片的容量等同於第三個參數的值,需要注意的是,切片的容量必須不小於切片的長度。 -
map分配一個有足夠空間可以容納指定數量元素的空映射,第二個參數可以省略,如果省略第二個參數,將分配一個起始值 0。 -
channel指定緩衝區大小,初始化通道,如果第二個參數省略,或指定值爲 0,該通道將被初始化爲一個無緩衝通道。
內置函數 new:
內置函數 new 也可以分配內存,與 make 的區別是,它僅分配內存,而未初始化。
和 make 相同,第一個參數是類型,而不是值;
和 make 不同,返回值是新分配的類型零值的指針。
內置函數 complex:
內置函數 complex 將兩個浮點型的值構造爲一個複合類型的值,需要注意的是,實部和虛部必須是相同類型,即都是 float32 或 float64。
返回值是對應的複合類型,即 complex64 對應 float32 或 complex128 對應 float64。
內置函數 real:
內置函數 real 用於返回複合類型的值的實部,返回值是對應的浮點數類型。
內置函數 imag:
內置函數 imag 用於返回複合類型的值的虛部,返回值是對應的浮點數類型。
注意:
complex、real和imag三個內置函數,一般不常用,讀者朋友們只需簡單瞭解即可。
內置函數 close:
內置函數 close 關閉通道,被關閉的通道必須是一個雙向通道或僅支持發送的單向通道。
並且 close 應該由發送者執行,結果是在最後一個發送的值被接收後,關閉該通道。
通道被關閉後,任何該通道的接收者將返回成功而不會阻塞,接收者得到的返回值是該通道的類型零值和一個布爾類型的零值 false。
需要注意的是,不僅是關閉通道會返回 false,空通道也會返回 false。
內置函數 panic:
內置函數 panic 停止當前 goroutine 正常執行,當一個函數 F 調用 panic 時,該函數 F 立即停止正常執行。
該函數 F 通過 defer 延遲調用的任意函數,仍然會執行,並將執行結果返回給 F 調用者。
對於 F 的調用者 F2,調用 F 也會像調用 panic,停止 F2 的執行,並運行 F2 通過 defer 延遲調用的任意函數。以此類推,一直持續到當前 goroutine 中的所有函數都以相反的順序停止運行。
此時,程序以非 0 退出代碼終止運行。
以上終止程序運行的序列稱爲 “恐慌”,可以通過接下來我們要介紹的內置函數 recover 進行控制。
內置函數 recover:
內置函數 recover 允許程序管理 “恐慌” 的 goroutine 的行爲。
可以在 defer 中調用 recover 恢復正常執行來停止 “恐慌”,並且檢索導致“恐慌” 的錯誤。
但是,如果在 defer 之外調用 recover,它不會恢復正常執行來停止 “恐慌”。此種情況,recover 的返回值是 nil。此外,當前執行 recover 的 goroutine 未 “恐慌”,或調用 panic(nil) 時,recover 的返回值也是 nil。
因此,我們可以通過 recover 的返回值,判斷當前 goroutine 是否 “恐慌”。
注意:此處講的在
defer中調用recover,是指在defer本身中,而不是任何被defer調用的函數中。
內置函數 print:
內置函數 print 可以通過指定格式來格式化其參數,並將結果輸出。
內置函數 println:
內置函數 println 可以通過指定格式來格式化其參數,並將結果輸出。與 print 的區別是,參數之間會添加空格,末尾會添加換行符。
注意:
println與標準庫fmt中的fmt.Print()和fmt.Println()的區別是,前者是標準錯誤輸出,後者是標準輸出。在 Go 語言開發中,官方推薦使用標準庫fmt包,感興趣的讀者朋友們可以查閱相關資料進一步瞭解。
03 總結
本文我們介紹 Go 語言的內置函數,讀者朋友們需要重點掌握的內置函數是 len、cap、make、new、append、copy、delete、close、panic 和 recover。
Go 語言作爲靜態編程語言,分爲編譯期和運行時,Go 語言的內置函數的底層原理,感興趣的讀者朋友們可以閱讀 Go 語言內置函數的源碼 [2]。
參考資料
[1] Go 內置函數官方文檔: https://pkg.go.dev/builtin@go1.20.3
[2] Go 語言內置函數的源碼: https://cs.opensource.google/go/go/+/refs/tags/go1.20.3:src/cmd/compile/internal/typecheck/universe.go
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/FKp1nAX2FOeBMgchJOe4ag