Go-内置类型和内置函数

1. 内置类型

值类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
bool -- 布尔类型
string -- 8位byte序列构成的字符串,约定但不必须是utf-8编码的文本。字符串可以为空但不能是nil,其值不可变。
int -- 至少32位的有符号整形,但和int32/rune并非同一类型。
uint -- 至少32位的无符号整形,但和uint32不是同一类型。
int8 -- 8位有符号整形,范围[-128, 127]。
uint8 -- 8位无符号整型,范围[0, 255]。
int16 -- 16位有符号整形,范围[-32768, 32767]。
uint16 -- 16位无符号整型,范围[0, 65535]。
int32 -- 32位有符号整形,范围[-2147483648, 2147483647]。
uint32 -- 32位无符号整型,范围[0, 4294967295]。
int64 -- 64位有符号整形,范围[-9223372036854775808, 9223372036854775807]。
uint64 -- 64位无符号整型,范围[0, 18446744073709551615]。
uintptr -- 可以保存任意指针的位模式的整数类型。
byte -- 8位无符号整型,是uint8的别名,二者视为同一类型。
rune -- 32位有符号整形,int32的别名,二者视为同一类型。
float32 -- 所有IEEE-754 32位浮点数的集合,12位有效数字。
float64 -- 所有IEEE-754 64位浮点数的集合,16位有效数字。
complex64 -- 具有float32 类型实部和虚部的复数类型。
complex128 -- 具有float64 类型实部和虚部的复数类型。
array -- 固定长度的数组

引用类型:(指针类型)

1
2
3
slice   -- 序列数组(最常用)
map -- 映射
chan -- 管道

2. 内置函数

Go 语言拥有一些不需要进行导入操作就可以使用的内置函数。它们有时可以针对不同的类型进行操作,例如:len、cap 和 append,或必须用于系统级的操作,例如:panic。因此,它们需要直接获得编译器的支持。

名称 说明
append 用来追加元素到array、slice中,返回修改后的array、slice
close 用于管道通信,主要用来关闭channel,用于发送方关闭chan,仅适用于双向或发送通道。
delete 从map中删除key对应的value
new、make new 和 make 均是用于分配内存: new 用于值类型用户定义的类型,如int、struct 自定义结构体。返回指向Type的指针。生成类型T的零值指针,注意它返回的是指针 T。*make 用于内置引用类型(只能应用于slice、map 和channel)。返回Type本身。生成slice、map、channel对象。
它们的用法就像是函数,但是将类型作为参数:new(type)、make(type)。
new(T) 分配类型 T 的零值并返回其地址,也就是指向类型 T 的指针。它也可以被用于基本类型:v := new(int)
make(T) 返回类型 T 的初始化之后的值(实例),返回的是一个实例,而不是指针,因此它比 new 进行更多的工作,new() 是一个函数,不要忘记它的括号。
new 函数作用于值类型,仅分配内存空间,返回的是指针,make 函数作用于引用类型,除了分配内存空间,还会对对应类型进行初始化,返回的是初始值。 在 Go 语言中,引用类型包括切片(slice)、字典(map)和管道(channel),其它都是值类型。
len len 用于返回某个类型的长度或数量(string、array、slice、map 和channel)
cap capacity是容量的意思,用于返回某个类型的最大容量(只能用于slice和 map)
copy 用于复制和连接slice,返回复制的数目
panic、recover 两者均用于错误处理机制:
panic:停止常规的goroutine
recover:允许程序定义goroutine的panic动作
complex、real、imag 用于创建和操作复数
complex:从指定的实部和虚部构建复数
real:返回complex的实部
imag:返回complex的虚部
print、println 底层打印函数,在部署环境中建议使用 fmt 包

make用法示例

func make(t Type, size …IntegerType) Type

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 生成slice、map、channel对象
sl1 := make([]int, 5) //定义长度和容量都为5的切片
sl2 := make([]int, 5, 10) //定义长度为5,容量为10的切片

map1 := make(map[string]int) //定义map
map2 := make(map[string]int, 2) //定义map 初始可以容纳2个元素的空间

c1 := make(chan int) //定义不带缓存的channel
c2 := make(chan int, 5) // 定义缓存大小为5的channel

# 切片:size指定了其长度。该切片的容量等于其长度。切片支持第二个整数实参可用来指定不同的容量;
它必须不小于其长度,因此 make([]int, 0, 10) 会分配一个长度为0,容量为10的切片。
# 映射:初始分配的创建取决于size,但产生的映射长度为0。size可以省略,这种情况下就会分配一个
小的起始大小。
# 通道:通道的缓存根据指定的缓存容量初始化。若 size为零或被省略,该信道即为无缓存的。
  • make函数也用于内存分配,和new不同的地方在于,make函数只能用于chan,map和切片三种类型的创建,返回值就是对象本身,因为这三类数据结构本身就是引用类型,必须要初始化。

    new用法示例

    funcnew(Type) Type

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
p1 := new(int)     // 返回 int 类型指针
p2 := new(string) // 返回 string 类型指针
p3 := new([3]int) // 返回数组类型指针,数组长度是3

