最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

模塊一 GO語(yǔ)言基礎(chǔ)知識(shí)-庫(kù)源碼文件

 更新時(shí)間:2021年01月26日 09:49:51   作者:lvp  
這篇文章主要介紹了模塊一 GO語(yǔ)言基礎(chǔ)知識(shí)-庫(kù)源碼文件,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

你已經(jīng)使用過(guò) Go 語(yǔ)言編寫(xiě)了小命令(或者說(shuō)微型程序)嗎?

當(dāng)你在編寫(xiě)“Hello, world”的時(shí)候,一個(gè)源碼文件就足夠了,雖然這種小玩意兒沒(méi)什么用,最多能給你一點(diǎn)點(diǎn)莫名的成就感。如果你對(duì)這一點(diǎn)點(diǎn)并不滿(mǎn)足,別著急,跟著學(xué),我肯定你也可以寫(xiě)出很厲害的程序。

我們?cè)谏弦黄奈恼轮袑W(xué)到了命令源碼文件的相關(guān)知識(shí),那么除了命令源碼文件,你還能用 Go 語(yǔ)言編寫(xiě)庫(kù)源碼文件。那么什么是庫(kù)源碼文件呢?

在我的定義中,庫(kù)源碼文件是不能被直接運(yùn)行的源碼文件,它僅用于存放程序?qū)嶓w,這些程序?qū)嶓w可以被其他代碼使用(只要遵從 Go 語(yǔ)言規(guī)范的話(huà))。

這里的“其他代碼”可以與被使用的程序?qū)嶓w在同一個(gè)源碼文件內(nèi),也可以在其他源碼文件,甚至其他代碼包中。

那么程序?qū)嶓w是什么呢?在 Go 語(yǔ)言中,程序?qū)嶓w是變量、常量、函數(shù)、結(jié)構(gòu)體和接口的統(tǒng)稱(chēng)。我們總是會(huì)先聲明(或者說(shuō)定義)程序?qū)嶓w,然后再去使用。比如在上一篇的例子中,我們先定義了變量name,然后在main函數(shù)中調(diào)用fmt.Printf函數(shù)的時(shí)候用到了它。再多說(shuō)一點(diǎn),程序?qū)嶓w的名字被統(tǒng)稱(chēng)為標(biāo)識(shí)符。標(biāo)識(shí)符可以是任何 Unicode 編碼可以表示的字母字符、數(shù)字以及下劃線(xiàn)“_”,但是其首字母不能是數(shù)字。從規(guī)則上說(shuō),我們可以用中文作為變量的名字。但是,我覺(jué)得這種命名方式非常不好,自己也會(huì)在開(kāi)發(fā)團(tuán)隊(duì)中明令禁止這種做法。作為一名合格的程序員,我們應(yīng)該向著編寫(xiě)國(guó)際水準(zhǔn)的程序無(wú)限逼近。

回到正題。

我們今天的問(wèn)題是:怎樣把命令源碼文件中的代碼拆分到其他庫(kù)源碼文件?

我們用代碼演示,把這個(gè)問(wèn)題說(shuō)得更具體一些。

如果在某個(gè)目錄下有一個(gè)命令源碼文件 demo4.go,如下:

package main
 
import (
 "flag"
)
 
var name string
 
func init() {
 flag.StringVar(&name, "name", "everyone", "The greeting object.")
}
 
func main() {
 flag.Parse()
 hello(name)
}

其中的代碼你應(yīng)該比較眼熟了。我在講命令源碼文件的時(shí)候貼過(guò)很相似的代碼,那個(gè)源碼文件名為 demo2.go。

這兩個(gè)文件的不同之處在于,demo2.go 直接通過(guò)調(diào)用fmt.Printf函數(shù)打印問(wèn)候語(yǔ),而當(dāng)前的 demo4.go 在同樣位置調(diào)用了一個(gè)叫作hello的函數(shù)。

函數(shù)hello被聲明在了另外一個(gè)源碼文件中,我把它命名為 demo4_lib.go,并且放在與 demo4.go 相同的目錄下。如下:

// 需在此處添加代碼。[1]
 
import "fmt"
 
func hello(name string) {
 fmt.Printf("Hello, %s!\n", name)
}

那么問(wèn)題來(lái)了:注釋 1 處應(yīng)該填入什么代碼?

典型回答

答案很簡(jiǎn)單,填入代碼包聲明語(yǔ)句package main。為什么?我之前說(shuō)過(guò),在同一個(gè)目錄下的源碼文件都需要被聲明為屬于同一個(gè)代碼包。

