1. 程式人生 > >Go包管理

Go包管理

什麼是包?為什麼要使用包?

為了更好地組織類,Java 和GO都提供了包機制,用於區別類名的名稱空間。

包的作用

  • 1、把功能相似或相關的類或介面組織在同一個包中,方便類的查詢和使用。

  • 2、如同資料夾一樣,包也採用了樹形目錄的儲存方式。同一個包中的類名字是不同的,不同的包中的類的名字是可以相同的,當同時呼叫兩個不同包中相同類名的類時,應該加上包名加以區別。因此,包可以避免名字衝突。

  • 3、包也限定了訪問許可權,擁有包訪問許可權的類才能訪問某個包中的類。

比如Go內建的net包
net
├── http
├── internal
├── mail
├── rpc
├── smtp
├── testdata
├── textproto
└── url
以上是net包的一個目錄結構,net本身是一個包,net目錄下的http又是一個包。從這個大家可以看到,go語言的包其實就是我們計算機裡的目錄,或者叫資料夾,通過它們進行目錄結構和檔案組織,go只是對目錄名字做了一個翻譯,叫【包】而已。比如這裡的net包其實就是net目錄,http包其實就是http目錄,這也是go語言中的一個命名習慣,包名和檔案所在的目錄名是一樣的。

包的命名

go語言的包的命名,遵循簡潔、小寫、和go檔案所在目錄同名的原則,這樣就便於我們引用,書寫以及快速定位查詢。在Java裡面有一句話叫做見名知意。

比如go自帶的http這個包,它這個http目錄下的所有go檔案都屬於這個http包,所以我們使用http包裡的函式、介面的時候,匯入這個http包就可以了。

package main
import "net/http"
func main() {
	http.ListenAndServe("127.0.0.1:80",handler);
}

從這個例子可以看到,我們匯入的是net/http,這在go裡叫做全路徑,因為http包在net裡面,net是最頂級的包,所以必須使用全路徑匯入,go編譯程式才能找到http這個包,和我們檔案系統的目錄路徑是一樣的。

因為有了全路徑,所以命名的包名可以和其他庫的一樣,只要它們的全路徑不同就可以了,使用全路徑的匯入,也增加了包名命名的靈活性。

對於自己或者公司開發的程式而言,我們一般採用域名作為頂級包名的方式,這樣就不用擔心和其他開發者包名重複的問題了。

main包

當把一個go檔案的包名宣告為main時,就等於告訴go編譯程式,我這個是一個可執行的程式,那麼go編譯程式就會嘗試把它編譯為一個二進位制的可執行檔案。

一個main的包,一定會包含一個main()函式,這種我們也不陌生,比如C和Java都有main()函式,它是一個程式的入口,沒這個函式,程式就無法執行。在go語言裡,同時要滿足main包和包含main()函式,才會被編譯成一個可執行檔案。

我們看一個Hello World的Go語言版本,來說明main 包。

package main


import (
"fmt"
)


func main() {
/* 這是我的第一個簡單的程式 */
fmt.Println("Hello, World!")
}

假設該go檔案叫hello.go,放在$GOPATH/src/hello目錄下,那麼我們在這個目錄下執行go build命令就會生成二進位制的可執行檔案,在window系統下生成的是hello.exe,在Unix,MAC和Linux下生成的是hello,我們在CMD或者終端裡執行它,就可以看到控制檯列印的:Hello,World。但是有一個很奇怪的現象,就是如果你建立的包名並不叫main,比如說叫test,我在test下面建立一個hello.go方法,執行起來肯定不對,但是如果我改成包名為main,就可以執行成。這在Java裡面是不允許的,因為你在某個包下面建立的類必須屬於這個包,go語言似乎可以動態的指定包,而不拘泥於當前類擺放的位置。

二進位制可執行檔案的名字,就是該main包的go檔案所在目錄的名字,因為hello.go在hello目錄下,所以生成的可執行檔案就是hello這個名字。

import 關鍵字

