Go中切片的内部结构包括地址、大小和容量。切片通常用于快速操作部分数据收集。如果将数据收集比作切蛋糕,那么每一片都是您需要的“部分”。切割过程包括从哪里开始切割(切片起始位置)和切割多远(切片大小)。容量可以理解为切片口袋的大小,如下图所示。
图:Slice结构和内存分配[/caption]从数组或切片生成新切片
默认情况下,切片指的是内存的连续区域。这可能是一个数组或一个切片本身。
从内存的连续区域生成切片是一种常见的操作,其格式为:
slice [開始位置 : 終了位置]
语法解释如下:
- Slice:目标切片对象。
- 起始位置:目标切片对象对应的索引。
- 结束位置:对应于目标切片的结束索引。
以下是从数组生成切片的代码:
var a[3]int{1, 2, 3}
fmt.Println(a, a[1:2]) 这里,a是一个包含三个整数元素的数组,初始化为1到3之间的值,a[1:2]可用于生成新的切片。代码操作的结果是:
[1 2 3] [2]
这里,[2]是[1:2]切片操作的结果。
从数组或切片创建新切片具有以下特征:
- 要提取的元素数量是结束位置减去开始位置。
- 检索到的元素不包含结束位置对应的索引,使用slice[len(slice)]检索切片的最后一个元素;
- 默认起始位置是从连续区域的开头到结束位置。
- 如果使用默认结束位置,则表示从开始位置到整个连续区域的结束位置。
- 如果两者同时设置为默认值,则它相当于切片本身。
- 如果两者同时为0,则相当于一个空切片,常用来重置切片。
根据索引位置获取切片元素的值时,取值范围为(0~len(slice)-1),超过限制会报运行时错误。生成切片时,可以指定结束位置。 len(slice) 但没有报错。
下面通过例子来了解切片的特性。
1)从指定范围生成切片
切片和数组是密不可分的。如果把阵列理解为办公楼,切片就是将不同的连续楼层出租给用户。租赁过程要求您选择起始楼层和结束楼层。这个过程产生切片。示例代码如下。
var highRiseBuilding [30]int
for i := 0; i < 30; i++ {
highRiseBuilding[i] = i + 1
}
// 範囲
fmt.Println(highRiseBuilding[10:15])
// 中央から末尾までのすべての要素
fmt.Println(highRiseBuilding[20:])
// 先頭から指定した位置までのすべての要素
fmt.Println(highRiseBuilding[:2]) 这是代码输出:
[11 12 13 14 15]
[21 22 23 24 25 26 27 28 29 30]
[1 2]
代码中,正在建设一栋30层的高层建筑,数组元素值范围为1到30,代表不同的独立楼层,输出结果是不同的出租和销售计划。
代码说明如下:
- 8号线,我们正在尝试出租一个区域楼层。
- 11 号线 20 层或以上的出租物业。
- 14号二楼以下出租,一般为商业用途。
切片类似于 C 中的指针。指针可用于计算,但代价是内存操作越界。切片的大小根据指针增长,限制了切片对应的内存区域。使用切片时,切片内的地址和大小无法更改。切片比指针更安全、更稳健,因为它们是手动调整的。
2) 代表原始切片
在生成的切片的格式中,如果忽略起始位置和结束位置,则生成的切片表示与原始切片相同的切片,并且生成的切片在数据内容上也与原始切片匹配。像这样:
a := []int{1, 2, 3}
fmt.Println(a[:])
a 是一个包含三个元素的切片。用a[:]操作切片a后,结果切片与切片a匹配。这是代码输出:
[1 2 3]
3)重置切片并清除拥有的元素
如果切片的起始位置和结束位置都设置为0,则生成的切片将为空。这是代码:
a := []int{1, 2, 3}
fmt.Println(a[0:0])
a := []int{1, 2, 3}
fmt.Println(a[0:0]) 这是代码输出:
[]
直接声明一个新的切片
除了从原始数组或切片生成切片之外,您还可以声明新切片。每个类型还可以有一个切片类型,表示相同类型的元素的连续集合,因此您也可以声明切片类型。切片类型的声明格式为:
var name []Type
其中,name表示切片的变量名,Type表示切片对应的元素类型。
以下代码演示了切片声明的使用。
// 文字列スライスを宣言する
var strList []string
// 整数スライスを宣言する
var numList []int
// 空スライスを宣言する
var numListEmpty = []int{}
// 3つのスライスを出力する
fmt.Println(strList、numList、numListEmpty)
// 3つのスライスのサイズを出力する
fmt.Println(len(strList)、len(numList)、len(numListEmpty))
// スライスの空の判定結果を出力する
fmt.Println(strList == nil)
fmt.Println(numList == nil)
fmt.Println(numListEmpty == nil) 代码输出结果:
[] [] []
0 0 0
true
true
false
代码说明如下:
- 第 2 行声明一个包含多个字符串的字符串切片。
- 第 5 行声明一个包含多个整数值的整数切片。
- 第 8 行将 numListEmpty 声明为整数切片。这将填充
{}内切片的初始化元素,但由于此处没有填充,因此切片将为空。 然而,此时numListEmpty有分配给它的内存,但没有内存。元素仍然存在。 - 第 11 行中,任何切片中都没有元素,并且所有三个切片的输出元素内容均为空。
- 第14行,没有对切片进行任何操作,strList和numList没有指向数组或其他切片。
- 在第 17 行和第 18 行中,已声明但未使用的切片的默认值为 nil,strList 和 numList 也为 nil,因此与 nil 的比较结果为 true。
- 在第 19 行中,分配了 numListEmpty,但没有元素,因此将其与 nil 比较结果为 false。
切片是动态结构,只能确定是否等于 nil,而不能确定彼此是否相等。声明新切片后,您可以使用append()函数向切片添加元素。

如果需要动态创建切片,可以使用内置函数make()。格式为:
make( []Type, size, cap )
其中,Type是指切片的元素类型,size是指分配给该类型的元素数量,cap是预先分配的元素数量。设置该值后,不会影响大小,但可以预先分配空间,以降低因多次分配而出现性能问题的风险。
一个例子是:
a := make([]int, 2)
b := make([]int, 2, 10)
fmt.Println(a, b)
fmt.Println(len(a), len(b))
这是代码输出:
[0 0] [0 0]
2 2
a和b都是预分配的具有两个元素的切片,但是b的内部存储空间分配了10个切片,但实际上使用了两个元素。
容量不会影响当前的元素数量,因此a和b的len都是2。
善意的提示
使用make()函数生成的切片需要内存分配操作,但指定起始和结束位置的切片(包括重置切片)无需使用新的切片结构分配内存,只需指向该区域并设置起始和结束位置即可。 。不执行任何内存分配操作。




![2021 年如何设置 Raspberry Pi Web 服务器 [指南]](https://i0.wp.com/pcmanabu.com/wp-content/uploads/2019/10/web-server-02-309x198.png?w=1200&resize=1200,0&ssl=1)