如果該目錄下有一個(gè)命令源碼文件,那么為了讓同在一個(gè)目錄下的文件都通過(guò)編譯,其他源碼文件應(yīng)該也聲明屬于main包。

如此一來(lái),我們就可以運(yùn)行它們了。比如,我們可以在這些文件所在的目錄下運(yùn)行如下命令并得到相應(yīng)的結(jié)果。

$ go run demo4.go demo4_lib.go
Hello, everyone!

或者,像下面這樣先構(gòu)建當(dāng)前的代碼包再運(yùn)行。

$ go build puzzlers/article3/q1
$ ./q1   
Hello, everyone!

在這里,我把 demo4.go 和 demo4_lib.go 都放在了一個(gè)相對(duì)路徑為puzzlers/article3/q1的目錄中。

在默認(rèn)情況下,相應(yīng)的代碼包的導(dǎo)入路徑會(huì)與此一致。我們可以通過(guò)代碼包的導(dǎo)入路徑引用其中聲明的程序?qū)嶓w。但是,這里的情況是不同的。

注意,demo4.go 和 demo4_lib.go 都聲明自己屬于main包。我在前面講 Go 語(yǔ)言源碼的組織方式的時(shí)候提到過(guò)這種用法,即:源碼文件聲明的包名可以與其所在目錄的名稱(chēng)不同,只要這些文件聲明的包名一致就可以。

順便說(shuō)一下,我為本專(zhuān)欄創(chuàng)建了一個(gè)名為“Golang_Puzzlers”的項(xiàng)目。該項(xiàng)目的 src 子目錄下會(huì)存有我們涉及的所有代碼和相關(guān)文件。

也就是說(shuō),正確的用法是,你需要把該項(xiàng)目的打包文件下載到本地的任意目錄下,然后經(jīng)解壓縮后把“Golang_Puzzlers”目錄加入到環(huán)境變量GOPATH中。還記得嗎?這會(huì)使“Golang_Puzzlers”目錄成為工作區(qū)之一。

問(wèn)題解析

這個(gè)問(wèn)題考察的是代碼包聲明的基本規(guī)則。這里再總結(jié)一下。

第一條規(guī)則,同目錄下的源碼文件的代碼包聲明語(yǔ)句要一致。也就是說(shuō),它們要同屬于一個(gè)代碼包。這對(duì)于所有源碼文件都是適用的。

如果目錄中有命令源碼文件,那么其他種類(lèi)的源碼文件也應(yīng)該聲明屬于main包。這也是我們能夠成功構(gòu)建和運(yùn)行它們的前提。

第二條規(guī)則,源碼文件聲明的代碼包的名稱(chēng)可以與其所在的目錄的名稱(chēng)不同。在針對(duì)代碼包進(jìn)行構(gòu)建時(shí),生成的結(jié)果文件的主名稱(chēng)與其父目錄的名稱(chēng)一致。

對(duì)于命令源碼文件而言,構(gòu)建生成的可執(zhí)行文件的主名稱(chēng)會(huì)與其父目錄的名稱(chēng)相同,這在我前面的回答中也驗(yàn)證過(guò)了。

好了,經(jīng)過(guò)我的反復(fù)強(qiáng)調(diào),相信你已經(jīng)記住這些規(guī)則了。下面的內(nèi)容也將會(huì)與它們相關(guān)。

在編寫(xiě)真正的程序時(shí),我們僅僅把代碼拆分到幾個(gè)源碼文件中是不夠的。我們往往會(huì)用模塊化編程的方式,根據(jù)代碼的功能和用途把它們放置到不同的代碼包中。不過(guò),這又會(huì)牽扯進(jìn)一些 Go 語(yǔ)言的代碼組織規(guī)則。我們一起來(lái)往下看。

知識(shí)精講

1. 怎樣把命令源碼文件中的代碼拆分到其他代碼包?

我們先不用關(guān)注拆分代碼的技巧。我在這里仍然依從前面的拆分方法。我把 demo4.go 另存為 demo5.go,并放到一個(gè)相對(duì)路徑為puzzlers/article3/q2的目錄中。

然后我再創(chuàng)建一個(gè)相對(duì)路徑為puzzlers/article3/q2/lib的目錄,再把 demo4_lib.go 復(fù)制一份并改名為 demo5_lib.go 放到該目錄中。

現(xiàn)在,為了讓它們通過(guò)編譯,我們應(yīng)該怎樣修改代碼?你可以先思考一下。我在這里給出一部分答案,我們一起來(lái)看看已經(jīng)過(guò)修改的 demo5_lib.go 文件。

