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

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

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类似,骗过编译器。直接访问变量

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,907评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,546评论 1 289
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,705评论 0 238
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,624评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,940评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,371评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,672评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,396评论 0 195
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,069评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,350评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,876评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,243评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,847评论 3 231
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,004评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,755评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,378评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,266评论 2 259

推荐阅读更多精彩内容