type Student struct {
id int
name string
grade string
}
p4 := new(Student) // 返回对象类型指针

println("p1: ", p1)
println("p2: ", p2)
println("p3: ", p3)
println("p4: ", p4)
  • new函数用来创建某一个类型的指针型对象,理论上,只要一个数据类型能够被访问到,就能用new函数来创建指针类型的对象。返回值是一个指向新分配的type类型的零值的指针。
  • 在Go语言中,如果使用new创建chan类型的指针对象,在使用之前仍然需要使用make函数来初始化chan的容量。
  • new函数创建对象与直接使用struct{}创建的对象的区别是,前者为指向对象的一个指针,后者创建的是对象引用本身。

    append用法示例

    func append(slice []Type, elems …Type) []Type

1
2
3
4
5
# 增加0到n个元素到slice中,返回新的slice,注意第一个参数不能是指针类型
intslice := make([]int, 0)
intslice = append(intslice, 1)
intslice = append(intslice, 2)
//intslice : [1,2]
  • go语言中的append函数作用是在切片变量的后面追加新的数据,然后返回新的切片变量
  • 内建函数append将元素追加到切片的末尾。若它有足够的容量,其目标就会重新切片以容纳新的元素。否则,就会分配一个新的基本数组。append返回更新后的切片,因此必须存储追加后的结果。

    complex用法示例

    Go提供了两种大小的复数类型:complex64和complex128,分别由float32和float64组成。

    func complex(r, i FloatType) ComplexType // 参数列表中r 为复数的实部,i 表示为复数的虚部
    func real(c ComplexType) FloatType
    func imag(c ComplexType) FloatType

1
2
3
4
5
var x complex128 = complex(1, 2) // 1+2i  构建复数
var y complex128 = complex(3, 4) // 3+4i 构建复数
fmt.Println(x*y) // "(-5+10i)"
fmt.Println(real(x*y)) // "-5" 获取实部
fmt.Println(imag(x*y)) // "10" 获取虚部

close用法示例

func close(c chan<- Type)

1
2
3
4
5
6
7
# 关闭channel
ch := make(chan bool)
close(ch)
close(ch) // 这样会panic的,channel不能close两次
ch <- false //已经关闭channel 不能写入数据
i, ok := <- ch 判断channel是否关闭
i := <-ch 不会panic, i读取到的值是false,如果是有缓存channel,可以继续读取channel中的剩余的数据
  • 内建函数close关闭信道,该通道必须为双向的或只发送的。它应当只由发送者执行,而不应由接收者执行,其效果是在最后发送的值被接收后停止该通道。在最后的值从已关闭的信道中被接收后,任何对其的接收操作都会无阻塞的成功。
  • close函数用于关闭一个非只读的管道。
  • close方法应该由管道的数据发送一方调用。
  • 当最后一个发送的值被从管道中接收之后,后面的所有值接收都会非阻塞直接返回,返回值为元素类型的零值。
  • 如果chan已经关闭,则x,ok := <- chan 中,ok为false。

    panic用法示例

    func panic(v interface{})
    func recover() interface{}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
defer func() { // 必须要先声明defer,否则不能捕获到panic异常
fmt.Println("c")
if err := recover(); err != nil { //调用recover函数将会捕获到当前的panic(如果有的话
fmt.Println(err) // 这里的err其实就是panic传入的内容,55
}
fmt.Println("d")
}()

fmt.Println("a")
panic(55) // panic是用来表示非常严重的不可恢复的错误的,一般会导致程序挂掉(除非recover)
fmt.Println("b")
fmt.Println("f")
// 输出结果:a c 55 d

# panic 只会触发当前 Goroutine 的延迟函数调用
# recover 只有在 defer 函数中调用才会生效;
# panic 允许在 defer 中嵌套多次调用;
  • 内建函数panic停止当前Go程的正常执行。当函数F调用panic时,F的正常执行就会立刻停止。F中defer的所有函数先入后出执行后,F返回给其调用者G。G如同F一样行动,层层返回,直到该Go程中所有函数都按相反的顺序停止执行。之后,程序被终止,而错误情况会被报告,包括引发该恐慌的实参值,此终止序列称为恐慌过程。
  • 内建函数recover允许程序管理恐慌过程中的Go程序。在defer的函数中,执行recover调用会取回传至panic调用的错误值,恢复正常执行,停止恐慌过程。若recover在defer的函数之外被调用,它将不会停止恐慌过程序列。在此情况下,或当该Go程不在恐慌过程中时,或提供给panic的实参为nil时,recover就会返回nil。
  • panic函数表示程序中非常严重,不可恢复的错误,与java中的 try{} catch{} 类似。
  • panic异常被抛出之后,会一层一层的上传至最外层,直至程序崩溃。
  • recover函数用于捕获程序中抛出的panic,recover函数只能在defer延迟函数中调用。

    cap用法示例

    func cap(v Type) int

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 可以用来查看数组或slice的容量
slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
slice1 := slice[1:5]

