目录
切片类型
切片是GO语言中的一种类型。
切片类型的内部实现具有以下几个字段:
1.数组的地址——也就是是有指向一个数组的。
2.切片的长度。并不是底层数组的长度
3.切片的容量。
切片本身的数据结构大小占的并不多,主要是底层数组的大小占比较大了。
在 64 位架构的机器上,一个切片需要 24 字节的内存:指针字段需要 8 字节,长度和容量字段分别需要 8 字节。
由于与切片关联的数据包含在底层数组里,不属于切片本身,
所以将切片复制到任意函数的时候,对底层数组大小都不会有影响。复制时只会复制切片本身,不会涉及底层数组:
GO中传参数本身都是传值的。只不过比如切片底层是有指向一个底层数组的。
创建切片
创建类型的变量,都以整型切片为例子。
1.
slice1 := make([]int, 3, 5)——————肯定有创建了一个底层数组,具体不知道数组的大小,不小于5是肯定的了
2.
slice2 := []int{10, 20, 30, 40}————估计就是创建了一个长度为4的数组?然后切片的其长度和容量都是 4 。
// ps 创建数组和切片的区别。对切片里某个索引指向的元素赋值和对数组里某个索引指向的元素赋值的方法完全一样。使用 [] 操作符就可以改变某个元素的值
// 创建有 3 个元素的整型数组
myArray := [3]int{10, 20, 30}
// 创建长度和容量都是 3 的整型切片
mySlice := []int{10, 20, 30}
3.
// 创建 nil 整型切片
var slice3 []int ————指针为nil 长度和容量都是0
对切片进行一个切片或者扩容的操作
当切片可以共享一个底层数组的时候就共享(也就是两个切片的数组的地址 的值 是相同的),当不能共享的时候就重新创建一个底层数组出来了。
主要注意的就是两个切片是不是共享一个底层数组,修改元素是不是会相互影响。
动词切片语法:(j肯定要 > i)
slice[i:j]
slice[i:j:k]
i 表示从 slice 的第几个元素开始切
j 控制切片的长度(j-i),
k 控制切片的容量(k-i),如果没有给定 k,k=len(slice),表示最尾部。
简写:
slice[i:] // 从 i 切到最尾部 == slice[i:len(slice)]
slice[:j] // 从最开头切到 j(不包含 j)
slice[:] // 从头切到尾,等价于复制整个 slice
通过"切片"创建新的切片的本质——共享一个底层数组(也就是两个切片的数组的地址 的值 是相同的),注意一旦共享的底层数组元素修改便会引用其的切片都会改变。
切片扩容append()
函数 append() 总是会增加新切片的长度,而容量有可能会改变,也可能不会改变
1.
如果原切片的可用容量还有可用,append() 函数就不会创建新的底层数组,长度加1,容量不变。
2
.如果原切片的可用容量已经没有了,append() 函数会创建一个新的底层数组,将被引用的现有的值复制到新数组里,长度加1,容量未知,一般都是之前容量的2倍。
(append()智能地处理的容量增长,其切片的容量不是很切片的长度一样长了)
例子:
// myNum 长度和容量为4。
myNum := []int{10, 20, 30, 40}
// newNum 长度和容量为5和8
newNum := append(myNum, 50)
查看切片的底层数组的地址
不知道怎么看切片的指向的数组的地址,只能通过具体某个元素的值来查看了
共享底层数组:
myNum := make([]int, 4, 5)
newNum := append(myNum, 50)
fmt.Printf("Addr: %v\n", &newNum[0])
fmt.Printf("Addr: %v\n", &myNum[0])
不共享底层数组:
myNum := []int{10, 20, 30, 40}
newNum := append(myNum, 50)
fmt.Printf("Addr: %v\n", &newNum[0])
fmt.Printf("Addr: %v\n", &myNum[0])
打印字符串的utf16编码:
golang默认编码正好是utf-8
中文在utf-8编码下一个汉字占3个字节。所以"高SHI在SHI高"的字节数15个
把"高SHI在SHI高"使用utf16编码的话,每个字符都是占2个字节的,不管汉字还是字母。
encodeContent := utf16.Encode([]rune("高SHI在SHI高")) contentlen := len(encodeContent) for i := 0; i < contentlen; i++ { fmt.Printf("%04X", encodeContent[i]) } fmt.Printf("\n")
%04X -- 0表示填充0,4代表宽度
比如字母也会被填充0
output:
9AD8 0053 0048 0049 5728 0053 0048 0049 9AD8
byte 等同于int8,常用来处理ascii字符
rune 等同于int32,常用来处理unicode或utf-8字符
golang中string底层是通过byte数组实现的。中文字符在unicode下占2个字节,在utf-8编码下占3个字节,而golang默认编码正好是utf-8。