如果代碼太復(fù)雜,就可以把代碼寫在多個(gè)源碼文件里?;蛘呤瞧渌a包中(這個(gè)后面講)
成都創(chuàng)新互聯(lián),專注為中小企業(yè)提供官網(wǎng)建設(shè)、營(yíng)銷型網(wǎng)站制作、響應(yīng)式網(wǎng)站設(shè)計(jì)、展示型成都做網(wǎng)站、成都網(wǎng)站設(shè)計(jì)等服務(wù),幫助中小企業(yè)通過(guò)網(wǎng)站體現(xiàn)價(jià)值、有效益。幫助企業(yè)快速建站、解決網(wǎng)站建設(shè)與網(wǎng)站營(yíng)銷推廣問(wèn)題。下面是程序的主體,但是其中調(diào)用了square()函數(shù),這個(gè)函數(shù)并沒(méi)有聲明:
// Go36/article03/example01/demo.go
package main
import (
"flag"
"fmt"
)
var x int
func init() {
flag.IntVar(&x, "x", 0, "計(jì)算平方")
}
func main() {
flag.Parse()
res := square(x)
fmt.Println(x, "的平方:", res)
}
上面用到的square()函數(shù)被聲明在了另一個(gè)文件中:
// Go36/article03/example01/calc.go
package main
func square(x int) int {
return x * x
}
這里只聲明了一個(gè)函數(shù),可以在這個(gè)寫更多關(guān)于計(jì)算的函數(shù),這樣在同個(gè)包里都可以方便的調(diào)用這些函數(shù)使用。
上面的2個(gè)文件都要在同一個(gè)目錄下,并且需要被聲明為屬于同一個(gè)包。
因?yàn)槭纠卸悸暶鳛閙ain包,并且包里也有一個(gè)main函數(shù)。所以存在一個(gè)命令源碼文件,這樣就可以直接運(yùn)行起來(lái):
PS H:\Go\src\Go36\article03\example01> go run demo.go calc.go -x 3
3 的平方: 9
PS H:\Go\src\Go36\article03\example01>
上面注意要把所有的文件都寫在命令里。
還可以先構(gòu)建代碼包,在執(zhí)行:
PS H:\Go\src> go build Go36/article03/example01
PS H:\Go\src> .\example01.exe -x 4
4 的平方: 16
PS H:\Go\src>
先修改calc.go的路徑,并且做一些修改:
// Go36/article03/example02/lib/calc.go
package lib2
func Square(x int) int {
return x * x
}
這里創(chuàng)建了一個(gè)子目錄,把文件放到了這個(gè)子目錄中,這樣使得它同命令源碼文件不在同一個(gè)目錄下了。
并行代碼也做了一些修改:
現(xiàn)在要使用上面的包。導(dǎo)入包的路徑應(yīng)該是目錄的路徑名稱:
import (
"Go36/article03/example02/lib"
)
如果要構(gòu)建或者安裝這個(gè)代碼包,使用的命令應(yīng)該是下面這樣,還是用目錄名稱:
go install Go36/article03/example02/lib
并且命令成功后,pkg子目錄產(chǎn)生的歸檔文件也是目錄名稱:
pkg\windows_amd64\Go36\article03\example02\lib.a
但是最后調(diào)用的時(shí)候需要使用包名稱,命令源碼文件的代碼如下:
// Go36/article03/example02/demo.go
package main
import (
"flag"
"fmt"
"Go36/article03/example02/lib"
)
var x int
func init() {
flag.IntVar(&x, "x", 0, "計(jì)算平方")
}
func main() {
flag.Parse()
res := lib2.Square(x)
fmt.Println(x, "的平方:", res)
}
上面調(diào)用程序時(shí)使用的lib2.稱為限定符。
結(jié)論:導(dǎo)入路徑使用的是文件所在目錄的路徑。而調(diào)用程序時(shí)使用的限定符要與它聲明的包的名稱一致。
為了不在使用代碼包是產(chǎn)生困惑,應(yīng)該讓聲明的包的名稱與其父目錄的目錄名稱一致。
在這里把函數(shù)名稱的首字母改為大寫的原因是,名稱的首字母為大寫的程序?qū)嶓w才可以被當(dāng)前包外的代碼引用,否則它就只能被當(dāng)前包內(nèi)的其他代碼引用。
這涉及了Go語(yǔ)言中對(duì)于程序?qū)嶓w訪問(wèn)權(quán)限的規(guī)則。通過(guò)名稱的首字母的大小寫,就把訪問(wèn)權(quán)限分為了包級(jí)私有和公開這兩種。對(duì)于包級(jí)私有,只有在包內(nèi)部可以訪問(wèn)。由于我們需要在main包里調(diào)用lib包的函數(shù),只能訪問(wèn)到公開的部分,所以需要把函數(shù)的首字母大寫。
模塊級(jí)私有
上面的訪問(wèn)權(quán)限都以包的級(jí)別進(jìn)行劃分的。在Go 1.5及后續(xù)版本中,可以通過(guò)創(chuàng)建internal代碼包讓一些程序?qū)嶓w僅僅能被當(dāng)前模塊中的其他代碼引用。這是第三種訪問(wèn)權(quán)限:模塊級(jí)私有。
具體規(guī)則是,internal代碼包中聲明的公開程序?qū)嶓w僅能被該代碼包的直接父包及其子包中的代碼引用。當(dāng)然,引用前需要先導(dǎo)入這個(gè)internal包。對(duì)于其他代碼包,導(dǎo)入該internal包都是非法的,無(wú)法通過(guò)編譯。
這里的名稱必須是internal,示例如下:
// 父級(jí)目錄 Go36/article03/example03/demo.go
package main
import (
"flag"
"Go36/article03/example03/lib"
//"Go36/article03/example03/lib/internal" // 此行無(wú)法通過(guò)編譯。
)
var x int
func init() {
flag.IntVar(&x, "x", 0, "計(jì)算平方")
}
func main() {
flag.Parse()
lib.Cale(x)
//res := internal.Square(x)
//lib.Cale(res)
}
// 子級(jí)目錄 Go36/article03/example03/lib/demo_lib.go
package lib
import (
"fmt"
"Go36/article03/example03/lib/internal"
)
func Cale(x int) {
res := internal.Square(x)
fmt.Println(x, "的平方:", res)
}
// 孫子目錄 Go36/article03/example03/lib/internal/internal.go
package internal
func Square(x int) int {
return x * x
}
模塊級(jí)私有的internal包,僅能被直接父包及其子包中的代碼引用。上面如果要在父級(jí)里調(diào)用孫級(jí)目錄的internal包,就是非法的:
PS H:\Go\src\Go36\article03\example03> go run demo.go -x 7
demo.go:6:2: use of internal package not allowed
PS H:\Go\src\Go36\article03\example03>
創(chuàng)新互聯(lián)www.cdcxhl.cn,專業(yè)提供香港、美國(guó)云服務(wù)器,動(dòng)態(tài)BGP最優(yōu)骨干路由自動(dòng)選擇,持續(xù)穩(wěn)定高效的網(wǎng)絡(luò)助力業(yè)務(wù)部署。公司持有工信部辦法的idc、isp許可證, 機(jī)房獨(dú)有T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確進(jìn)行流量調(diào)度,確保服務(wù)器高可用性。佳節(jié)活動(dòng)現(xiàn)已開啟,新人活動(dòng)云服務(wù)器買多久送多久。