# Go语言核心36讲（Go语言进阶技术一）--学习笔记

## 07 | 数组和切片

### 我们今天的问题就是：怎样正确估算切片的长度和容量？

```package main

import "fmt"

func main() {
// 示例1。
s1 := make([]int, 5)
fmt.Printf("The length of s1: %d\n", len(s1))
fmt.Printf("The capacity of s1: %d\n", cap(s1))
fmt.Printf("The value of s1: %d\n", s1)
s2 := make([]int, 5, 8)
fmt.Printf("The length of s2: %d\n", len(s2))
fmt.Printf("The capacity of s2: %d\n", cap(s2))
fmt.Printf("The value of s2: %d\n", s2)
}```

### 问题解析

```s3 := []int{1, 2, 3, 4, 5, 6, 7, 8}
s4 := s3[3:6]
fmt.Printf("The length of s4: %d\n", len(s4))
fmt.Printf("The capacity of s4: %d\n", cap(s4))
fmt.Printf("The value of s4: %d\n", s4)```

（切片与数组的关系）

### 知识扩展

#### 问题 1：怎样估算切片容量的增长？

```package main

import "fmt"

func main() {
// 示例1。
s6 := make([]int, 0)
fmt.Printf("The capacity of s6: %d\n", cap(s6))
for i := 1; i <= 5; i++ {
s6 = append(s6, i)
fmt.Printf("s6(%d): len: %d, cap: %d\n", i, len(s6), cap(s6))
}
fmt.Println()

// 示例2。
s7 := make([]int, 1024)
fmt.Printf("The capacity of s7: %d\n", cap(s7))
s7e1 := append(s7, make([]int, 200)...)
fmt.Printf("s7e1: len: %d, cap: %d\n", len(s7e1), cap(s7e1))
s7e2 := append(s7, make([]int, 400)...)
fmt.Printf("s7e2: len: %d, cap: %d\n", len(s7e2), cap(s7e2))
s7e3 := append(s7, make([]int, 600)...)
fmt.Printf("s7e3: len: %d, cap: %d\n", len(s7e3), cap(s7e3))
fmt.Println()

// 示例3。
s8 := make([]int, 10)
fmt.Printf("The capacity of s8: %d\n", cap(s8))
s8a := append(s8, make([]int, 11)...)
fmt.Printf("s8a: len: %d, cap: %d\n", len(s8a), cap(s8a))
s8b := append(s8a, make([]int, 23)...)
fmt.Printf("s8b: len: %d, cap: %d\n", len(s8b), cap(s8b))
s8c := append(s8b, make([]int, 45)...)
fmt.Printf("s8c: len: %d, cap: %d\n", len(s8c), cap(s8c))
}```

#### 问题 2：切片的底层数组什么时候会被替换？

```package main

import "fmt"

func main() {
// 示例1。
a1 := [7]int{1, 2, 3, 4, 5, 6, 7}
fmt.Printf("a1: %v (len: %d, cap: %d)\n",
a1, len(a1), cap(a1))
s9 := a1[1:4]
//s9[0] = 1
fmt.Printf("s9: %v (len: %d, cap: %d)\n",
s9, len(s9), cap(s9))
for i := 1; i <= 5; i++ {
s9 = append(s9, i)
fmt.Printf("s9(%d): %v (len: %d, cap: %d)\n",
i, s9, len(s9), cap(s9))
}
fmt.Printf("a1: %v (len: %d, cap: %d)\n",
a1, len(a1), cap(a1))
fmt.Println()

}```

### 思考题

• 如果有多个切片指向了同一个底层数组，那么你认为应该注意些什么？
• 怎样沿用“扩容”的思想对切片进行“缩容”？请写出代码。

0 条评论

• ### Go语言核心36讲（Go语言进阶技术十一）--学习笔记

我刚才说过，一旦主 goroutine 中的代码执行完毕，当前的 Go 程序就会结束运行，无论其他的 goroutine 是否已经在运行了。那么，怎样才能做到等...

• ### Go语言核心36讲（Go语言进阶技术十）--学习笔记

