go package包的使用以及路徑問題

前言

一開始學(xué) Go,非常暈的就是 package 包的問題,我們知道 Go 有一個(gè)很簡單的文件可見性規(guī)則:首字母大寫即對(duì)外可見,但是不知道對(duì)外是對(duì)什么外。
以及我在一個(gè) ch1 目錄下,創(chuàng)建一個(gè) demo.go 文件,在輸入 package 時(shí), VS 又會(huì)自動(dòng)提示 package ch1,這個(gè)和 main 又有什么關(guān)系呢?
我在一個(gè) ch1 目錄下寫了一個(gè) demo.go 文件,里面有一個(gè)函數(shù),我在 ch2/demo2.go 里面想用又該怎么 import 呢?
帶著這些疑問,這次來系統(tǒng)的了解一下~

Go的環(huán)境變量

在我們安裝完 go 之后,輸入

go env

會(huì)輸出一大堆信息,其中 GOPATH 就是我們的工作區(qū),我們寫了一個(gè) demo.go 文件,其中如果 import 了一些第三方庫,運(yùn)行的時(shí)候就會(huì)先從 GOROOT 中找,如果沒有找到會(huì)再去 GOPATH 里面找
我們可以通過修改 GOPATH 添加額外的工作區(qū),在你的 .zshrc / .bash_profile 文件里面

export GOPATH="/Users/lijun/go:/Users/lijun/Documents/Go/golearning"

引入第三方庫

一般我們通過

go get -u github.com/julienschmidt/httprouter

這個(gè)指令下載的第三方庫都會(huì)保存在 GOPATH 第一個(gè)工作區(qū)指定的 src 目錄下
只需要在項(xiàng)目里

import "github.com/julienschmidt/httprouter"

就能使用這個(gè)第三方包了

有時(shí)候 go get 下載失敗,可以手動(dòng)去 GitHub 下載源代碼,放到對(duì)應(yīng)目錄下,記住路徑要和 GitHub 上的文件路徑一致

在當(dāng)前文件使用另一個(gè)文件定義的函數(shù)或變量

  • 同級(jí)目錄
    在class文件夾下新建 demo.go 和 demo_lib.go
// demo_lib.go
package main

import "fmt"

func hello(name string) {
    fmt.Printf("Hello, %s!\n", name)
}
// demo.go
package main

import "flag"

var name string

func init() {
    flag.StringVar(&name, "name", "everyone", "The greeting object.")
}

func main() {
    flag.Parse()
    hello(name)
}

當(dāng)在一個(gè)同級(jí)目錄下面,有一個(gè) package main 實(shí)現(xiàn)了 main() 函數(shù)的時(shí)候,這是作為程序的唯一入口。在同級(jí)目錄下,別的文件也必須 package main,且不能再實(shí)現(xiàn) main() 函數(shù),否則提示 redeclared 錯(cuò)誤。
此時(shí) demo_lib.go 文件里的變量和函數(shù)對(duì) demo.go 都是可見的。且不受可見性影響

  • 不同級(jí)目錄
    現(xiàn)在我們?cè)?class 文件夾下新建 lib 文件夾,在新建一個(gè) demo2_lib.go 文件,demo2_lib 現(xiàn)在就有兩種可能了
    1. package main 并且實(shí)現(xiàn) main() 函數(shù),那么它就是另一個(gè)新程序的入口了,內(nèi)部的函數(shù)和變量就不能被別的文件 import
    2. package 包名,這樣的話是可以被外部使用,但是我們需要把首字母大寫,對(duì)外部可見(這里了解了對(duì)外部是指對(duì)別的包而言),我們現(xiàn)在測試這種情況
package lib

import "fmt"

func Hello(name string) {
    fmt.Println("Hello, %s!\n",)
}

如果 demo.go 要使用 demo2_lib 下的 Hello 函數(shù),需要導(dǎo)入這個(gè)包。這時(shí)候我們需要 go install 一下

go install class/lib

后面的路徑是要導(dǎo)入的包的相對(duì)路徑,執(zhí)行完之后,會(huì)在我們的工作區(qū)下生成 pkg/darwin_amd64/class/lib.a


