go程序中同一個(gè)包下為什么會(huì)存在多個(gè)同名的函數(shù)或變量(詳細(xì)解析)
背景
首先,這種情況顯然是不符合編譯規(guī)則的,我們都知道在同一個(gè)包下出現(xiàn)兩個(gè)同名的函數(shù)、變量、常量等會(huì)編譯不通過(guò),那么怎么還會(huì)有這種現(xiàn)象存在?
如下,源碼中任意找一個(gè)有這種現(xiàn)象的包:
一探究竟
既然都是go代碼,肯定是適配同一套邏輯的。
創(chuàng)建一個(gè)測(cè)試項(xiàng)目,創(chuàng)建一個(gè)包pkg,分別創(chuàng)建如下文件:
我們讓mypkg包下的所有文件中都有GetPackageName函數(shù)(返回的值不同)、flag變量。
注意,這些文件目前并未提示redeclared。
然后main中調(diào)用GetPackageName函數(shù)。
在運(yùn)行之前,編譯器并沒(méi)有顯式的報(bào)錯(cuò)。接著go build,編譯正常。運(yùn)行結(jié)果輸出了:
mypkg from windows
交叉編譯一下Linux平臺(tái),運(yùn)行:
mypkg from linux
看起來(lái)編譯時(shí)自動(dòng)找到對(duì)應(yīng)文件處理了。
繼續(xù)。
在mypkg包下接著新建一個(gè)名為openbsd.go的文件,和上述文件的函數(shù)保持同名,然后很明顯的報(bào)錯(cuò)出來(lái)了:'GetPackageName' redeclared in this package
條件不變,且在pkg_windows.go文件已存在的前提下:
繼續(xù)創(chuàng)建名為_openbsd.go的文件,沒(méi)有報(bào)錯(cuò)。
繼續(xù)創(chuàng)建名為pkg_amd64.go、pkg_x64.go、pkg_x86.go、othername_amd64.go等文件均會(huì)提示redeclared。
但創(chuàng)建的othername_arm64.go、pkg_linux_amd64.go、pkg_linux_arm64.go不會(huì)提示。
對(duì)于linux的兩個(gè)文件,這里看著沒(méi)毛病,實(shí)際上在linux、amd64平臺(tái)上編譯就會(huì)報(bào)錯(cuò):
mypkg\pkg_linux_amd64.go:4:2: flag redeclared in this block
mypkg\pkg_linux.go:4:2: other declaration of flag
mypkg\pkg_linux_amd64.go:7:6: GetPackageName redeclared in this block
mypkg\pkg_linux.go:7:6: other declaration of GetPackageName
是因?yàn)閜kg_linux_amd64.go文件和pkg_linux.go文件的同名內(nèi)容沖突了,在linux、amd64平臺(tái)上編譯,這兩文件就會(huì)被適配到。
如果目標(biāo)平臺(tái)改為linux、arm64進(jìn)行編譯,也會(huì)報(bào):
mypkg\pkg_arm64.go:4:2: flag redeclared in this block
mypkg\othername_arm64.go:4:2: other declaration of flag
mypkg\pkg_arm64.go:7:6: GetPackageName redeclared in this block
mypkg\othername_arm64.go:7:6: other declaration of GetPackageName
mypkg\pkg_linux.go:4:2: flag redeclared in this block
mypkg\othername_arm64.go:4:2: other declaration of flag
mypkg\pkg_linux.go:7:6: GetPackageName redeclared in this block
mypkg\othername_arm64.go:7:6: other declaration of GetPackageName
是因?yàn)閛thername_arm64.go文件、pkg_arm64.go和pkg_linux.go文件的同名內(nèi)容沖突了,在linux、arm64平臺(tái)上編譯,這三個(gè)文件就會(huì)被適配到。
綜合來(lái)看:
1,類(lèi)似約定xxx_windows.go、xxx_arm64.go、xxx_linux_arm64.go命名的文件用于實(shí)現(xiàn)平臺(tái)特定的代碼。
2,編譯器自動(dòng)認(rèn)識(shí)以_系統(tǒng)/arch名稱(chēng)結(jié)尾的go文件。
3,編譯時(shí),GOOS 和 GOARCH都可以在文件名上來(lái)做構(gòu)建約束,go編譯器會(huì)根據(jù)當(dāng)前操作系統(tǒng)自動(dòng)選擇匹配的文件進(jìn)行編譯。
增加構(gòu)建約束 & 不同格式的構(gòu)建約束
例如,針對(duì)不同的系統(tǒng)、架構(gòu)的代碼文件做相同的事情,我們可以進(jìn)行編譯約束:
即,頂部增加如下格式的約束(不能漏掉注釋?zhuān)?/p>
//go:build arm64 && freebsd
如下格式僅針對(duì)特定操作系統(tǒng):
//go:build freebsd
如下格式針對(duì)特定的多個(gè)系統(tǒng)均可:
//go:build aix || darwin || freebsd || linux
如下格式的文件支持在linux系統(tǒng)、但不能在arm或arm64架構(gòu)下進(jìn)行編譯
//go:build linux && !arm && !arm64
感嘆號(hào)表示“非”。
以上是go 1.17及以上版本引入的格式,定義了一個(gè)布爾表達(dá)式,包含了邏輯運(yùn)算符,條件可以更復(fù)雜。
與此不同,下面的格式是go 1.17以下支持的約束格式:
// +build freebsd
也會(huì)有兩種格式并存的情況:
//go:build linux // +build linux
因?yàn)橐灿协h(huán)境是老編譯器的情況,老版本的編譯器不能識(shí)別新的約束語(yǔ)法。
go語(yǔ)言支持的系統(tǒng)和架構(gòu)列表
#go tool dist list aix/ppc64 android/386 android/amd64 android/arm android/arm64 darwin/amd64 darwin/arm64 dragonfly/amd64 freebsd/386 freebsd/amd64 freebsd/arm freebsd/arm64 freebsd/riscv64 illumos/amd64 ios/amd64 ios/arm64 js/wasm linux/386 linux/amd64 linux/arm linux/arm64 linux/loong64 linux/mips linux/mips64 linux/mips64le linux/mipsle linux/ppc64 linux/ppc64le linux/riscv64 linux/s390x netbsd/386 netbsd/amd64 netbsd/arm netbsd/arm64 openbsd/386 openbsd/amd64 openbsd/arm openbsd/arm64 openbsd/ppc64 plan9/386 plan9/amd64 plan9/arm solaris/amd64 wasip1/wasm windows/386 windows/amd64 windows/arm windows/arm64
到此這篇關(guān)于go程序中同一個(gè)包下為什么會(huì)存在多個(gè)同名的函數(shù)或變量的文章就介紹到這了,更多相關(guān)go程序同一個(gè)包存在多個(gè)同名的函數(shù)或變量?jī)?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解golang開(kāi)發(fā)中http請(qǐng)求redirect的問(wèn)題
這篇文章主要介紹了詳解golang開(kāi)發(fā)中http請(qǐng)求redirect的問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10golang如何使用gomobile進(jìn)行Android開(kāi)發(fā)
golang可以開(kāi)發(fā)android,使用golang開(kāi)發(fā)android需要下載安裝gomobile,下面這篇文章主要給大家介紹了關(guān)于golang如何使用gomobile進(jìn)行Android開(kāi)發(fā)的相關(guān)資料,需要的朋友可以參考下2023-01-01Go語(yǔ)言普通指針unsafe.Pointer?uintpt之間的關(guān)系及指針運(yùn)算
這篇文章主要為大家介紹了Go語(yǔ)言普通指針unsafe.Pointer?uintpt之間的關(guān)系及指針運(yùn)算示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12GOPROXY:解決go get golang.org/x包失敗問(wèn)題
這篇文章主要介紹了GOPROXY:解決go get golang.org/x包失敗問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01