Go 語言 15 個內置函數詳解

大家好,我是 frank。
歡迎大家關注「Golang 語言開發棧」公衆號。

01 介紹

Go 語言爲了方便我們開發,提供了 15 個內置函數,比如 lencapmakenew 等。

本文我們結合 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 中的元素。

如果 mapnil 或沒有元素,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 返回值的長度,值的類型不同,值的長度含義也不同。

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

需要注意的是,slicemapchannel 必須先使用內置函數 make 初始化後,該類型的值纔可以使用。

內置函數 cap

內置函數 cap 返回值的容量,值的類型不同,值的容量含義也不同。

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 僅限爲 slicemapchannel 分配內存並初始化。

func make(t Type, size ...IntegerType) Type

make 第一個參數是類型,而不是值;第二個參數是可選(變長)參數,整型類型的值,返回值是該類型的值本身。

需要注意的是,第一個參數不同(不同類型),第二個參數的含義不同。

內置函數 new

內置函數 new 也可以分配內存,與 make 的區別是,它僅分配內存,而未初始化。

make 相同,第一個參數是類型,而不是值;

make 不同,返回值是新分配的類型零值的指針。

內置函數 complex

內置函數 complex 將兩個浮點型的值構造爲一個複合類型的值,需要注意的是,實部和虛部必須是相同類型,即都是 float32float64

返回值是對應的複合類型,即 complex64 對應 float32complex128 對應 float64

內置函數 real

內置函數 real 用於返回複合類型的值的實部,返回值是對應的浮點數類型。

內置函數 imag

內置函數 imag 用於返回複合類型的值的虛部,返回值是對應的浮點數類型。

注意:complexrealimag 三個內置函數,一般不常用,讀者朋友們只需簡單瞭解即可。

內置函數 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。此外,當前執行 recovergoroutine 未 “恐慌”,或調用 panic(nil) 時,recover 的返回值也是 nil

因此,我們可以通過 recover 的返回值,判斷當前 goroutine 是否 “恐慌”。

注意:此處講的在 defer 中調用 recover,是指在 defer 本身中,而不是任何被 defer 調用的函數中。

內置函數 print

內置函數 print 可以通過指定格式來格式化其參數,並將結果輸出。

內置函數 println

內置函數 println 可以通過指定格式來格式化其參數,並將結果輸出。與 print 的區別是,參數之間會添加空格,末尾會添加換行符。

注意:printprintln 與標準庫 fmt 中的 fmt.Print()fmt.Println() 的區別是,前者是標準錯誤輸出,後者是標準輸出。在 Go 語言開發中,官方推薦使用標準庫 fmt 包,感興趣的讀者朋友們可以查閱相關資料進一步瞭解。

03 總結

本文我們介紹 Go 語言的內置函數,讀者朋友們需要重點掌握的內置函數是 lencapmakenewappendcopydeleteclosepanicrecover

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