要想使用一個包,必須先匯入它才可以使用,Go語言提供了import關鍵字來匯入一個包,這個關鍵字告訴Go編譯器到磁碟的哪裡去找要想匯入的包,所以匯入的包必須是一個全路徑的包,也就是包所在的位置。
import "fmt"
這就表示我們匯入了fmt包,也就等於告訴go編譯器,我們要使用這個包下面的程式碼。如果要匯入多個包怎麼辦呢?Go語言還為我們提供的匯入塊。
import (
	"net/http"
	"fmt"
)

使用一對括號包含的匯入塊,每個包獨佔一行。

對於多於一個路徑的包名,在程式碼中引用的時候,使用全路徑最後一個包名作為引用的包名,比如net/http,我們在程式碼使用的是http,而不是net

現在我匯入了包,那麼編譯的時候,go編譯器去什麼位置找他們呢?這裡就要介紹下Go的環境變量了。Go有兩個很重要的環境變數GOROOTGOPATH,這是兩個定義路徑的環境變數,GOROOT是安裝Go的路徑,比如/usr/local/goGOPATH是我們自己定義的開發者個人的工作空間,比如/home/flysnow/go

編譯器會使用我們設定的這兩個路徑,再加上import匯入的相對全路徑來查詢磁碟上的包,比如我們匯入的fmt包,編譯器最終找到的是/usr/local/go/fmt這個位置。

值得了解的是:對於包的查詢,是有優先順序的,編譯器會優先在GOROOT裡搜尋,其次是GOPATH,一旦找到,就會馬上停止搜尋。如果最終都沒找到,就報編譯異常了。

遠端包匯入

網際網路的時代,現在大家使用類似於Github共享程式碼的越來越多,如果有的Go包共享在Github上,我們一樣有辦法使用他們,這就是遠端匯入包了,或者是網路匯入,Go天生就支援這種情況,所以我們可以很隨意的使用Github上的Go庫開發程式。
import "github.com/spf13/cobra"

這種匯入,前提必須是該包託管在一個分散式的版本控制系統上,比如Github、Bitbucket等,並且是Public的許可權,可以讓我們直接訪問它們。

編譯在匯入它們的時候,會先在GOPATH下搜尋這個包,如果沒有找到,就會使用go get工具從版本控制系統(GitHub)獲取,並且會把獲取到的原始碼儲存在GOPATH目錄下對應URL的目錄裡,以供編譯使用。

go get工具可以遞迴獲取依賴包,如果github.com/spf13/cobra也引用了其他的遠端包,該工具可以一併下載下來。

這種匯入看起來是不是很像Java的maven裡面的pom檔案匯入類。go裡面直接簡化了匯入包的方法,需要哪個包直接匯入就好,而不需要再去建立maven專案,在寫一個pom類確實很方便。

命名匯入

我們知道,在使用import關鍵字匯入包之後,我們就可以在程式碼中通過包名使用該包下相應的函式、介面等。如果我們匯入的包名正好有重複的怎麼辦呢?針對這種情況,Go語言可以讓我們對匯入的包重新命名,這就是命名匯入。在Java中一個包的名稱可能會有部分重複,但是沒有全部重複的概念。
package main
import (
	"fmt"
	myfmt "mylib/fmt"
)
func main() {
	fmt.Println()
	myfmt.Println()
}

如果沒有重新命名,那麼對於編譯器來說,這兩個fmt它是區分不清楚的。重新命名也很簡單,在我們匯入的時候,在包名的左側,起一個新的包名就可以了。

Go語言規定,匯入的包必須要使用,否則會包編譯錯誤,這是一個非常好的規則,因為這樣可以避免我們引用很多無用的程式碼而導致的程式碼臃腫和程式的龐大,因為很多時候,我們都不知道哪些包是否使用,這在C和Java上會經常遇到,有時候我們不得不借助工具來查詢我們沒有使用的檔案、型別、方法和變數等,把它們清理掉。

但是有時候,我們需要匯入一個包,但是又不使用它,按照規則,這是不行的,為此Go語言給我們提供了一個空白標誌符_,只需要我們使用_重新命名我們匯入的包就可以了。

