真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

golang中的鏈接link是什么

  • 我們編寫的程序可能會使用其他程序或程序庫( library ) 正如我們在helloworld程序中使用的fmt package

  • 我們編寫的程序必須與這些程序或程序庫一起才能夠執(zhí)行

  • 鏈接是將我們編寫的程序與我們需要的外部程序組合在一起的過程

  • 鏈接器是系統(tǒng)軟件,在系統(tǒng)開發(fā)中起著至關(guān)重要的作用,因為它可以進(jìn)行單獨的編譯。您可以將它分解為更小,更易管理的塊,然后分別進(jìn)行修改和編譯,而不是將一個大型應(yīng)用程序組織為一個整體的源文件。當(dāng)您更改其中一個模塊時,只需重新編譯它并重新鏈接應(yīng)用程序,而無需重新編譯其他源文件。

  • 鏈接分為兩種,靜態(tài)鏈接與動態(tài)鏈接

  • 靜態(tài)鏈接的特點在于鏈接器會將程序中使用的所有庫程序復(fù)制到最后的可執(zhí)行文件中。而動態(tài)鏈接只會在最后的可執(zhí)行文件中存儲動態(tài)鏈接庫的位置,并在運行時調(diào)用。

  • 因此靜態(tài)鏈接要更快,可移植,因為它不需要在運行它的系統(tǒng)上存在該庫。但是在磁盤和內(nèi)存上占用更多的空間

  • 鏈接發(fā)生的過程會在兩個地方,一種是靜態(tài)鏈接會在編譯時的最后一步發(fā)生,一種是動態(tài)鏈接在程序加載到內(nèi)存時發(fā)生。

  • 下面我們簡單對比一下靜態(tài)鏈接與動態(tài)鏈接

go語言是靜態(tài)鏈接還是動態(tài)鏈接?

  • 有時會看到一些比較老的文章說go語言是靜態(tài)鏈接的,但這種說法是不準(zhǔn)確的

  • 現(xiàn)在的go語言不僅支持靜態(tài)鏈接也支持動態(tài)編譯

  • 總的來說,go語言在一般默認(rèn)情況下是靜態(tài)鏈接的,但是一些特殊的情況,例如使用了CGO(即引用了C代碼)的地方,則會使用操作系統(tǒng)的動態(tài)鏈接庫。例如go語言的net/http包在默認(rèn)情況下會應(yīng)用libpthread與 libc 的動態(tài)鏈接庫,這種情況會導(dǎo)致go語言程序虛擬內(nèi)存的增加(下一文介紹)

  • go語言也支持在go build編譯時傳遞參數(shù)來指定要生成的鏈接庫的方式,我們可以使用go help buildmode 命令查看

? go help buildmode                                                                                                                                                             jackson@192
    -buildmode=archive
        Build the listed non-main packages into .a files. Packages named
        main are ignored.

    -buildmode=c-archive
        Build the listed main package, plus all packages it imports,
        into a C archive file. The only callable symbols will be those
        functions exported using a cgo //export comment. Requires
        exactly one main package to be listed.

    -buildmode=c-shared
        Build the listed main package, plus all packages it imports,
        into a C shared library. The only callable symbols will
        be those functions exported using a cgo //export comment.
        Requires exactly one main package to be listed.

    -buildmode=default
        Listed main packages are built into executables and listed
        non-main packages are built into .a files (the default
        behavior).

    -buildmode=shared
        Combine all the listed non-main packages into a single shared
        library that will be used when building with the -linkshared
        option. Packages named main are ignored.

    -buildmode=exe
        Build the listed main packages and everything they import into
        executables. Packages not named main are ignored.

    -buildmode=pie
        Build the listed main packages and everything they import into
        position independent executables (PIE). Packages not named
        main are ignored.

    -buildmode=plugin
        Build the listed main packages, plus all packages that they
        import, into a Go plugin. Packages not named main are ignored.
  • archive: 將非 main package構(gòu)建為 .a 文件. main 包將被忽略。

  • c-archive: 將 main package構(gòu)建為及其導(dǎo)入的所有package構(gòu)建為構(gòu)建到 C 歸檔文件中

  • c-shared: 將mainpackage構(gòu)建為,以及它們導(dǎo)入的所有package構(gòu)建到C 動態(tài)庫中。

  • shared: 將所有非 main package合并到一個動態(tài)庫中,當(dāng)使用-linkshared參數(shù)后,能夠使用此動態(tài)庫

  • exe: 將main package和其導(dǎo)入的package構(gòu)建為成為可執(zhí)行文件

  • 本文不再介紹go如何手動使用動態(tài)庫這一高級功能,讀者只需現(xiàn)在知道go可以實現(xiàn)這一功能即可

