企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持知识库和私有化部署方案 广告
> go语言github项目:https://github.com/minibear2333/how_to_code [TOC] ### 先来看看Golang中的数组 其实在[循环](https://mp.weixin.qq.com/s?__biz=MzAxOTc1OTY4NA==&mid=2650856000&idx=3&sn=1a6cdbf89fcfa4cd7fa0d66a7d1de2e2&chksm=80366d6bb741e47d96d1706713198ce6840a87576bb97ffd5b3c3cecbf964509b607950b0d23&scene=21#wechat_redirect)那一节用到过数组,我快速介绍一下。 - 数组中是固定长度的连续空间(内存区域) - 数组中所有元素的类型是一样的 ```go var a1 [10]int //初始化数组 var b1 = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0} ``` **多维数组** ```go //声明二维数组,只要 任意加中括号,可以声明更多维,相应占用空间指数上指 var arr [3][3]int //赋值 arr = [3][3]int{ {1, 2, 3}, {2, 3, 4}, {3, 4, 5}, } ``` ### 何谓切片? 类比`c`语言,一个`int`型数组`int a[10]`,`a`的类型是`int*`,也就是整型指针,而`c`语言中可以使用`malloc()`动态的分配一段内存区域,`c++`中可以用`new()`函数。例如: ```go int* a = (int *)malloc(10); int* b = new int(4); ``` 此时,`a`和`b`的类型也是`int*`,`a`和`b`此时分配内存的方式类似于`go`语言中的切片。 `Go`的数组和切片都是从`c`语言中延续过来的设计。 ### 有何不同? ```go var sliceTmp []int ``` 可以看到和`c`不同的是,`go`可以声明一个空切片(默认值为`nil`),然后再增加值的过程中动态的改变切片值大小。 ### 怎么动态增加? 增加的方式只有一种,使用`append`函数追加。 ```go sliceTmp = append(sliceTmp, 4) sliceTmp = append(sliceTmp, 5) ``` 每个切片有长度`len`和容量`cap`两个概念,长度是我们最熟知的,和数组长度相同,可以直接用来遍历。 ```go for _,v := range slice1{ fmt.Println(v) } ``` 用切糕来对比 ![](https://coding3min.oss-accelerate.aliyuncs.com/coding3min/2020-05-05-080617.jpg) 每个切片,在声明或扩建时会分配一段连续的空间,称为容量`cap`,是不可见的;真正在使用的只有一部分连续的空间,称为长度`len`,是可见的。 每次`append`时,如果发现`cap`已经不足以给`len`使用,就会重新分配原`cap`两倍的容量,把原切片里已有内容全部迁移过去。 新分配的空间也是连续的,不过不一定直接在原切片内存地址处扩容,也有可能是新的内存地址。 ### 切片的长度与容量,len cap append copy ```go slice1 := []int{1, 2, 3} ``` 普通切片的声明方式,长度和容量是一致的。 ``` len=3 cap=3 slice=[1 2 3] ``` 当然,控制权在我们手上,我们可以自己控制长度和容量, ```go slice1 = make([]int, 3, 5) // 3 是长度 5 是容量 ``` 输出 ``` len=3 cap=5 slice=[0 0 0] ``` 尝试使用一般的方式扩容 ```go slice1[len(slice1)] = 4 //报错 panic: runtime error: //index out of range [3] with length 3 ``` 这种方式是会报错的,虽然容量是 5 ,但是数组长度是3,这里是以长度为准,而不是容量,`append`内部如果超过容量相当于创建了一个新数组,每个新数组都是定长的,只不过外部是切片。 尝试扩容 ```go slice1 = append(slice1, 4) ``` 输出,可以发现`len`扩容了! ``` len=4 cap=5 slice=[0 0 0 4] ``` 让我们连续扩容,让容量超过`5` ```go slice1 = append(slice1, 5) slice1 = append(slice1, 6) // 到这里长度超过了容量,容量自动翻倍为 5*2 ``` 输出 ``` len=6 cap=10 slice=[0 0 0 4 5 6] ``` 上面的过程,我 用自己的代码模拟一遍 ```go // 上面容量自动翻倍的过程可以看作和下面一致 slice1 = make([]int, 3, 5) // 3 是长度 5 是容量 slice1 = append(slice1, 4) slice1 = append(slice1, 5) // 长度不变,容量自动翻倍为 5*2 slice2 := make([]int, len(slice1), (cap(slice1))*2) // 拷贝 slice1 的内容到 slice2 // 注意是后面的拷贝给前面 copy(slice2, slice1) slice2 = append(slice2, 6) ``` **所以,你理解容量,长度的概念了吗?**