go linkname 使用

在 go 中如果希望调用某些模块的私有方法,可以使用 //go:linkname 来实现,过程很简单,以调用 runtime.fastrand 为例

首先,在文件中写入如下内容,注意,//go:linkname ... 之间不能有空格!!

1
2
3
4
5
6
7
8
9
10
import _ "unsafe"

//go:linkname fastrand runtime.fastrand
//go:nosplit
func fastrand() uint32

//go:nosplit
func fastrandn(n uint32) uint32 {
return uint32(uint64(fastrand()) * uint64(n) >> 32)
}

然后,同级目录下创建一个空的汇编文件 i.s ,这样 go build 的时候就不会报错了。

大功告成,测试一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main

import (
"fmt"
_ "unsafe"
)

//go:linkname fastrand runtime.fastrand
//go:nosplit
func fastrand() uint32

//go:nosplit
func fastrandn(n uint32) uint32 {
return uint32(uint64(fastrand()) * uint64(n) >> 32)
}

func main() {
fmt.Println(fastrandn(100))
}
1
2
3
4
5
6
7
8
9
> tree

.
├── cmd.go
└── i.s

> go run cmd.go

28