編譯與鏈接的具體過程

  • 下面我們以helloworld程序為例,來說明go語言編譯與鏈接的過程,我們可以使用go build命令,-x參數(shù)代表了打印執(zhí)行的過程

go build  -x main.go

輸出如下:

WORK=/var/folders/g2/0l4g444904vbn8wxnrw0j_980000gn/T/go-build757876739
mkdir -p $WORK/b001/
cat >$WORK/b001/importcfg << 'EOF' # internal
# import config
packagefile fmt=/usr/local/go/pkg/darwin_amd64/fmt.a
packagefile runtime=/usr/local/go/pkg/darwin_amd64/runtime.a
EOF
cd /Users/jackson/go/src/viper/XXX
/usr/local/go/pkg/tool/darwin_amd64/compile -o $WORK/b001/_pkg_.a -trimpath "$WORK/b001=>" -p main -complete -buildid JqleDuJlC1iLMVADicsQ/JqleDuJlC1iLMVADicsQ -goversion go1.13.6 -D _/Users/jackson/go/src/viper/args -importcfg $WORK/b001/importcfg -pack -c=4 ./main.go
/usr/local/go/pkg/tool/darwin_amd64/buildid -w $WORK/b001/_pkg_.a # internal
cp $WORK/b001/_pkg_.a /Users/jackson/Library/Caches/go-build/cf/cf0dc65f39f01c8494192fa8af14570b445f6a25b762edf0b7258c22d6e10dc8-d # internal
cat >$WORK/b001/importcfg.link << 'EOF' # internal
packagefile command-line-arguments=$WORK/b001/_pkg_.a
packagefile fmt=/usr/local/go/pkg/darwin_amd64/fmt.a
packagefile runtime=/usr/local/go/pkg/darwin_amd64/runtime.a
packagefile errors=/usr/local/go/pkg/darwin_amd64/errors.a
...
EOF
mkdir -p $WORK/b001/exe/
cd .
/usr/local/go/pkg/tool/darwin_amd64/link -o $WORK/b001/exe/a.out -importcfg $WORK/b001/importcfg.link -buildmode=exe -buildid=zCU3mCFNeUDzrRM33f4L/JqleDuJlC1iLMVADicsQ/r7xJ7p5GD5T9VONtmxob/zCU3mCFNeUDzrRM33f4L -extld=clang $WORK/b001/_pkg_.a
/usr/local/go/pkg/tool/darwin_amd64/buildid -w $WORK/b001/exe/a.out # internal
mv $WORK/b001/exe/a.out main
rm -r $WORK/b001/
  • 下面我們對輸出進(jìn)行逐行分析

  • 創(chuàng)建了一個臨時目錄,用于存放臨時文件。默認(rèn)情況下命令結(jié)束時自動刪除此目錄,如果需要保留添加-work參數(shù)。

WORK=/var/folders/g2/0l4g444904vbn8wxnrw0j_980000gn/T/go-build757876739
mkdir -p $WORK/b001/
cat >$WORK/b001/importcfg << 'EOF' # internal
  • 生成編譯配置文件,主要為編譯過程需要的外部依賴(如:引用的其他包的函數(shù)定義)

# import config
packagefile fmt=/usr/local/go/pkg/darwin_amd64/fmt.a
packagefile runtime=/usr/local/go/pkg/darwin_amd64/runtime.a
  • 編譯,生成中間結(jié)果$WORK/b001/pkg.a,

