Stay Hungry.Stay Foolish.
Go语言里面的"(void *)通用指针"类型

习惯了C的灵活指针,学习Go最感兴趣就是看Go的指针

Golang有一个unsafe包,可以用来灵活的操作内存地址来寻址想要的数据。对应于C语言里面的通用指针类型void *,Go里面有个unsafe.Pointer类型,其实就是一个无符号整形值,可以加减这个值就相当于加减内存地址,内存地址的大小和操作系统有关,比如我的64位系统是8个字节,可以使用查看内存地址大小。

fmt.Println(unsafe.Sizeof(uintptr(p1)))

关于unsafe包

  • 任何类型的指针值都可以转换为unsafe.Pointer。
  • unsafe.Pointer可以转换为任何类型的指针值。
  • uintptr可以转换为unsafe.Pointer。
  • unsafe.Pointer可以转换为uintptr。

我们测试看下uintptr干了啥

package main

func main() {
    a := [4]int{0, 1, 2, 3}
    p := unsafe.Pointer(&a[0])
    fmt.Println("转换前: ", p, "转换后: ", uintptr(p))
}

我得到的结果是: 转换前: 0xc820012780 转换后: 859530405760

可以看到把16进制表示的内存地址转换为了10进制的内存地址

相比于C里面的指针操作,Go还是差了很多,比如使用指针方式操作数组

#include <stdio.h>

int
main (void) 
{
    int  a[] = {1,2,3,4};
    *(&a[0] + 1) = 6;
    printf("%d\n", a[1]);
}

当然这里可以直接使用语法糖a来取代&a[0]的写法。

在Go里面,我们需要这么做

package main

func main() {
    a := [4]int{0, 1, 2, 3}
    p1 := unsafe.Pointer(&a[0])
    p2 := unsafe.Pointer(uintptr(p1) + unsafe.Sizeof(a[0]))
    *((*int)(p2)) = 6
    fmt.Println(a)
}
自由转载-非商用-非衍生-保持署名(创意共享3.0许可证
评论

暂无评论~~