Go 言語のソース コードには、関数シグネチャのみを持つコードがたくさんありますが、関数本体が表示されません。例:
// src/os/proc.go 68行 func runtime_beforeExit() // implemented in runtime
ここでは、関数シグネチャのみが表示されますが、関数本体は表示されません。グローバルに検索した結果、その関数本体は src/runtime/proc.go で定義されていることがわかりました。
// os_beforeExit is called from os.Exit(0). //go:linkname os_beforeExit os.runtime_beforeExit func os_beforeExit() { if raceenabled { racefini() } }
go:linkname を通じて関数シグネチャと関数本体を接続します。では、これをコードで実装できるでしょうか?これはライブラリ関数で使用できるので、独自のコード構造でも使用できますか?以下は、そのような使用法を段階的に実装するための実験的な方法です。
Create project directory
$mkdir demo && cd demo
go mod initialize project directory
$go mod init demo
関数シグネチャ pkg と関数本体 pkg の作成
$mkdir hello $mkdir link
テスト コードの作成
$cd hello // 函数签名 $vim hello.go package hello import ( _ "demo/link" ) func Hello() // 函数体 $vim link.go package link import _ "unsafe" //go:linkname helloWorld demo/hello.Hello func helloWorld() { println("hello world!") }
コードの実行
$cd demo vim demo.go package main import ( "demo/hello" ) func main() { hello.Hello() }
コンパイルと実行
go run demo.go # demo/hello hello/hello.go:7:6: missing function body
hello フォルダに aa.s のアセンブリ ファイル マークを追加すると、コンパイルと実行が可能です
$cd hello && touch aa.s $go run demo.go hello world!