新聞中心
前言

Hey,大家好呀,我是星期八,咱們?cè)瓉?lái)寫(xiě)的代碼,都是縮在一塊的,久而久之咱們可能都能感覺(jué)到冗余。
所以今天就來(lái)學(xué)一下包這個(gè)東西,將咱們的代碼拆分一下。
包
包可以理解為存放多個(gè).go的文件夾但是這個(gè)文件夾下面的第一行的package后面跟的不再是main了而是文件名,就像這樣。
目錄
clac和main.go文件是同級(jí)的。
可以看到clac文件夾下的add.go第一行不再是main而是文件夾名 clac同理sub.go第一行也是。
這個(gè)只是單獨(dú)的解釋包的定義方式?jīng)]有實(shí)際意義。
包的注意事項(xiàng)
如果這個(gè)文件夾要當(dāng)包使用文件夾名中不能包含_。
導(dǎo)入包
上面我們知道了包是如何定義的。
并且在和main.go同級(jí)的項(xiàng)目目錄下建了一個(gè)clac包。
在clac包下有倆個(gè)文件一個(gè)是add.go一個(gè)是sub.go兩個(gè)文件夾分別都有對(duì)應(yīng)的方法。問(wèn)題來(lái)了???
那我們?nèi)绾卧趍ain.go中使用上述建立的包調(diào)用里面的方法呢?
這就是要導(dǎo)入它們了。
示例代碼
- package main
- import (
- "a3_course/clac"
- )
- func main() {
- clac.Add()
- clac.Sub()
- }
執(zhí)行結(jié)果
可以看到在main.go中成功調(diào)用了clac包中的代碼。
注:導(dǎo)入包只需要導(dǎo)入到文件夾即可就可以調(diào)用下面所有的方法和屬性不再需要包名.xx.go這種方式。
如上述導(dǎo)入calc不管calc下面有幾個(gè).go文件里面的方法和屬性都可以隨便調(diào)用。
導(dǎo)入包注意事項(xiàng)
上述我是直接通過(guò)
- import (
- "a3_course/clac"
- )
這種方式導(dǎo)入包的但是在你們那可能不太行。
因?yàn)槲沂褂玫氖莋o mod所以通過(guò)項(xiàng)目目錄/包名導(dǎo)入。
如果你沒(méi)有使用go mod是傳統(tǒng)的方式那么導(dǎo)入包需要從GOPATH/src進(jìn)行導(dǎo)入這里不舉例了。
如果還不會(huì)使用go mod記得爬樓看以往文章,上面有教程,一篇文章教會(huì)你如何使用Go語(yǔ)言Modules,記得要擁抱未來(lái)噢。
可見(jiàn)性
可見(jiàn)性在其他語(yǔ)言中有的叫私有成員之類的稱呼在Go中就叫可見(jiàn)性。
Go中可見(jiàn)性很簡(jiǎn)單不管是變量還是函數(shù)還是結(jié)構(gòu)體。
首字母大寫(xiě)在哪都能訪問(wèn)。
首字母小寫(xiě)只能在當(dāng)前包使用。
示例
- package clac
- import (
- "fmt"
- )
- //這是一個(gè)公開(kāi)的變量
- var Name = "張三"
- //這是一個(gè)私有變量,只能在 clac 包中訪問(wèn)
- var age = 18
- //這是一個(gè)公開(kāi)的函數(shù)
- func Add() {
- fmt.Println("我是做加法的...")
- }
main.go文件
- func main() {
- clac.Add()
- clac.Sub()
- fmt.Println(clac.Name)
- //clac中的age是小寫(xiě)開(kāi)頭,屬于私有變量,所以其他包不能訪問(wèn)
- //fmt.Println(clac.age) // cannot refer to unexported name clac.age
- }
訪問(wèn)私有變量報(bào)錯(cuò)信息。
結(jié)構(gòu)體可見(jiàn)性的問(wèn)題
我們知道結(jié)構(gòu)體是有字段的但是你想過(guò)結(jié)構(gòu)體的字段大小寫(xiě)問(wèn)題嗎?
- type Student struct {
- Name string
- age int
- }
- //age是小寫(xiě)開(kāi)頭
結(jié)構(gòu)體名開(kāi)頭是不是大寫(xiě)影響的主要是在其他包里面的調(diào)用權(quán)限問(wèn)題。
結(jié)構(gòu)體字段開(kāi)頭是不是大寫(xiě)主要影響的是調(diào)用里面字段的問(wèn)題一個(gè)明顯的問(wèn)題就是序列化。
更多結(jié)構(gòu)體的相關(guān)文章,可前往:Go語(yǔ)言基礎(chǔ)之結(jié)構(gòu)體(春日篇)
示例代碼
- package main
- import (
- "encoding/json"
- "fmt"
- )
- type Student struct {
- Name string
- age int
- }
- func main() {
- var s1 = Student{
- Name: "張三",
- age: 18,
- }
- serializeBytes,err:=json.Marshal(s1)
- if err != nil {
- fmt.Println("序列化失敗")
- }
- serializeStr := string(serializeBytes)
- fmt.Println(serializeStr)
- }
執(zhí)行結(jié)果
會(huì)發(fā)現(xiàn)執(zhí)行結(jié)果少了一個(gè)age。
這是因?yàn)閍ge小寫(xiě)開(kāi)頭屬于私有變量。
但是json.Marshal(s1)這個(gè)已經(jīng)屬于其他包了所以訪問(wèn)不到age。
包別名
我們?cè)趯?dǎo)入包時(shí)其實(shí)還可以自定義包名就像Python中的 from xx import xx as yy。
示例代碼
- package main
- //給 clac 包起別名
- import cl "a3_course/clac"
- func main() {
- cl.Add()
- }
執(zhí)行結(jié)果
匿名導(dǎo)入包
匿名導(dǎo)入包就是相當(dāng)于不用這個(gè)包里面的東西。
可能有人就會(huì)問(wèn)了那不用包里面的東西,那還導(dǎo)入作甚呢?
嗯...這個(gè)匿名導(dǎo)入包主要要跟包的一個(gè)init方法有關(guān)系咱們先繼續(xù)看。
匿名導(dǎo)入包示例代碼
- package main
- //前面有個(gè) _ 就表示是匿名導(dǎo)入
- import _ "a3_course/clac"
- func main() {
- }
包的init方法
其實(shí)每次導(dǎo)入其他包的時(shí)候都會(huì)執(zhí)行包的init方法。
示例
- //clac/add.go
- package clac
- import "fmt"
- func init() {
- fmt.Println("clac/add.go/init")
- }
- func Sub() {
- fmt.Println("我是做減法的...")
- }
- //clac/sub.go
- package clac
- import "fmt"
- func init() {
- fmt.Println("clac/sub.go/init")
- }
- func Sub() {
- fmt.Println("我是做減法的...")
- }
main.go
- package main
- import _ "a3_course/clac"
- func main() {
- }
執(zhí)行結(jié)果
可以發(fā)現(xiàn)我雖然是匿名導(dǎo)入包但是仍然還是執(zhí)行了add.go和sub.go下的init方法。
這就說(shuō)明了一個(gè)問(wèn)題導(dǎo)入一個(gè)包會(huì)執(zhí)行這個(gè)包下面所有的init方法不管下面有幾個(gè).go文件。
注:包的init方法不能寫(xiě)參數(shù)也不能有返回值init方法只能在導(dǎo)入時(shí)調(diào)用不能主動(dòng)調(diào)用。
init方法比main方法更提前一步執(zhí)行。
多個(gè)包嵌套導(dǎo)入時(shí)init方法執(zhí)行的順序
代碼較多就直接如圖所示了:
這意思是main.go導(dǎo)入了other包other包導(dǎo)入了inner包 ,套娃。
先看一下執(zhí)行結(jié)果
執(zhí)行結(jié)果是inner的init方法先執(zhí)行然后是ohter的init方法。
其實(shí)本質(zhì)是碰到import就執(zhí)行被導(dǎo)入包的init方法。
它的圖應(yīng)該是這樣子的。
意思是main導(dǎo)入了ohter那就執(zhí)行other的init方法。
但是在導(dǎo)入ohter時(shí)發(fā)現(xiàn)other導(dǎo)入了inner那就執(zhí)行inner的init方法。
總結(jié)
上述我們學(xué)習(xí)了Go基礎(chǔ)之包,學(xué)習(xí)了如何創(chuàng)建包,組織包,導(dǎo)入包的注意事項(xiàng)。包的權(quán)限問(wèn)題(大寫(xiě)開(kāi)頭所有可見(jiàn)),匿名導(dǎo)入包,init方法,多個(gè)init方法注意事項(xiàng)。
可能有點(diǎn)不太好理解,但是還是要堅(jiān)持,一定要多敲兩次。
當(dāng)前名稱:手把手教會(huì)你帶你理解Go語(yǔ)言中的包
文章URL:http://m.fisionsoft.com.cn/article/cohphhd.html


咨詢
建站咨詢
