Go标准库学习:builtin

发布时间 2023-11-16 21:45:02作者: 流云cpp

Builtin 模块

最近在学Go,但感觉标准库中文资料不是很多,直接看官网文档又没有循序渐进的过程,所以自己在边看边记录,如有谬误还请指出,感谢。

这部分总结了Go中内置的模块,不需要导包。
来自Go的标准文档,版本是1.21.4。
在类型方面是我自己的总结和理解。

类型(types)

Go语言提供的类型

首先,Go语言内置了多种类型,我这里将其分为两类:值类型和引用类型。

并不是说值类型就分配在栈上,引用类型就分配在堆上,Go中的变量分配的位置会由Go编译器自动评估,如果可以就在栈上分配,如果要传出指针则会分配在堆上。

我这里说得值类型和引用类型的区别是当该类型的值作为函数参数时,对于该类型的修改不会传播到函数之外,值类型的影响局限于函数内,而引用类型则传递到函数之外。另外,引用类型可以被赋值为nil,而值类型则不行。

Go内置的值类型(在x64平台上)如下:

类型名 大小
(u)int 1 word
intN(N=8,16,32,64) N/8 bytes
uintN(N=8,16,32,64) N/8 bytes
uintptr 8 bytes
floatN(N=32,64) N/8 bytes
complexN(N=64,128) N/8 bytes
bool 1 byte
[N]Type N*sizeof(Type)
string 16 byte

需要注意的是,数组类型是值类型,其大小也是数组中所有元素的数量之和。
string是不可变的类型,所以其传值、获取字串的操作是非常高效的。

Go内置的引用类型(在x64平台上)如下:

类型名 大小
slice 24 btes
map 8 bytes
chan 8 bytes
函数类型 8 bytes
interface 16 bytes

slice中包含指向元素的指针、长度、容量。
slice
interface包含真实类型和指向其引用的值的指针。
需要注意的是,等于nilinterface和其引用的值为nilinterface是不一样的,要注意区分。
interface

验证代码:

func GetValueTypeSize() {
	showTypeAndSize(int(0))
	showTypeAndSize(int8(0))
	showTypeAndSize(int16(0))
	showTypeAndSize(int32(0))
	showTypeAndSize(int64(0))
	showTypeAndSize(uint(0))
	showTypeAndSize(uint8(0))
	showTypeAndSize(uint16(0))
	showTypeAndSize(uint32(0))
	showTypeAndSize(uint64(0))
	showTypeAndSize(uintptr(0))
	showTypeAndSize(float32(0.0))
	showTypeAndSize(float64(0.0))
	showTypeAndSize(complex64(0))
	showTypeAndSize(complex128(0))
	showTypeAndSize(true)
	showTypeAndSize([1]int{})
	showTypeAndSize([2]int{})
	showTypeAndSize([3]int{})
	showTypeAndSize("你好,世界!")
	showTypeAndSize([]int{})
	showTypeAndSize(map[int]int{})
	showTypeAndSize(make(chan int))
	showTypeAndSize((func())(nil)) // 函数类型
	fmt.Printf("sizeof %-15s: %2d byte(s)\n", "interface{}", unsafe.Sizeof(interface{}(nil)))
}

func showTypeAndSize(obj interface{}) {
	t := reflect.TypeOf(obj)
	fmt.Printf("sizeof %-15s: %2d byte(s)\n", t.String(), t.Size())
}
/*
Output:
sizeof int            :  8 byte(s)
sizeof int8           :  1 byte(s)
sizeof int16          :  2 byte(s)
sizeof int32          :  4 byte(s)
sizeof int64          :  8 byte(s)
sizeof uint           :  8 byte(s)
sizeof uint8          :  1 byte(s)
sizeof uint16         :  2 byte(s)
sizeof uint32         :  4 byte(s)
sizeof uint64         :  8 byte(s)
sizeof uintptr        :  8 byte(s)
sizeof float32        :  4 byte(s)
sizeof float64        :  8 byte(s)
sizeof complex64      :  8 byte(s)
sizeof complex128     : 16 byte(s)
sizeof bool           :  1 byte(s)
sizeof [1]int         :  8 byte(s)
sizeof [2]int         : 16 byte(s)
sizeof [3]int         : 24 byte(s)
sizeof string         : 16 byte(s)
sizeof []int          : 24 byte(s)
sizeof map[int]int    :  8 byte(s)
sizeof chan int       :  8 byte(s)
sizeof func()         :  8 byte(s)
sizeof interface{}    : 16 byte(s)
*/
别名数据类型