/usr/local/go/pkg/tool/darwin_amd64/compile -o $WORK/b001/_pkg_.a -trimpath "$WORK/b001=>" -p main -complete -buildid JqleDuJlC1iLMVADicsQ/JqleDuJlC1iLMVADicsQ -goversion go1.13.6 -D _/Users/jackson/go/src/viper/args -importcfg $WORK/b001/importcfg -pack -c=4 ./main.go
  • .a文件由compile命令生成,也可以通過go tool compile進(jìn)行調(diào)用

  • .a類型的文件又叫做目標(biāo)文件(object file),其是一個壓縮包,內(nèi)部包含了_.PKGDEF`、`_go.o兩個文件,分別為編譯目標(biāo)文件和鏈接目標(biāo)文件

$ file _pkg_.a # 檢查文件格式
_pkg_.a: current ar archive # 說明是ar格式的打包文件
$ ar x _pkg_.a #解包文件
$ ls
__.PKGDEF  _go_.o
  • 文件內(nèi)容由代碼導(dǎo)出的函數(shù)、變量以及引用的其他包的信息組成。為了弄清這兩個文件包含的信息需要查看go編譯器實現(xiàn)的相關(guān)代碼,相關(guān)代碼在src/cmd/compile/internal/gc/obj.go文件中(源碼中的文件內(nèi)容可能隨版本更新變化,本系列文章以Go1.13.5版本為準(zhǔn))

  • 下面代碼中生成ar文件,ar文件 是一種非常簡單的打包文件格式,廣泛用于linux中靜態(tài)鏈接庫文件中,文件以 字符串"!\n"開頭。隨后跟著60字節(jié)的文件頭部(包含文件名、修改時間等信息),之后跟著文件內(nèi)容。因為ar文件格式簡單,Go編譯器直接在函數(shù)中實現(xiàn)了ar打包過程。

  • startArchiveEntry用于預(yù)留ar文件頭信息位置(60字節(jié)),finishArchiveEntry用于寫入文件頭信息,因為文件頭信息中包含文件大小,在寫入完成之前文件大小未知,所以分兩步完成。

func dumpobj1(outfile string, mode int) {
    bout, err := bio.Create(outfile)
    if err != nil {
        flusherrors()
        fmt.Printf("can't create %s: %v\n", outfile, err)
        errorexit()
    }
    defer bout.Close()
    bout.WriteString("!\n")

    if mode&modeCompilerObj != 0 {
        start := startArchiveEntry(bout)
        dumpCompilerObj(bout)
        finishArchiveEntry(bout, start, "__.PKGDEF")
    }
    if mode&modeLinkerObj != 0 {
        start := startArchiveEntry(bout)
        dumpLinkerObj(bout)
        finishArchiveEntry(bout, start, "_go_.o")
    }
}
  • 生成鏈接配置文件,主要為需要鏈接的其他依賴

cat >$WORK/b001/importcfg.link << 'EOF' # internal
packagefile command-line-arguments=$WORK/b001/_pkg_.a
packagefile fmt=/usr/local/go/pkg/darwin_amd64/fmt.a
packagefile runtime=/usr/local/go/pkg/darwin_amd64/runtime.a
packagefile errors=/usr/local/go/pkg/darwin_amd64/errors.a
...
EOF
  • 執(zhí)行鏈接器,生成最終可執(zhí)行文件main,同時可執(zhí)行文件會拷貝到當(dāng)前路徑,最后刪除臨時文件

/usr/local/go/pkg/tool/darwin_amd64/link -o $WORK/b001/exe/a.out -importcfg $WORK/b001/importcfg.link -buildmode=exe -buildid=zCU3mCFNeUDzrRM33f4L/JqleDuJlC1iLMVADicsQ/r7xJ7p5GD5T9VONtmxob/zCU3mCFNeUDzrRM33f4L -extld=clang $WORK/b001/_pkg_.a
/usr/local/go/pkg/tool/darwin_amd64/buildid -w $WORK/b001/exe/a.out # internal
mv $WORK/b001/exe/a.out main
rm -r $WORK/b001/


文章名稱:golang中的鏈接link是什么
URL標(biāo)題:http://weahome.cn/article/psecdg.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部