package main
import (
	_ "mylib/fmt"
)

包的init函式

每個包都可以有任意多個init函式,這些init函式都會在main函式之前執行。init函式通常用來做初始化變數、設定包或者其他需要在程式執行前的引導工作。比如上面我們講的需要使用_空標誌符來匯入一個包的目的,就是想執行這個包裡的init函式。

我們以資料庫的驅動為例,Go語言為了統一關於資料庫的訪問,使用databases/sql抽象了一層資料庫的操作,可以滿足我們操作MYSQL、Postgre等資料庫,這樣不管我們使用這些資料庫的哪個驅動,編碼操作都是一樣的,想換驅動的時候,就可以直接換掉,而不用修改具體的程式碼。

這些資料庫驅動的實現,就是具體的,可以由任何人實現的,它的原理就是定義了init函式,在程式執行之前,把實現好的驅動註冊到sql包裡,這樣我們就使用使用它操作資料庫了。


package mysql
import (
	"database/sql"
)
func init() {
	sql.Register("mysql", &MySQLDriver{})
}

因為我們只是想執行這個mysql包的init方法,並不想使用這個包,所以我們在匯入這個包的時候,需要使用_重新命名包名,避免編譯錯誤。
import "database/sql"
import _ "github.com/go-sql-driver/mysql"
db, err := sql.Open("mysql", "user:[email protected]/dbname")

看非常簡潔,剩下針對的資料庫的操作,都是使用的database/sql標準介面,如果我們想換一個mysql的驅動的話,只需要換個匯入就可以了,靈活方便,這也是面向介面程式設計的便利。





相關推薦

Go 管理工具--glide

網上有一篇解釋glide比較好的文章:https://my.oschina.net/u/553243/blog/1475626 在命令列中輸入glide $glide NAME: glide - Vendor Package Management for your Go projects.

Go管理

什麼是包?為什麼要使用包?為了更好地組織類,Java 和GO都提供了包機制,用於區別類名的名稱空間。包的作用1、把功能相似或相關的類或介面組織在同一個包中,方便類的查詢和使用。2、如同資料夾一樣,包也採用了樹形目錄的儲存方式。同一個包中的類名字是不同的,不同的包中的類的名字是

Go 管理歷史以及 Go mod 使用

之前也寫過 Go 管理依賴工具 godep 的使用,當時看 godep 使用起來還是挺方便,其原因主要在於有總比沒有強。關於依賴管理工具其實還是想從頭聊聊這個需求以及大家做這個功能的各種出發點。 #### GOPATH 和 GOROOT GOROOT 這個變數的作用就是為了告訴當前執行的 Go 程序當前

TFS:需要管理許可證才能進一步操作You need a Package Management license to go further

管理 服務器 borde com pri 級別 image pack 如果 問題:為什麽團隊成員沒有查看包管理服務的權限?如下圖:答案:TFS系統的訪問級別設置,決定在默認配置中用戶是否有包管理的訪問權限。默認配置中,只有“VS Enterprise”級別的配置,才包含包管

Go語言的管理

