Skip to the content.

清空slice的两种方法

当我刚开始学习Go语言时,对slice中没有类似于C++的vector中clear()/erase()的函数而感到不知所措。后来的我却发现,Go中对清空、删除元素有着更方便的操作。

1. 索引操作

清空slice的第一种方法就是利用索引操作,如:

a = a[:0]

就可以将slice a clear。这句话的实际含义是:将a中第0个元素之前的数据赋给a。这个操作:

实际例子:

package main

import (
	"fmt"
)

func main() {
	a := []int{1, 2, 3, 4, 5, 6}
	fmt.Printf("addr of a before clear: %p\n", a)
	a = a[:0]
	fmt.Printf("before append, content of a: %v, len of a: %d, cap of a: %d\n", a, len(a), cap(a))
	fmt.Printf("addr of a after clear: %p\n", a)
	a = append(a, 7)
	fmt.Printf("after append, content of a: %v, len of a: %d, cap of a: %d\n", a, len(a), cap(a))
}

输出:

addr of a before clear: 0xc00001c180
before append, content of a: [], len of a: 0, cap of a: 6
addr of a after clear: 0xc00001c180
after append, content of a: [7], len of a: 1, cap of a: 6

由其中的地址打印语句即可以看出:slice a还是原来的slice a。

2. nil赋值

清空一个slice的第二种方法就是将slice赋一个nil值,如:

b = nil

这句话的实际意义就是给b赋一个空指针。这个操作:

package main

import (
	"fmt"
)

func main() {
	b := []int{1, 2, 3, 4, 5, 6}
	fmt.Printf("addr of b before clear: %p\n", b)
	b = nil
	fmt.Printf("before append, content of b: %v, len of b: %d, cap of b: %d\n", b, len(b), cap(b))
	fmt.Printf("addr of b after clear: %p\n", b)
	b = append(b, 7)
	fmt.Printf("after append, content of b: %v, len of b: %d, cap of a: %b\n", b, len(b), cap(b))
	fmt.Printf("addr of b after append: %p\n", b)
}

输出:

addr of b before clear: 0xc000098000
before append, content of b: [], len of b: 0, cap of b: 0
addr of b after clear: 0x0
after append, content of b: [7], len of b: 1, cap of a: 1
addr of b after append: 0xc000094020

从上面对地址的输出可以看到,clear之前和之后的slice已经不在指向同一个地址了,也实际上不再是同一个slice了。并且当我们append元素时,发生了类似于创建一个新slice的操作过程。