go 利用unsafe.Pointer和uintptr 给私有变赋值

  • 定义类型 及访问是有变量的方法
package p

import "fmt"

type V struct {
    i int
    j string
    k float64
}

// 此处不用V,否则this 会是调用者的复制,而不是原对象
func (this *V) PutIPtr() {
    fmt.Println(fmt.Sprintf("v.i ptr:%p", &this.i))
}

func (this V) PutI() {
    fmt.Println(fmt.Sprintf("V.i:%d", this.i))
}

func (this V) PutJ() {
    fmt.Println(fmt.Sprintf("V.j:%s", this.j))
}

func (this V) PutK() {
    fmt.Println(fmt.Sprintf("V.j:%f", this.k))
}

  • 在外面赋值
package main

import (
    "fmt"
    "myself/go-ptr/p"
    "unsafe"
)

func main() {
    // 初始化内存,返回p.V类型的一个指针
    v := new(p.V)

    // v 的地址也是v.i的地址
    fmt.Println(fmt.Sprintf("new ptr:%p", v))
    v.PutIPtr()
    i := (*int)(unsafe.Pointer(v))
    *i = 66

    // uintptr(unsafe.Sizeof(int(2))) 获取int类型的指针长度
    // v 指针地址的基础上加上int类型长度,为v.j的地址
    j := (*string)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + uintptr(unsafe.Sizeof(int(2)))))
    *j = "this is string"
    k := (*float64)(unsafe.Pointer(uintptr(unsafe.Pointer(j)) + uintptr(unsafe.Sizeof(string("22")))))
    *k = 99
    v.PutI()
    v.PutJ()
    v.PutK()
}

*运行结果

new ptr:0xc000004480
v.i ptr:0xc000004480
V.i:66
V.j:this is string
V.j:99.000000
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容