Go中的Package和Module分析


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下有三個目錄

  1. src: 存儲我們包的路路徑
  2. pkg:是存儲go install的歸檔文件
  3. 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

歡迎大家關注微信公眾號:“技術人技術事”,更多精彩期待你的到來

![](https://img2018.cnblogs.com/blog/706455/201908/706455-20190821134639128-1638065311.jpg)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM