美文网首页
Golang 隐藏技能 -- 访问私有成员

Golang 隐藏技能 -- 访问私有成员

作者: 郭老汉 | 来源:发表于2019-08-22 20:45 被阅读0次

警告一下!以下代码均不是常规操作,且存在各种潜在不可控的风险。在项目中应用有可能被同事打死,慎用!!!

1.调用其他包中公有结构的私有成员变量

如果需要引用某个包中公有结构体的私有变量,而这个变量又没有提供对应的访问方法。那么如何绕过“小写不公开”这个限制呢?简单介绍一种方法直接通过变量地址访问变量:

package other1

import "fmt"

type TestPointer struct {
    A int
    b int    // 私有变量
}

func (T *TestPointer) OouPut() {
    fmt.Println("TestPointer OouPut:", T.A, T.b)
}
package main

import (
    "fmt"
    "test/test4/other1"
    "unsafe"
)

func main() {
    T := other1.TestPointer{A:1}
    pb := (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&T)) + 8))
    /*
    Tmp := uintptr(unsafe.Pointer(&T)) + 8)
    pb := (*int)(unsafe.Pointer(Tmp)
    千万不能出现这种用临时变量中转一下的情况。因为GC可能因为优化内存碎片的原因移动了这个对象。只保留了指针的地址是没有意义的。
    */
    *pb = 2
    T.OouPut()    //1 2
}

用unsafe包中的unsafe.Pointer获取到结构体对象的首地址,然后加上想访问的私有变量的偏移地址就是私有变量的地址。关于成员变量偏移量的问题请参阅 内存对齐

2.调用其他包的私有func

go提供了一个编译指令,绕过编译器检查。直接访问func的实现
//go:linkname

package other1

import "fmt"

func privateFunc() {
    fmt.Println("this is private func")
}

package main

import (
    _ "test/test4/other1"
    _ "unsafe"
)
// call private func
//go:linkname private_func test/test4/other1.privateFunc
func private_func()

func main() {
    private_func() // this is private func
}

关于编译指令可以参阅 编译指令Command compile
上面代码需要在调用者(这里是main.go)同目录添加一个.s汇编文件,骗过编译器。让编译器认为是实现是在.s汇编文件中,从而跳过检查

3. 调用其他包的公有结构的私有方法

package other1
import "fmt"
type PublicStruct struct {
    I int
    b int
}
func (p *PublicStruct) f(a int) {
    println("PublicStruct f()", p.I, p.b, a)
}
package main
import (
    "test/test4/other1"
    _ "unsafe"
)
// 调用其他包的公有结构的私有func
//go:linkname public_struc_private_func test/test4/other1.(*PublicStruct).f
func public_struc_private_func(p *other1.PublicStruct, a int)

func main() {
    // 先构造一个other1.PublicStruct
    p := &other1.PublicStruct{I:1}
    public_struc_private_func(p, 100)   // PublicStruct f() 1 0 100
}

和上面的类似用linkname指令骗过编译器。这里声明了一个指针接收者的func public_struc_private_func
第一个参数是对应对象的指针,第二个参数开始是对应func需要的参数。
其实这就是指针接收者func原本的实现方式(即 本质上是一个普通的函数,只是隐式传递了对象的指针)

4. 调用其他包的私有全局变量

package other1
var private_m = map[int]string {
    1:"a",
}
import (
    "fmt"
    _ "test/test4/other1"
    _ "unsafe"
) // 调用其他包的私有全局变量
//go:linkname private_member test/test4/other1.private_m
var private_member map[int]string

func main() {
    fmt.Println(private_member[1])  // a
    private_member[2] = "b"
    for k, v := range private_member {
        fmt.Println(k, v)       // 1 a; 2 b
    }
}

和上面的linkname类似,骗过编译器。直接访问变量

相关文章

  • Golang 隐藏技能 -- 访问私有成员

    警告一下!以下代码均不是常规操作,且存在各种潜在不可控的风险。在项目中应用有可能被同事打死,慎用!!! 1.调用其...

  • python类的假私有成员变量

    前言 Python的类并不使用关键字区分是私有成员和共有成员,但是为啥私有成员变量外面还是访问不到呢? 粗糙的隐藏...

  • Python 入门 之 类成员

    1、类的私有成员: 私有: 只能自己拥有 以 __ 开头就是私有内容 ​ 为什么可以通过.类__私有成员名访问呢?...

  • Java中类的特性

    1. 访问控制 私有成员:通过关键字 private 来声明。无法从类的外部访问到私有成员,只能被该类自身访问和修...

  • Lession06面向对象深入

    结构体 访问私有成员属性 索引器

  • C++学习(2)-类和对象

    1.类成员的可访问范围 private: 私有成员,只能在成员函数内访问 public : 公有成员,可以在任何地...

  • C++11笔记

    友元类是模板类的声明 有一个类成员私有,希望指定的模板类可以访问,比如: 只希望Container能访问私有成员,...

  • TypeScript--类的访问修饰

    类的访问修饰符 public类成员默认都是公开的 private,声明私有成员,私有成员无法被继承,不希望被外部修...

  • C++入门04 --封装,内存布局,内存分配,构造/析构函数

    封装 成员变量私有化,提供公共的set,get方法给外界去访问成员变量; this是指针,通过指针访问结构体的成员...

  • Java Util包

    内部类 以前:一个类是不能去访问另一个类的私有成员 现在:内部类的作用:可以直接访问外部类的私有成员1:成员内部类...

网友评论

      本文标题:Golang 隐藏技能 -- 访问私有成员

      本文链接:https://www.haomeiwen.com/subject/wviosctx.html