package lib5
 
import "fmt"
 
func Hello(name string) {
 fmt.Printf("Hello, %s!\n", name)
}

可以看到,我在這里修改了兩個(gè)地方。第一個(gè)改動(dòng)是,我把代碼包聲明語(yǔ)句由package main改為了package lib5。注意,我故意讓聲明的包名與其所在的目錄的名稱(chēng)不同。第二個(gè)改動(dòng)是,我把全小寫(xiě)的函數(shù)名hello改為首字母大寫(xiě)的Hello。

基于以上改動(dòng),我們?cè)賮?lái)看下面的幾個(gè)問(wèn)題。

2. 代碼包的導(dǎo)入路徑總會(huì)與其所在目錄的相對(duì)路徑一致嗎?

庫(kù)源碼文件 demo5_lib.go 所在目錄的相對(duì)路徑是puzzlers/article3/q2/lib,而它卻聲明自己屬于lib5包。在這種情況下,該包的導(dǎo)入路徑是puzzlers/article3/q2/lib,還是puzzlers/article3/q2/lib5?

這個(gè)問(wèn)題往往會(huì)讓 Go 語(yǔ)言的初學(xué)者們困惑,就算是用 Go 開(kāi)發(fā)過(guò)程序的人也不一定清楚。我們一起來(lái)看看。

首先,我們?cè)跇?gòu)建或者安裝這個(gè)代碼包的時(shí)候,提供給go命令的路徑應(yīng)該是目錄的相對(duì)路徑,就像這樣:

go install puzzlers/article3/q2/lib

該命令會(huì)成功完成。之后,當(dāng)前工作區(qū)的 pkg 子目錄下會(huì)產(chǎn)生相應(yīng)的歸檔文件,具體的相對(duì)路徑是:

pkg/darwin_amd64/puzzlers/article3/q2/lib.a

其中的darwin_amd64就是我在講工作區(qū)時(shí)提到的平臺(tái)相關(guān)目錄??梢钥吹?,這里與源碼文件所在目錄的相對(duì)路徑是對(duì)應(yīng)的。

為了進(jìn)一步說(shuō)明問(wèn)題,我需要先對(duì) demo5.go 做兩個(gè)改動(dòng)。第一個(gè)改動(dòng)是,在以import為前導(dǎo)的代碼包導(dǎo)入語(yǔ)句中加入puzzlers/article3/q2/lib,也就是試圖導(dǎo)入這個(gè)代碼包。

第二個(gè)改動(dòng)是,把對(duì)hello函數(shù)的調(diào)用改為對(duì)lib.Hello函數(shù)的調(diào)用。其中的lib.叫做限定符,旨在指明右邊的程序?qū)嶓w所在的代碼包。不過(guò)這里與代碼包導(dǎo)入路徑的完整寫(xiě)法不同,只包含了路徑中的最后一級(jí)lib,這與代碼包聲明語(yǔ)句中的規(guī)則一致。

現(xiàn)在,我們可以通過(guò)運(yùn)行g(shù)o run demo5.go命令試一試。錯(cuò)誤提示會(huì)類(lèi)似于下面這種。

./demo5.go:5:2: imported and not used: "puzzlers/article3/q2/lib" as lib5
./demo5.go:16:2: undefined: lib

第一個(gè)錯(cuò)誤提示的意思是,我們導(dǎo)入了puzzlers/article3/q2/lib包,但沒(méi)有實(shí)際使用其中的任何程序?qū)嶓w。這在 Go 語(yǔ)言中是不被允許的,在編譯時(shí)就會(huì)導(dǎo)致失敗。

注意,這里還有另外一個(gè)線(xiàn)索,那就是“as lib5”。這說(shuō)明雖然導(dǎo)入了代碼包puzzlers/article3/q2/lib,但是使用其中的程序?qū)嶓w的時(shí)候應(yīng)該以lib5.為限定符。這也就是第二個(gè)錯(cuò)誤提示的原因了。Go 命令找不到lib.這個(gè)限定符對(duì)應(yīng)的代碼包。

為什么會(huì)是這樣?根本原因就是,我們?cè)谠创a文件中聲明所屬的代碼包與其所在目錄的名稱(chēng)不同。請(qǐng)記住,源碼文件所在的目錄相對(duì)于 src 目錄的相對(duì)路徑就是它的代碼包導(dǎo)入路徑,而實(shí)際使用其程序?qū)嶓w時(shí)給定的限定符要與它聲明所屬的代碼包名稱(chēng)對(duì)應(yīng)。

