Package
所謂package(包)其實就是代碼的一種組織管理方式,代碼多了就需要放入文件,文件多了就需要歸類放入文件夾,就好比我們在給電腦裝軟件時會進行歸類安裝,其實也是有意無意對電腦軟件安裝的一種管理方式。那么不同的go文件交給不同的package管理時,如果A package需要引用 B package中的文件時go是怎么處理的?基於此,我們來對go的package和module一探究竟
我們以一個例子來學習,這里假設我們做一個學生管理系統,如下代碼
//學生管理系統(學生管理package,成績管理package,主package)
student_manage_system
student_manage
student.go
achievement_manage
achievement.go
main
main.go
student.go文件內容如下
package student_manage
func QueryStudent(no string) Student{
}
//main.go 文件內容如下
package main
import student_manage
func main() {
student := sutdent_manage.QueryStudent("stuNo")
}
在main包需要依賴student_manage包查詢學生對象,在go中是通過import
關鍵字導入我們需要使用的包的路徑,什么是包,什么是包的路徑?以student_manage文件夾 和package后面寫的student_manage為例,乍一看,一模一樣,沒什么區別;其實不然,在go中文件夾名稱和包名稱是可以不一樣的;需要使用其它包中的方法時,引入包所在的路徑,真實使用時,是通過包名.的形式去使用,
舉個例子
假設文件夾名稱為:student_manage,
包名為:student
那么在main中使用時,應該import student_manage ,但真實調用其方法時應該是student.QueryStudent("stuNo"),在真實項目中,go官方建議文件夾名稱和包的名稱一樣,以防止歧義產生,同時盡量簡短。
理解了package,那么go是如何尋找包路徑的,看下面代碼
package main
import(
"fmt"
"student_manage"
)
func main(){
}
如上代碼中,我們引入了fmt包,student_manage包,我們知道fmt是go sdk中的包,student_manage是我們自己的包,在go中,有兩個變量:goroot和gopath
GOOOT
goroot指的是go的安裝路徑,比如 D:\sdk\go12;在這個目錄下有一個src的文件夾 D:\sdk\go12\src,大家可以點進去看一下,在里面你會找到fmt包。
GOAPTH
gopath是go項目的路徑,我們開發一個學生管理系統,通過gopath指定學生管理系統路徑
gopath下有三個目錄
- src: 存儲我們包的路路徑
- pkg:是存儲go install的歸檔文件
- bin: 存儲go的可執行文件
舉個例子如下,假設gopath指定路徑D:\mygo,那么最終目錄結構為
D:\mygo\
src
student_manage_system(項目名稱)
student_manage
student.go
main
mian.go
pkg
存儲最后打包后的歸檔文件
bin
存儲執行文件
Module
舉個例子,我們在使用別人的包的時候需要引入,比如小明開發了一個消息中間件MQ,我們在使用時如何引入小明的包,了解Java的人都知道Maven, Java中包的管理,依賴,版本等是通過maven中央倉庫引入,也就是你開發一個Java程序可以打成jar包,上傳maven中央倉庫,那么別人使用是就可以通過mavnen坐標來引入你開發的jar,那么go中這一切是怎么做的呢?
在Go1.11之后go官方推出了Go Module,在這之前Go的包管理百花齊放(也意味着比較混亂),主流的有 govender,glide,gopm,以及半官方的 dep,這里對這些不做介紹,感興趣的可以去google一下,我們主要學習一下Go官方的Module
剛才我們提到了java的maven中央倉庫,誰開發了誰上傳,誰想用誰下載,go也有這么一個中央倉庫,就是大名鼎鼎的 github,我們還以學生管理系統為例,在說項目之前,再說一下gopath,在go1.11之后,gopath概念淡化了許多,不再是以前的結構,gopath的作用是存儲項目依賴的包路徑,項目本身可以創建在任何地方
//go1.11之后gopath
默認gopath路徑,當前系統賬戶目錄下會有一個go目錄,如下
C:/Users/sunpengwei/go
pkg
mod
整體目錄是
C:/Users/sunpengwei/go/pkg/mod
Go module具體如何使用呢?我們在github上新建一個學生管理系統,然后git clone到本地
student_manage_system
在根目錄下執行 go mod init 會在項目目錄下生成一個go.mod文件,
文件內容是module student_manage_system(module的名稱)
go 1.12(go的版本)
有了go.mod 文件,假設我們需要引用一個redis第三方包
go.mod 中有兩個關鍵字 reuqire replace
require字段: require github.com/gomodule/redigo v2.0.0+incompatible
require 代表必須,必要的, github.com/gomodule/redigo 是包的路徑 v2.0.0是版本 +incompatible暫且不討論,這樣我們就在項目中使用了redigo包,就可以使用redigo包中的方法了,在真實使用時我們只需要的是導入具體的包,如下代碼示例
module student_manage_system
require github.com/gomodule/redigo v2.0.0+incompatible
go 1.12
package main
import(
"github.com/gomodule/redigo/redis"
)
func main(){
}
replace字段,從字面理解意思是替換
假設學生管理系統有兩個包student_manage和achievement_manage
現在achievement_manage包需要使用student_manage包中的方法怎么辦?我們的項目托管給了github,
此時包路徑為 github.com/sunpengwei1992/student_manage_system,
但這時我們能的代碼並沒有上傳至github,這個時候replace字段就開始使用了,我們對包路徑進行了替換 。
把github.com/sunpengwei1992/student_manage_system替換成 ./
在本地使用時只需要通過 ./student_manage使用就可以了
replace github.com/sunpengwei1992/student_manage_system v1.0.0 => ./
Go module 常用的一些命令
go mod init module_name 初始化mod文件
go mod tidy 下載依賴的包
go get github.com/jtianling/goModule@latest 的形式更新到最新版
go get -u 的形式升級所有的依賴庫
go mod edit -require="github.com/chromedp/chromedp@v0.1.0" 修改指定的版本,修改之后執行第二步
如何給一個項目打上版本號,這是通過git的tag來做到的
git tag查詢所有的tag
git tag -a v1.0 -m "對Tag的描述信息"
git push origin --tags
大家可以看我github的代碼測試:https://github.com/sunpengwei1992/go_module_test
歡迎大家關注微信公眾號:“技術人技術事”,更多精彩期待你的到來
