学习Go语言的内置函数(built-in)。
什么是Go语言内置函数呢?
简单地理解就是指Go内置的不需要以包名为前缀就可以直接访问的函数:
//非内置函数
import "fmt"
fmt.Println("test")
//内置函数
println("test")
按目前Go最新的版本(1.20.5
),Go语言总共有15个内置函数,分别为:append,new,make,len,cap,copy,delete,panic,recover,close,complex,real,imag,print,println。
append
append
函数用于将一个或多个元素添加到切片(slice
)的末尾,其函数签名为:
func append(slice []Type, elems ...Type) []Type
append
函数第一个参数slice
是一个切片,elems
表示切片的元素,其数据类型与切片元素的数据类型必须相同:
s0 := []int{1, 2}
// 添加一个元素 s1 = []int{1, 2, 3}
s1 := append(s0, 3)
// 添加多个元素 s2 = []int{1, 2, 3, 4, 5, 6}
s2 := append(s1, 4, 5, 6)
// 将切片添加到另一个切片 s3 = []int{1, 2, 3, 4, 5, 6 , 1 , 2}
s3 := append(s2, s0...)
// 截取不同切片再合并 s4 = []int{[4 5 6 3 4 5 6 1 2]}
s4 := append(s3[3:6], s3[2:]...)
//空接口切片
var t []interface{}
//t == []interface{}{100, 6.8, "test"}
t = append(t, 100, 6.8, "test")
var b []byte
// 将字符串添加字节数组 b = []byte{'j', 'u', 's','t','','g','o'}
b = append(b, "just go"...)
append
函数往切片添加元素时,如果切片的容量还没满,那么返回的新切片与源切片指向同一个底层数组:
package main
import "fmt"
func main() {
//创建一个容量为2,长度为0的切片
s1 := make([]int, 0, 2)
//向s1添加两个元素
s2 := append(s1, 3, 4)
fmt.Printf("s1的地址:%p,容量:%d,长度:%d\n", s1, cap(s1), len(s1))
fmt.Printf("s2的地址:%p,容量:%d,长度:%d\n", s2, cap(s2), len(s2))
}
上面代码的运行结果如下所示,可以看出两个切片指向的底层数组地址是一致的:
s1的地址:0xc0000140a0,容量:2,长度:0
s2的地址:0xc0000140a0,容量:2,长度:2
如果切片的容量已经耗尽,那么append
函数会为切片重新分配一个更大容量的底层数组,并将数据复制过去,此时返回的切片则指向新分配的数组:
package main
import "fmt"
func main() {
//创建一个容量为2,长度为0的切片
s3 := make([]int, 0, 2)
//向s4添加两个元素
s4 := append(s3, 1, 2, 3, 4)
fmt.Printf("s3的地址:%p,容量:%d,长度:%d\n", s3, cap(s3), len(s3))
fmt.Printf("s4的地址:%p,容量:%d,长度:%d\n", s4, cap(s4), len(s4))
}
上面代码的运行结果如下,可以看到,向一个容量只有2的切片添加4个元素时,append
函数会自动扩容:
s3的地址:0xc0000140c0,容量:2,长度:0
s4的地址:0xc000020080,容量:4,长度:4
new
new
函数用于为指定的类型分配内存,并返回一个对应内存的指针,其函数签名如下:
func new(Type) *Type
使用new
分配的一般是普通数据类型(如:int
,float32
等)或复合类型(比如array
,struct
):
i := new(int)
*i = 10
fmt.Println(*i) //10
type User struct{
ID int
Name string
}
// 下面使用new创建结构体的语句等同于 u := &User{}
u := new(User)
make
make
函数用于创建并初始化slice
、channel
和map
这样的引用类型,其函数签名如下:
func make(t Type, size ...IntegerType) Type
与new
函数相似,make
的第一个参数是所要定义的数据类型,而与new
函数不同的是,make
函数并不是返回一个指针类型,这是因为slice
,channel
和map
是引用类型:
m := make(map[string]string)
当创建切片时,必须传入第二个参数来指定切片的长度:
s := make([]int,2)
也可以传入第三个参数来指定义切片的容量,如果不传第三个参数,则容量与长度相等:
//容量:5,长度:2
s1 := make([]int,2,5)
//未指定容量,因此容量与长度都等3
s2 := make([]string,3)
如果是创建map
类型时,那么就不需要传入第二个与第三个参数了:
m := make(map[string]string)
创建channel
对象时,make
函数的第二个参数用于指定channel
缓冲区的大小,如果没有传入,就表示创建了一个没有缓冲区的channel
:
//无缓冲区
c1 := make(chan int)
//缓冲区大小:2
c := make(chan int,2)
len与cap
len
函数用于获得指定类型的长度,其函数签名如下:
func len(v Type) int
len
函数只能用于获得数组,数组指针,切片,channel以及字符串这五种类型的长度。
如果是数组或者数组指针,len函数返回的是数组元素数量:
a := [5]int{1, 2, 3, 4, 5}
p := &a
fmt.Printf("数组长度:%d,指针数组长度:%d\n", len(a), len(p))
对于channel
类型,len
函数返回channel
当前缓冲区元素的个数:
package main
import (
"fmt"
"sync"
)
func main() {
//容量为10
ch := make(chan int, 10)
var w sync.WaitGroup
w.Add(1)
go func(ch chan int) {
ch