美文网首页Golang
[Golang] 调用其它包中的私有函数、全局变量

[Golang] 调用其它包中的私有函数、全局变量

作者: Platanuses | 来源:发表于2017-12-19 17:25 被阅读2310次

在使用 Golang 的某些情况下(当然,应该是在万不得已的情况下),你可能需要调用引入的某个包中的某些私有全局变量或函数(包括方法)。事实上,Golang 是有一些未在官方文档中公布的相关隐藏技能的,这些技能在 Golang 开源的标准库代码中出现,终究被挖了出来。

调用私有函数

这里有一个被引入的包somewhere.com/someone/another

package another

func inc(i int) int {
    return i + 1
}

在自己的包中调用上面的私有函数inc

package main

import (
    _ "unsafe"

    _ "somewhere.com/someone/another"
)

//go:linkname inc somewhere.com/someone/another.inc
func inc(i int) int

func main() {
    println(inc(2))
}

首先,需要在自己的包中声明要调用的私有函数。在声明的上一行虽然是一行注释,不过和//export开头的注释一样,这样的注释是有自己特殊语义的。//go:linkname会在编译期将本包符号链接到目标符号。因为在编译产物的符号表中已不存在 Golang 语法中的所谓公开与私有,可谓“想跳就跳”。

//go:linkname后面跟上本地函数名和目标函数,目标函数需要指定包含完整路径的包名,点号后面加上函数名。

同时,需要引入unsafe包,并且在自己的包中需要加入一个空白的*.s汇编文件,来绕过编译检查。

调用公开结构的私有方法

这里有一个公开结构Cls和其私有方法m

package another

type Cls struct {
    I int
}

func (c *Cls) m() {
    println(c.I)
}
package main

import (
    _ "unsafe"

    "somewhere.com/someone/another"
)

//go:linkname m somewhere.com/someone/another.(*Cls).m
func m(c *another.Cls)

func main() {
    c := &another.Cls{2}
    m(c)
}

Golang 不能在一个包内定义其它包中类型的方法,因此需要定义为本包内的函数,并把方法的 this 指针语义显式地表达出来。同时,对于目标方法的指定,需要加上形如(*S)的类型指定。

调用私有结构的私有方法

结构的定义不像函数那样是在符号表进行链接,所以私有结构的定义需要在本包重复进行一次。也因为本包已有此结构,所以可直接在结构上声明方法,无须显式表达 this 指针。

package another

type cls struct {
    I int
}

func (c *cls) m() {
    println(c.I)
}
package main

import (
    _ "unsafe"

    _ "somewhere.com/someone/another"
)

type cls struct {
    I int
}

//go:linkname (*cls).m somewhere.com/someone/another.(*cls).m
func (c *cls) m()

func main() {
    c := &cls{2}
    c.m()
}

到这里,对于私有结构的公开方法的调用,相信你已心里有数了吧。:D

调用私有全局变量

和函数一样,全局变量也存在于符号表中,因此也可以有这种操作。

package another

var m = map[int]string{
    1: "a",
}

func M(i int) string {
    return m[i]
}
package main

import (
    _ "unsafe"

    "somewhere.com/someone/another"
)

//go:linkname m somewhere.com/someone/another.m
var m map[int]string

func main() {
    println(m[1])
    m[2] = "b"
    println(another.M(2))
}

References

相关文章

  • [Golang] 调用其它包中的私有函数、全局变量

    在使用 Golang 的某些情况下(当然,应该是在万不得已的情况下),你可能需要调用引入的某个包中的某些私有全局变...

  • golang package init 可以多处定义

    在 golang 中 import 包 A 的时候,会自动隐式的调用该包A的 init() 函数。 调用顺序:如果...

  • JavaScript 函数

    函数函数定义与调用变量作用域全局变量方法高阶函数闭包箭头函数$generator$ 函数 函数定义与调用 定义函数...

  • JavaScript 闭包

    JavaScript 变量可以是局部变量或全局变量。私有变量可以用到闭包。 全局变量 函数可以访问由函数内部定义的...

  • Python学习杂记——函数篇

    函数的定义: 函数中调用全局变量:使用global关键字标识 缺省参数: 不定长参数: 元组和字典拆包: 函数的递...

  • web大前端复习——JavaScript

    1.关于闭包 什么是闭包? 闭包是有权限访问其它函数作用域内的变量的一个函数。 在js中,变量分为全局变量和局部变...

  • 大前端面试JS

    1.关于闭包 什么是闭包? 闭包是有权限访问其它函数作用域内的变量的一个函数。 在js中,变量分为全局变量和局部变...

  • Swift-访问权限

    一、private: 表示私有的,除了局部变量其它都可以修饰。 private修饰全局变量、全局函数、枚举、结构体...

  • Golang WebAssembly 前端开发 - 2. Gol

    函数调用 Golang 标准库中的 syscall/js 包提供了一系列接口。其中 js.Global() 返回一...

  • golang中defer的使用

    在golang当中,defer代码块会在函数调用链表中增加一个函数调用。这个函数调用不是普通的函数调用,而是会在函...

网友评论

    本文标题:[Golang] 调用其它包中的私有函数、全局变量

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