跳转至

9.切片

基本用法

go语言和Python一样,有切片操作:

a := {1, 2, 3, 4}
b := a[1:2]
c := a[:3]
d := a[2:]
e := a[:] // equal e := a[0:len(a)] 

Warning

go语言的切片操作不能是负数索引,区别于Python。

如果对字符串进行切片,改变字符串的值,切片的值不会改变(可以将看作切片是一种特殊的指针)。且切分字符串时,只能按照字节数进行切分。

切片的另一种声明方式

a := []string{"s1", "s2"}

在声明函数时,也可以传入切片,其类型写作[]<type>,如[]string

Info

将切片传入函数,再对切片中的元素做修改,可以影响到原值(将切片看作是指针)。

切片是没有长度的,所以对于函数,无论切片的长度如何,都能传入。

带有方法的切片

可以以切片类型为底层类型,使用type声明一个新类型,然后给予方法。
sort库的StringSlice

append函数

通过内置的append函数,可以实现在切片后增加元素(但是没有改变原数组),其使用方法如下:

append
slice := []string{"A", "B"};
slice = append(slice, "C", "D", "E", ...)

Warning

append并不会修改切片对象,不是slice的一个方法,而是返回一个新的切片对象。这与Python中的list的append函数不同。

容量与大小

容量(Capacity)和大小(或者称为长度:Length)是切片类型的两个不同概念。

容量可以使用函数cap()查询,长度可以使用内置函数len()查询。

容量指的是切片类型的底层数组的大小,而长度指的是切片的长度。

可以使用下面这段代码来辨别容量和长度两个概念:

capacity and length of Slice in Golang, temp.go
package main

import (
        "fmt"
)

func main() {
        a := [5]string{"A", "B", "C"}
        b := a[:2]
        fmt.Println("array a is:", a)
        fmt.Println("slice b is:", b)
        fmt.Println("length of slice b is:\t", len(b))
        fmt.Println("capacity of slice b is:\t", cap(b))
        fmt.Println("append element at the end of slice b")
        b = append(b, "X", "Y")
        fmt.Println("Now, array a is:", a, "; Slice b is:", b)
        fmt.Println("length of slice b is:\t", len(b))
        fmt.Println("capacity of slice b is:\t", cap(b))
        fmt.Println("Go on, add more element,")
        b = append(b, "U", "V", "W")

        fmt.Println("Now, array a is:", a, "; Slice b is:", b)
        fmt.Println("length of slice b is:\t", len(b))
        fmt.Println("capacity of slice b is:\t", cap(b))
}
其输出如下:

$ go run temp.go
array a is: [A B C  ]
slice b is: [A B]
length of slice b is:    2
capacity of slice b is:  5
append element at the end of slice b
Now, array a is: [A B X Y ] ; Slice b is: [A B X Y]
length of slice b is:    4
capacity of slice b is:  5
Go on, add more element,
Now, array a is: [A B X Y ] ; Slice b is: [A B X Y U V W]
length of slice b is:    7
capacity of slice b is:  10

Warning

可以看出,当增加的元素总长度小于容量时,会覆盖底层数组,如果增加的元素总数多于数组时,容量会按照数组长度的倍数增加。

但是要注意,go会开一个新的数组,而不是在原数组上修改再追加数组。所以最好不要数组和切片混用。

如果必须从数组生成索引,且不希望修改原数组,则可以通过指定切片操作的第三个参数:容量,来生成一个新的数组。

切片操作的第三个参数

从go 1.2开始,切片操作可以有第三个参数。

Warning

注意,这并非Python中的[start:stop:step]

Go语言中的三个参数用来指定切片的容量,当容量与底层数组长度不同时,就会新开一个数组。

使用make函数生成切片

使用make函数能指定生成一个空的切片。

go titl="make()" slice := make([]string, 0, 10) // make(sliceType, length, capacity) // 如果省略capacity,则容量和长度都是第二个参数