2019-08-21-11.png

在 demo.go 導(dǎo)入即可

package main

import (
    "class/lib"
    "flag"
)

var name string

func init() {
    flag.StringVar(&name, "name", "everyone", "The greeting object.")
}

func main() {
    flag.Parse()
    lib.Hello(name)
}

到這里我們算是完成了一個(gè)供外部調(diào)用的包的程序

這里有個(gè)疑問

我在 class/lib 文件夾下創(chuàng)建的 demo2_lib.go 文件,并且 package lib,package的包名和所在文件夾名有必然聯(lián)系嗎?

// demo2_lib.go
package lib2

import "fmt"

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

改成 lib2 試一下
go install 后面跟的是路徑,所以依然是 class/lib

go install class/lib

在主函數(shù)什么都不改變,調(diào)用

go run demo.go

此時(shí)提示

# command-line-arguments
./demo.go:4:2: imported and not used: "class2/lib" as lib2
./demo.go:18:2: undefined: lib

從字面上理解一下的話,第一個(gè)是說導(dǎo)入了但是沒有把 class2/lib 當(dāng)做 lib2 來使用,第二行說沒有定義的 lib

emmm~~~

我記得 import 包的時(shí)候可以起個(gè)別名的,試一下

package main

import (
    lib2 "class/lib"
    "flag"
)

var name string

func init() {
    flag.StringVar(&name, "name", "everyone", "The greeting object.")
}

func main() {
    flag.Parse()
    lib2.Hello(name)
}

繼續(xù)運(yùn)行一下,輸出結(jié)果

lijun:class2/ $ go run demo.go     
Hello, everyone!

可以了?。。?br> 想一下,我們主要做了什么,和之前有什么不同
在路徑 class/lib 下,demo2_lib.go 文件沒有 package lib,而是 package lib2

// 原來
package lib

// 現(xiàn)在
package lib2

go install class/lib 這個(gè)步驟沒有變也變不了。
最后在 main 函數(shù)中調(diào)用,原來是

import "class/lib"

lib.Hello(name)

現(xiàn)在是

import lib2 "class/lib"

lib2.Hello(name)

也就是說,當(dāng)我們要在一個(gè)項(xiàng)目里新建一個(gè) tool 文件夾放我們的工具包,我們可以不 package tool,而是可以寫一個(gè)別的包名,依然可以使用,只不過在使用的時(shí)候,import 的還是 pkg 下的路徑,但是要給這個(gè) import 設(shè)置它真正的包名,即這里的 lib2

總結(jié)

算是弄明白了 Go 下的文件引用,以及 GOPATH 的設(shè)置。
同一級(jí)目錄下只能有一個(gè) main,且別的文件對(duì)它都是可見的,不需要設(shè)置大小寫都可以被訪問到,不同級(jí)目錄,根據(jù)首字母大小寫可見,還需要 go install一下,再 import 對(duì)應(yīng)路徑,包名可以和路徑不一致,但是要設(shè)置別名。
簡單了解后,如果還有別的疑惑歡迎大家一起探討!

來自 https://leejnull.github.io/2019/08/21/2019-08-21-1/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本項(xiàng)課程分為兩個(gè)階段,第一階段將讓學(xué)員全面了解并掌握Hadoop的架構(gòu)原理和使用場景,并通過貫穿課程的項(xiàng)目進(jìn)行實(shí)戰(zhàn)...
    小波yagamis閱讀 418評(píng)論 0 1
  • 不知不覺我要混成了適齡結(jié)婚女青年,周圍人紛紛踏入婚姻的圍城,而我在圍城之外自得其樂。 嗯,接下來要講故事了,...
    胖胖歡閱讀 394評(píng)論 0 0
  • 關(guān)于愛你 清晨,陽光開始溫暖,像隔壁阿姨家廚房里的飯菜香味,讓人想念。這是一個(gè)美麗的清晨,可以讓人忘掉憂傷。 每個(gè)...
    磊平閱讀 391評(píng)論 0 2

友情鏈接更多精彩內(nèi)容