func main() {
n := 1
nbytes := i2bin(n)
for i := 0; i < len(nbytes); i++ {
fmt.Printf("value: %v,addr: %p", nbytes[i], &nbytes[i])
}
}
func i2bin(i int) []byte {
sh := &reflect.SliceHeader{Len: 8, Cap: 8, Data: uintptr(unsafe.Pointer(&i))}
return *(*[]byte)(unsafe.Pointer(sh))
}
如题,转换完成后数据是正常的为:
[0]:0x1
[1]:0x0
[2]:0x0
[3]:0x0
[4]:0x0
[5]:0x0
[6]:0x0
[7]:0x0
进入循环,第一次打印数组结束数据就变成了:
[0]:0x9
[1]:0x10
[2]:0xa3
[3]:0x0
[4]:0x0
[5]:0x0
[6]:0x0
[7]:0x0
为什么会发生变化呢?
golang: v1.18.3 windows
1
joesonw 2022-07-19 09:58:40 +08:00 via iPhone
按值传进去的,在栈上。
|
2
RayR OP @joesonw
把`i2bin`写在 main 函数中确实访问后没有变化。通过指针传入 int 也可以达到这个效果,意味着这片内存会逃逸到堆上。 所以不论是在`i2bin`中创建完的 SliceHeader 还是`main`中响应过程中复制的切片,`uintptr`指向的是同一片内存空间。在函数执行完毕后`main`函数的切片依旧指向的是栈上的空间,但是这片空间已经被 runtime 标记为可回收的空间并且确实被回收了。 |
3
lysS 2022-07-27 10:05:43 +08:00
var sb = make([]byte, 8)
*(*int)(unsafe.Pointer(&sb[0])) = i 而且可以不取 0 ,这样可以避免一次中间内存的分配 |