Go语言中,数组长度一经定义,不可以修改,且数组的长度只能是常量或常量表达式,不可以是变量。那有的人说,我有一个长度是10的数组,我就想在运行时,得到一个长度是之前数组长度n倍的新数组,这做不到吗?在理论上是无法实现的。但是,我们可以使用一些hack技术。Go语言中slice的长度和容量是可以动态指定的,且slice底层有三个字段,分别是array,len,cap。array是一个unsafe.Pointer类型的指针,它就指向了一片连续的内存区域。所以通过unsafe包中的指针计算。我们可以短暂的持有内存地址的指针。通过计算指针的偏移,就能对内存区域中的值进行操作,这一点很像C语言。
package main
import (
"fmt"
"unsafe"
)
func main() {
n := 10
s := make([]int, n)
p := (*struct {
array unsafe.Pointer
len int
cap int
})(unsafe.Pointer(&s)).array
for j := 0; j < n; j++ {
*(*int)(unsafe.Pointer(uintptr(p) + uintptr(j)*unsafe.Sizeof(int(0)))) = j + 1
}
fmt.Println(s)
n *= 2
s = make([]int, n)
p = (*struct {
array unsafe.Pointer
len int
cap int
})(unsafe.Pointer(&s)).array
for j := 0; j < n; j++ {
*(*int)(unsafe.Pointer(uintptr(p) + uintptr(j)*unsafe.Sizeof(int(0)))) = j + 1
}
fmt.Println(s)
}
[1 2 3 4 5 6 7 8 9 10]
[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]