切片
切片是一种比较特殊的数据结构。它围绕动态数组的概念构建,可以按需自动增长和缩小。总的来说它可理解为动态数组,并根据切片里的元素自动调整切片长度。
切片指针
常用定义方式如下
var name []*type //定义方式一
name := []*type{} //定义方式二
需要注意的是,切片指针只能存放内存地址的数据格式,需要获取对应数值时需要加上取值操作符“*”。例子如下
package main
import "fmt"
func main() {
var nums []*int
for i := 0; i < 5; i++ {
nums = append(nums, &i)
}
for i, v := range nums {
_ = i
fmt.Printf("%v ", v)
}
}
得到的结果为地址
0xc00001a0a8 0xc00001a0a8 0xc00001a0a8 0xc00001a0a8 0xc00001a0a8
打印输出时,加上取值操作符后,结果为
5 5 5 5 5
当然你可能已经发现了,加上取值操作符后我们预期出现的结果应该是:”0,1,2,3,4“,为什么会是“5,5,5,5,5“呢?
再看看地址,发现这五个数都是同一个内存地址。这说明在向nums中添加元素时我们添加的都是同一个内存地址。再往前推就是说明变量i的地址不变,只有值变了。
我们再仔细观察第一个循环,发现每次往nums里添加的是变量i的值,变量i在这个循环中地址始终不变。而由于nums作为切片指针,它只能存放地址,而这些地址又来自同一个变量,那么最后的结果肯定是相同的了。
解决办法也很简单,循环内重新定义一个中间变量,这样在每次循环这个变量的地址都会改变
package main
import "fmt"
func main() {
var nums []*int
for i := 0; i < 5; i++ {
var tmp int = i
nums = append(nums, &tmp)
}
for _, v := range nums {
fmt.Printf("%v ", *v)
}
}
结果为
0 1 2 3 4