有兩個(gè)方式可以使上述構(gòu)建成功完成。我在這里選擇把 demo5_lib.go 文件中的代碼包聲明語(yǔ)句改為package lib。理由是,為了不讓該代碼包的使用者產(chǎn)生困惑,我們總是應(yīng)該讓聲明的包名與其父目錄的名稱(chēng)一致。

3. 什么樣的程序?qū)嶓w才可以被當(dāng)前包外的代碼引用?

你可能會(huì)有疑問(wèn),我為什么要把 demo5_lib.go 文件中的那個(gè)函數(shù)名稱(chēng)hello的首字母大寫(xiě)?實(shí)際上這涉及了 Go 語(yǔ)言中對(duì)于程序?qū)嶓w訪(fǎng)問(wèn)權(quán)限的規(guī)則。

超級(jí)簡(jiǎn)單,名稱(chēng)的首字母為大寫(xiě)的程序?qū)嶓w才可以被當(dāng)前包外的代碼引用,否則它就只能被當(dāng)前包內(nèi)的其他代碼引用。

通過(guò)名稱(chēng),Go 語(yǔ)言自然地把程序?qū)嶓w的訪(fǎng)問(wèn)權(quán)限劃分為了包級(jí)私有的和公開(kāi)的。對(duì)于包級(jí)私有的程序?qū)嶓w,即使你導(dǎo)入了它所在的代碼包也無(wú)法引用到它。

4. 對(duì)于程序?qū)嶓w,還有其他的訪(fǎng)問(wèn)權(quán)限規(guī)則嗎?

答案是肯定的。在 Go 1.5 及后續(xù)版本中,我們可以通過(guò)創(chuàng)建internal代碼包讓一些程序?qū)嶓w僅僅能被當(dāng)前模塊中的其他代碼引用。這被稱(chēng)為 Go 程序?qū)嶓w的第三種訪(fǎng)問(wèn)權(quán)限:模塊級(jí)私有。

具體規(guī)則是,internal代碼包中聲明的公開(kāi)程序?qū)嶓w僅能被該代碼包的直接父包及其子包中的代碼引用。當(dāng)然,引用前需要先導(dǎo)入這個(gè)internal包。對(duì)于其他代碼包,導(dǎo)入該internal包都是非法的,無(wú)法通過(guò)編譯。

“Golang_Puzzlers”項(xiàng)目的puzzlers/article3/q4包中有一個(gè)簡(jiǎn)單的示例,可供你查看。你可以改動(dòng)其中的代碼并體會(huì)internal包的作用。

總結(jié)

我們?cè)诒酒恼轮性敿?xì)討論了把代碼從命令源碼文件中拆分出來(lái)的方法,這包括拆分到其他庫(kù)源碼文件,以及拆分到其他代碼包。

這里涉及了幾條重要的 Go 語(yǔ)言基本編碼規(guī)則,即:代碼包聲明規(guī)則、代碼包導(dǎo)入規(guī)則以及程序?qū)嶓w的訪(fǎng)問(wèn)權(quán)限規(guī)則。在進(jìn)行模塊化編程時(shí),你必須記住這些規(guī)則,否則你的代碼很可能無(wú)法通過(guò)編譯。

思考題

  1. 如果你需要導(dǎo)入兩個(gè)代碼包,而這兩個(gè)代碼包的導(dǎo)入路徑的最后一級(jí)是相同的,比如:dep/lib/flag和flag,那么會(huì)產(chǎn)生沖突嗎?如果會(huì)產(chǎn)生沖突,那么怎樣解決這種沖突,有幾種方式?

