go:linkname 是啥?

Defs:

形如 //go:linkname localname importpath.name 的注释叫做 //go:linkname 指令,可理解为名为 localname 的私有函数|变量为 importpath 包下的 name 函数签名提供了实现|变量赋值,从而突破包的访问限制。 

官方解释

PartⅠ:源码实例

time/sleep.go 中存在如下:

func startTimer(*runtimeTimer)
func stopTimer(*runtimeTimer) bool

其实现在 runtime/time.go 

// startTimer adds t to the timer heap.
//go:linkname startTimer time.startTimer
func startTimer(t *timer) {
	if raceenabled {
		racerelease(unsafe.Pointer(t))
	}
	addtimer(t)
}

PartⅡ:实现

目录结构:

main.go

package main

import (
	"demo/usePrivate"
)

func main() {
	usePrivate.Call()
}

 

 private.go

package private

import (
	"fmt"
	_ "unsafe" //私有函数文件要 import  _ "unsafe" 
)

//go:linkname privateStr demo/usePrivate.usePrivateStr
var privateStr = "this is privateStr"

//go:linkname privateFunc demo/usePrivate.usePrivateFunc
func privateFunc() {
	fmt.Print("this is privateFunc\n")
}

usePrivate.go:调用私有函数|变量

package usePrivate

import (
	_ "demo/private" // 函数签名文件要 import 私有函数所在包
	"fmt"
)

func usePrivateFunc()

var usePrivateStr string

func Call() {
	usePrivateFunc()
	fmt.Printf("private str = %s", usePrivateStr)
}

Notes:

1. //go:linkname 不能通过 main 直接访问(试了不行,不清楚为什么)

2. //go:linkname 所在文件要 import  _ "unsafe"

3. 函数签名文件要 import 私有函数所在包

4. 函数签名文件夹要建立后缀为 .s 的空文件,原因在于Go在编译的时候会启用 -complete 编译器flag,它要求所有的函数必需包含函数体,创建一个空的汇编语言文件绕过这个限制。

 

参考:https://colobu.com/2017/05/12/call-private-functions-in-other-packages/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值