如果 shel private 程序 源碼 imp erp 安裝 所有 1 概述 Go 語言的源碼復用建立在包(package)基礎之上。包通過 package, import, GOPATH 操作完成。 2 main包 Go 語言的入口 main() 函數所在的包(pac

go依賴管理工具

文章目錄 go依賴包管理工具 manul 安裝 這是個實用工具的原因是什麼? 解決方案 使用 有GIF時誰需要文件? govendor

golang管理解決之道——go modules初探

golang的包管理是一直是為人詬病之處,從golang1.5引入的vendor機制,到準官方工具dep,目前為止還沒一個簡便的解決方案。 不過現在go modules隨著golang1.11的釋出而和我們見面了,這是官方提倡的新的包管理,乃至專案管理機制,可以不再需要GO

Go 語言管理機制深入分析

隨著 Go 語言的深入使用,其依賴管理機制也一直是各位 Gopher 熱衷於探討的話題。Go 語言的原始碼依賴可通過 go get 命令來獲取,但自動化程度不高,於是官方提供了 Dep 這樣的自動化批量管理依賴的工具。雖然 Go 語言的依賴管理在很多方面還是不

Go語言入門(4)dep管理

1. 什麼是dep? dep和go,在一定程度上相當於maven之於Java,composer之於PHP,dep是go語言官方的一個包管理工具。 相比較go get而言,dep可以直接給引入的第三方包

Go語言管理

轉載:https://www.cnblogs.com/sevenyuan/p/4548748.html Golang使用包(package)這種語法元素來組織原始碼,所有語法可見性均定義在package這個級別,與Java 、python等語言相比,這算不上什麼創新,但

go-module作為管理器搭建go的web伺服器

本篇部落格主要介紹瞭如何從零開始,使用Go Module作為依賴管理,基於Gin來一步一步搭建Go的Web伺服器。並使用Endless來使伺服器平滑重啟,使用Swagger來自動生成Api文件。 原始碼在此處:專案原始碼 大家可以先檢視原始碼,然後再根據本篇文章,來了解搭建過程中伺服器的一些細節。 搭建環境

[系列] 使用 go modules 管理工具(一)

目錄 概述 初始化 新增依賴包 go mod 命令 小結 原始碼地址 概述 我想實現一個開箱即用的 API 框架的輪子,這個輪子是基於 Gin 基

Python管理工具(pip)

too led -i min date pycuda nts nbsp env 1 前言 pip 是一個Python包管理工具,主要是用於安裝 PyPI 上的軟件包,可以替代 easy_install 工具。 GitHub: https://github.

BZOJ 4196: [Noi2015]軟件管理

noi make swa struct edge fine lis for nbsp 二次聯通門 : BZOJ 4196: [Noi2015]軟件包管理器 /* BZOJ 4196: [Noi2015]軟件包管理器 樹鏈剖分

#12 程序管理與rpm命令的使用

程序包管理與rpm命令的使用Linux的程序包管理:程序:指令+數據程序:算法+數據結構應用程序的存在形式:1.源代碼:包含了整個應用程序的編程語言的所有代碼的文本文件;2.二進制:將源代碼經過一系列的轉換操作之後得到的可以直接執行的文件使用源代碼安裝應用程序:預處理(預處理器) --> 編譯(編譯器)

Linux學習筆記:rpm程序管理

源代碼 rpm 程序包 以CentOS為例,rpm程序包管理器的相關內容如下:CentOS的程序包管理器: 程序包的命名規則: 源代碼包: software_name-VERSION.tar.gz VERSION:major.mino

day08 網絡設置、軟件管理

onf node 必須 解決安裝 linu 放下 字節 sta create 網絡設置 1 ifconfig //最小化安裝時不可用,需要安裝安裝包,命令為查看網卡信息 2 yum install net-tools 3 4 mtu 網卡的最大發

程序管理之----rpm

程序包管理 rpm 程序是什麽?指令+數據也好,算法+數據結構也罷。它的存在形式有兩種: 1.源代碼:包含了整個應用程序的編程語言的所有代碼的文本文件 2.二進制:將源代碼經過一系列轉換之後得到的直接執行的文件其中,使用源代碼安裝的過程如下: 預處理(用到預處理器) --> 編譯(

Python全棧_Day8_軟件管理

編譯 yum源配置 cnblogs mov 系統 .com 列表 技術分享 卸載 1.rpm rpm:用於安裝本地的rpm包。   -qa:查詢系統已安裝的所有軟件包   -ivh:安裝軟件包   -qi:查詢軟件包信息   -ql:查詢軟件包中的文件   -qf:查看某個

Python管理工具pip的基本使用

1.0 配置 .net 簡介 pac com 新的 png == 參考網址:https://pip.pypa.io/en/latest/quickstart/ 1.簡介 pip 是一個Python包管理工具,主要是用於安裝 PyPI 上的軟件包,可以替代 easy_inst