到此這篇關(guān)于模塊一 GO語(yǔ)言基礎(chǔ)知識(shí)-庫(kù)源碼文件的文章就介紹到這了,更多相關(guān)GO語(yǔ)言庫(kù)源碼文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • go語(yǔ)言使用pipe讀取子進(jìn)程標(biāo)準(zhǔn)輸出的方法

    go語(yǔ)言使用pipe讀取子進(jìn)程標(biāo)準(zhǔn)輸出的方法

    這篇文章主要介紹了go語(yǔ)言使用pipe讀取子進(jìn)程標(biāo)準(zhǔn)輸出的方法,實(shí)例分析了Go語(yǔ)言針對(duì)進(jìn)程操作的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-03-03
  • GoLang完整實(shí)現(xiàn)快速列表

    GoLang完整實(shí)現(xiàn)快速列表

    這篇文章主要介紹了GoLang完整實(shí)現(xiàn)快速列表,列表是一種非連續(xù)的存儲(chǔ)容器,由多個(gè)節(jié)點(diǎn)組成,節(jié)點(diǎn)通過(guò)一些 變量 記錄彼此之間的關(guān)系,列表有多種實(shí)現(xiàn)方法,如單鏈表、雙鏈表等
    2022-12-12
  • Golang壓縮Jpeg圖片和PNG圖片的操作

    Golang壓縮Jpeg圖片和PNG圖片的操作

    這篇文章主要介紹了Golang壓縮Jpeg圖片和PNG圖片的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • Go 協(xié)程超時(shí)控制的實(shí)現(xiàn)

    Go 協(xié)程超時(shí)控制的實(shí)現(xiàn)

    本文主要介紹了Go 協(xié)程超時(shí)控制的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • Golang函數(shù)式編程深入分析實(shí)例

    Golang函數(shù)式編程深入分析實(shí)例

    習(xí)慣與函數(shù)式編程語(yǔ)言的開(kāi)發(fā)者,會(huì)認(rèn)為for循環(huán)和if判斷語(yǔ)句是冗長(zhǎng)的代碼,通過(guò)使用map和filter處理集合元素讓代碼更可讀。本文介紹Go閉包實(shí)現(xiàn)集合轉(zhuǎn)換和過(guò)濾功能
    2023-01-01
  • Go項(xiàng)目與Docker結(jié)合實(shí)現(xiàn)高效部署深入探究

    Go項(xiàng)目與Docker結(jié)合實(shí)現(xiàn)高效部署深入探究

    在現(xiàn)代軟件開(kāi)發(fā)中,使用Docker部署應(yīng)用程序已經(jīng)成為一種標(biāo)準(zhǔn)實(shí)踐,本文將深入探討如何將Go項(xiàng)目與Docker結(jié)合,實(shí)現(xiàn)高效、可靠的部署過(guò)程,通過(guò)詳細(xì)的步驟和豐富的示例,你將能夠迅速掌握這一流程
    2023-12-12
  • Go調(diào)度器學(xué)習(xí)之協(xié)作與搶占詳解

    Go調(diào)度器學(xué)習(xí)之協(xié)作與搶占詳解

    如果某個(gè)G執(zhí)行時(shí)間過(guò)長(zhǎng),其他的G如何才能被正常調(diào)度,這就引出了接下來(lái)的話(huà)題:協(xié)作與搶占。本文將通過(guò)一些示例為大家詳細(xì)講講調(diào)度器中協(xié)作與搶占的相關(guān)知識(shí),需要的可以參考一下
    2023-04-04
  • 示例剖析golang中的CSP并發(fā)模型

    示例剖析golang中的CSP并發(fā)模型

    這篇文章主要為大家介紹了示例剖析golang中的CSP并發(fā)模型,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • Golang網(wǎng)絡(luò)模型netpoll源碼解析(具體流程)

    Golang網(wǎng)絡(luò)模型netpoll源碼解析(具體流程)

    本文介紹了Golang的網(wǎng)絡(luò)模型netpoll的實(shí)現(xiàn)原理,本文將從為什么需要使用netpoll模型,以及netpoll的具體流程實(shí)現(xiàn)兩個(gè)主要角度來(lái)展開(kāi)學(xué)習(xí),感興趣的朋友跟隨小編一起看看吧
    2024-11-11
  • Golang中slice刪除元素的性能對(duì)比

    Golang中slice刪除元素的性能對(duì)比

    go沒(méi)有對(duì)刪除切片元素提供專(zhuān)用的語(yǔ)法或者接口,需要使用切片本身的特性來(lái)刪除元素,下面這篇文章主要給大家介紹了關(guān)于Golang中slice刪除元素的性能對(duì)比,需要的朋友可以參考下
    2022-06-06

最新評(píng)論

亚东县| 军事| 闵行区| 台南县| 通化市| 佛山市| 保山市| 东海县| 友谊县| 吉首市| 铅山县| 时尚| 吴川市| 乡城县| 呼玛县| 定日县| 普兰店市| 平昌县| 康保县| 比如县| 和平区| 湘西| 德庆县| 双鸭山市| 松原市| 依安县| 彰武县| 营口市| 巴中市| 吉林省| 剑阁县| 铜鼓县| 尖扎县| 龙山县| 罗甸县| 介休市| 门头沟区| 枣阳市| 阜新市| 徐州市| 夏邑县|