fmt.Println(slice) //[1 2 3 4 5 6 7 8 9]
fmt.Println(slice1) // [2 3 4 5] : 包括1 但不包括5
fmt.Println(len(slice1)) // 4 切片的长度
fmt.Println(cap(slice1)) // 8 切片的容量

# 内建函数cap返回 v 的容量,这取决于具体类型:
# 数组:v中元素的数量,与 len(v) 相同
# 数组指针:*v中元素的数量,与len(v) 相同
# 切片:切片的容量(底层数组的长度);若 v为nilcap(v) 即为零
# 信道:按照元素的单元,相应信道缓存的容量;若v为nilcap(v)即为零
  • cap函数用来计算切片,通道,数组类型变量的容量,即这个容器最多能装多少元素。
  • 如果v是nil,则cap(v) 容量获取到的是0。

    len用法示例

    func len(v Type) int

1
2
3
4
5
6
7
8
9
10
11
12
# 得到字符串、数组、数值指针、slice、mapchan的长度
s := "hello world,你好中国"
a := [5]int{1, 2, 3, 4, 5}
sl := a[:3]
m := map[string]int{"a": 1, "b": 2}
c := make(chan int, 3)

fmt.Println(len(s)) // 字符串:记录字节数。 24
fmt.Println(len(a)) // 数组:记录数组元素个数。 5
fmt.Println(len(sl)) // 切片:记录切片元素个数。 3
fmt.Println(len(m)) // map:记录map元素个数。2
fmt.Println(len(c)) // channel:记录channel通道中的元素个数 0
  • len函数用来获取字符串,切片,数组,通道,字典类型变量的内容长度,不同的类型,长度的计算规则不一致。对于切片,字典,数组,通道类型的变量,他们中的每一个元素就是一个长度。string类型的变量,每一个字节都是一个长度,中文字在utf8编码中占三个字节,故len获取string类型长度时,每一个汉字都是三个长度。
  • len计算的是变量已有数据的内容长度,并非是变量的容量。
  • 如果v是nil,则len(v)为0。

    delete用法示例

    func delete(m map[Type]Type1, key Type)

1
2
3
4
5
6
7
# 删除map中的一个映射, m为nil或者m[k]不存在也不会panic,而是一个空操作
m := map[int]string{
1: "张三",
2: "李四",
}
delete(m, 1)
fmt.Println(m) // map[2:李四]
  • 内建函数delete按照指定的键将元素从映射中删除。若m为nil或无此元素,delete不进行操作

    copy用法示例

    func copy(dst, src []Type) int

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 用于将源slice的数据(第二个参数),复制到目标slice(第一个参数)。
# 返回值为拷贝了的数据个数,是len(dst)和len(src)中的最小值。
var a = []int{0, 1, 2, 3, 4, 5, 6, 7}
var s = make([]int, 6)
//源长度为8,目标为6,只会复制前6个
n1 := copy(s, a)
fmt.Println("s - ", s)
fmt.Println("n1 - ", n1)
//源长为7,目标为6,复制索引1到6
n2 := copy(s, a[1:])
fmt.Println("s - ", s)
fmt.Println("n2 - ", n2)
//源长为8-5=3,只会复制3个值,目标中的后三个值不会变
n3 := copy(s, a[5:])
fmt.Println("s - ", s)
fmt.Println("n3 - ", n3)
//将源中的索引5,6,7复制到目标中的索引3,4,5
n4 := copy(s[3:], a[5:])
fmt.Println("s - ", s)
fmt.Println("n4 - ", n4)
  • copy函数把slice源的数据复制到目的切片中,需要注意的是,copy不会主动的扩展目的切片的容量,在目的slice填充满之后会舍弃超出的部分,返回的是复制成功的元素个数

  • 若目的slice原来有元素,则会被覆盖掉

    3. 内置接口error

    1
    2
    3
    type error interface { //只要实现了Error()函数,返回值为String的都实现了err接口
    Error() String //内建error接口类型是约定用于表示错误信息,nil值表示无错误。
    }
  • nil是预定义的标识符,代表指针、通道、函数、接口、映射或切片的零值。

  • iota是一个预定义的标识符,代表顺序按行增加的无符号整数。


Go-内置类型和内置函数
https://www.chendujin.com/posts/4312b66a.html
作者
托马斯
发布于
2022年3月20日
许可协议