home icon Kha Research Blog
GithubTwitter

Go linkname directive

go:linkname directive

The go document says:

//go:linkname localname [importpath.name]

The //go:linkname directive instructs the compiler to use "importpath.name" as the object file symbol name for the variable or function declared as "localname" in the source code. If the "importpath.name" argument is omitted, the directive uses the symbol's default object file symbol name and only has the effect of making the symbol accessible to other packages. Because this directive can subvert the type system and package modularity, it is only enabled in files that have imported "unsafe".

What is the use case of this ?

It is only used for accessing unexported function.

It's primarily a hack that lets certain functions live in the runtime package, and access runtime internals, but still pretend that they are unexported functions of some different package. Look for the uses of go:linkname in the runtime package itself.

Practice

Let's make a time package.

package mono

import (
	_ "unsafe" // for go:linkname
)

//go:linkname now runtime.nanotime1
func now() int64

The benchmark:

package mono

import (
	"testing"
	"time"
)

func BenchmarkNow(b *testing.B) {
	for i := 0; i < b.N; i++ {
		_ = now()
	}
}

func BenchmarkTimeNow(b *testing.B) {
	for i := 0; i < b.N; i++ {
		_ = time.Now()
	}
}

The result is amazing.

goos: darwin
goarch: amd64
pkg: github.com/lotusirous/mono
cpu: Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
BenchmarkNow-16        	40866225	        29.14 ns/op	       0 B/op	       0 allocs/op
BenchmarkTimeNow-16    	18258596	        64.80 ns/op	       0 B/op	       0 allocs/op
PASS
ok  	github.com/lotusirous/tstime/mono	4.260s