Go还设置了基本数据类型的别名:

type byte = uint8
type rune = int32
type any = interface{}

接口(interface)

内置模块还默认定义了几个接口:

type error interface {
	Error() string
}

type comparable interface{ comparable }

comparable接口默认被所有可比较的类型(booleans, numbers, strings, pointers, channels, arrays of comparable types, structs whose fields are all comparable types)实现了。具体可见这里

函数

本文档中使用了以下仅用于解释的类型,这些类型均非实际存在:

类型 说明
ComplexType 表示一种复数类型:complex64complex128
FloatType 表示一种浮点类型:float32float64
IntegerType 表示一种整型:int, uint, int8
Type 表示任意一种Go的类型,但在一个函数调用中表示相同类型
Type1 表示任意一种Go的类型,但在一个函数调用中表示相同类型
内置函数
append
func append(slice []Type, elems ...Type) []Type

向一个slice中添加元素,并返回添加元素后的slice。注意,若原slice的capacity无法放得下要添加的元素,则会申请新的空间以存放元素,所以应该将append的返回值重新赋值给slice

作为例外,string可以被添加到byte的slice里。

例子:

slice = append(slice, elem1, elem2)
slice = append(slice, anotherSlice...)

slice = append([]byte("hello "), "world"...)
cap
func cap(v Type) int

获取v的容量:

类型 结果
数组 数组v中元素的数量,等于len(v)
指向数组的指针 *v中元素的数量,等于len(*v)
slice append时无需realloc而可以直接append时,最大的append后元素数量;等于nil时返回0
chan 通道的缓冲区容量,单位是元素的个数,如果v等于nil,返回0
len
func len(v Type) int

获取v的长度。

类型 结果
数组 数组v中元素的数量
指向数组的指针 *v中元素的数量,即便v等于nil
slice v中元素的数量,v等于nil时返回0
string v中的字节数
chan 缓冲队列中未读的元素的数量,v等于nil时返回0
new
func new(Type) *Type

这个函数会分配内存。第一个参数是一个类型,而不是值。返回值是一个指针,该指针指向该类型的零值。

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

为slice/map/chan分配内存并初始化。和new一样,make第一个参数也是一个类型。和new不同的是,函数的返回值是该类型的值,而非指针。

类型 其他参数
slice 如果有一个参数,那么该参数表示slice的长度和容量;如果有两个参数,那么第一个参数表示长度,第二个参数表示容量(容量>=长度)
map 能容纳指定数量元素的map,如果填则初始化为一个较小值
chan 通道的缓冲区大小,0或者不填表示无缓冲
clear
func clear[T ~[]Type | ~map[Type]Type1](t T)

参数必须是slice、map或者两种类型的指针。slice会将length清零,map会清空此map。

close
func close(c chan<- Type)

参数是双向的通道或者发送方的通道。作用是当最后一个元素从c中读出后关闭该通道。当最后一个元素从c中读出后,读取方再从通道中读取数据时会立刻非阻塞地返回,返回值时该通道中传递的数据类型的零值,如果接收者的形式为:

val, ok := <- c

ok的值为false

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

从map中删除键值为key的那一项。如果m为nil,或者map中没有该key,则无操作。

copy
func copy(dst, src []Type) int

把元素从slice src复制到slice dst(特例:也可以把从string中拷贝字节到[]byte)。源slice和目的slice可以重叠。返回值是复制的元素的数量,为len(src)和len(dst)的较小值。

complex
func complex(r, i FloatType) ComplexType

生成一个复数,r表示实部,i表示虚部。r和i必须类型相同,同时是float23或同时是float64(或者可以赋值给他们),float32对应返回值为complex64float64complex128.

real
func real(c ComplexType) FloatType

返回复数的实部。

imag
func imag(c ComplexType) FloatType

返回复数的虚部。

min, max
func min[T cmp.Ordered](x T, y ...T) T
func max[T cmp.Ordered](x T, y ...T) T

返回课比较类型的最小/大值,最少有两个参数。如果T是浮点类型且有一个是NaN,那么返回值会是NaN。

func print(args ...Type)
func println(args ...Type)

将输出写入到标准错误

panic, recover
func panic(v any)
func recover() any

出错和恢复,这里就不介绍了。

常量

const (
	true  = 0 == 0 // Untyped bool.
	false = 0 != 0 // Untyped bool.
)

const iota = 0 // Untyped int.

变量

var nil Type // Type must be a pointer, channel, func, interface, map, or slice type