我们已经知道，通道（也就是 channel）类型的值，可以被用来以通讯的方式共享数据。更具体地说，它一般被用来在不同的 goroutine 之间传递数据。那么 ...

• ### Go语言核心36讲（Go语言进阶技术九）--学习笔记

在前面的文章中，我们已经提到过很多次“指针”了，你应该已经比较熟悉了。不过，我们那时大多指的是指针类型及其对应的指针值，今天我们讲的则是更为深入的内容。

• ### Go语言核心36讲（Go语言进阶技术八）--学习笔记

在 Go 语言的语境中，当我们在谈论“接口”的时候，一定指的是接口类型。因为接口类型与其他数据类型不同，它是没法被实例化的。

• ### Go语言核心36讲（Go语言进阶技术八）--学习笔记

在 Go 语言的语境中，当我们在谈论“接口”的时候，一定指的是接口类型。因为接口类型与其他数据类型不同，它是没法被实例化的。

• ### Go语言核心36讲（Go语言进阶技术七）--学习笔记

我们都知道，结构体类型表示的是实实在在的数据结构。一个结构体类型可以包含若干个字段，每个字段通常都需要有确切的名字和类型。

• ### Go语言核心36讲（Go语言进阶技术五）--学习笔记

首先来说说单向通道。我们在说“通道”的时候指的都是双向通道，即：既可以发也可以收的通道。

• ### Go语言核心36讲（Go语言进阶技术六）--学习笔记

在前几期文章中，我们分了几次，把 Go 语言自身提供的，所有集合类的数据类型都讲了一遍，额外还讲了标准库的container包中的几个类型。

• ### Go语言核心36讲（Go语言进阶技术四）--学习笔记

作为 Go 语言最有特色的数据类型，通道（channel）完全可以与 goroutine（也可称为 go 程）并驾齐驱，共同代表 Go 语言独有的并发编程模式和...

• ### Go语言核心36讲（Go语言进阶技术三）--学习笔记

它们或用连续存储，或用互存指针的方式收纳元素，这里的每个元素都代表了一个从属某一类型的独立值。

• ### Go语言核心36讲（Go语言进阶技术二）--学习笔记

我们在上次讨论了数组和切片，当我们提到数组的时候，往往会想起链表。那么 Go 语言的链表是什么样的呢？

• ### Go语言核心36讲（Go语言进阶技术十三）--学习笔记

比如，我们声明过error类型的变量err，也调用过errors包中的New函数。

• ### Go语言核心36讲（Go语言进阶技术十二）--学习笔记

现在，让我们暂时走下神坛，回归民间。我今天要讲的if语句、for语句和switch语句都属于 Go 语言的基本流程控制语句。它们的语法看起来很朴素，但实际上也会...

• ### Go语言核心36讲（Go语言基础知识一）--学习笔记

从 Go 1.5 版本的自举（即用 Go 语言编写程序来实现 Go 语言自身），到 Go 1.7 版本的极速 GC（也称垃圾回收器），再到 2018 年 2 月...

• ### Go语言核心36讲（Go语言基础知识六）--学习笔记

在上一篇文章，我们一直都在围绕着可重名变量，也就是不同代码块中的重名变量，进行了讨论。还记得吗？

• ### Go语言核心36讲（Go语言基础知识五）--学习笔记

在前文中，我解释过代码块的含义。Go 语言的代码块是一层套一层的，就像大圆套小圆。

• ### Go语言核心36讲（Go语言基础知识四）--学习笔记

还记得吗？Go 语言中的程序实体包括变量、常量、函数、结构体和接口。 Go 语言是静态类型的编程语言，所以我们在声明变量或常量的时候，都需要指定它们的类型，或者...

• ### Go语言核心36讲（Go语言基础知识三）--学习笔记

在我的定义中，库源码文件是不能被直接运行的源码文件，它仅用于存放程序实体，这些程序实体可以被其他代码使用（只要遵从 Go 语言规范的话）。

• ### Go语言核心36讲（Go语言基础知识二）--学习笔记

我们已经知道，环境变量 GOPATH 指向的是一个或多个工作区，每个工作区中都会有以代码包为基本组织形式的源码文件。

.NET 开发工程师