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