Go基础系列:构建go程序
hello world
從一個簡單的程序開始解釋,將下面的內容放進test.go文件中,路徑隨意:
package mainimport ("fmt" )func main() {fmt.Println("Hello World") }Go通過包的方式管理程序,每個Go源代碼文件都必須聲明自己所在的包,正如上面的package main聲明自己所在的包是main包。
每個程序都必須有一個main包,main包作為整個程序的編譯入口包,main包中的main()函數(shù)作為程序的執(zhí)行入口。
import關鍵字用來導入其它包,導入某個包之后就能在當前文件中使用這個包中的函數(shù),例如上面的main包導入fmt包后,可以使用fmt包中的函數(shù)Println()。
然后可以使用go的build工具編譯這個test.go文件:
$ go build test.go編譯后,將在當前路徑下生成一個可執(zhí)行二進制文件:Windows下生成的是test.exe文件,Unix下生成的是test文件。既然是可執(zhí)行文件,當然可以直接執(zhí)行:
$ ./test將輸出"Hello World"。
也可以直接通過go的run工具將編譯和運行兩個步驟合二為一:
$ go run test.go Hello Worldgo run不會生成可執(zhí)行的二進制文件,它實際上是將編譯得到的文件放進一個臨時目錄,然后執(zhí)行,執(zhí)行完后自動清理臨時目錄。
關于包和go文件
每個go代碼文件只能且必須使用package語句聲明一個包,也就是說一個文件中不能包含多個包。
Go中有兩種類型的包,或者說有兩種類型的文件:
注意:
在go的官方文檔中將go的二進制可執(zhí)行程序稱為命令,有時候還會將go的源代碼文件稱為命令的源文件。可執(zhí)行程序和包相反,包一般是作為"庫"文件存在,用于導入而非用于執(zhí)行
共享庫中包含一些函數(shù),這些函數(shù)比較通用,所以放進共享庫方便函數(shù)復用。例如fmt包中的Println函數(shù),到處都在使用這個函數(shù),且因為fmt包是標準庫(Standary library),無論是誰都可以去使用這個包。
有兩種類型的庫文件:標準庫和第三方的庫。標準庫是隨Go安裝的時候放在go安裝目錄下的($GOROOT/src/),第三方庫是放在workspace下的。關于workspace后文再說。
共享庫可以被import導入(例如fmt包)。由于導入操作是在編譯期間實現(xiàn)的,共享庫中不應該包含任何輸出型語句。
Go中對庫文件要求比較嚴格,或者說強制性的規(guī)范。它要求庫文件中package聲明的包名必須和目錄名稱相同,且同一個目錄下只允許有一個包,但同一個目錄下可以有多個庫文件片段,只不過這些庫文件中必須都使用package聲明它的包名為目錄名。例如:
src/mycode|- first.go|- second.go|- third.go如果這三個文件都是庫文件,則它們都必須且只能使用package mycode聲明自己的包為mycode。go build的時候,會將它們合并起來。如果聲明的包名不是mycode,go build會直接忽略它。
當然,對main包就無所謂了,它不是庫文件,可以放在任何地方,對目錄名沒有要求。但如果使用go install,則有額外的要求,見后文。
庫文件中的大小寫命名
Go通過名稱首字母的大小寫決定屬性是否允許導出:
- 首字母大寫的屬性是允許導出的屬性
- 首字母小寫的屬性不允許被導出
所以當庫文件被導入時,只有這個庫文件中以大寫字母開頭的常量、變量、函數(shù)等才會被導出,才可以在其他文件中使用。
例如,庫文件abc.go中:
func first() {} func Second() {}當導入這個包的時候,由于first()函數(shù)首字母小寫,外界無法使用它,它只能在自己的包abc.go中使用,對外界不可見。大寫字母開頭的Second()函數(shù)會被導入,所以可用。
工作空間(workspace)
速覽
- 通過環(huán)境變量GOPATH設置workspace的路徑
- Go編程人員一般將它們的Go代碼放在一個workspace下,當然,這不是必須的
- workspace包含一個或多個版本控制系統(tǒng)的倉庫(如git)
- 每個倉庫包含一個或多個package
- 每個package由單個目錄下的一個或多個Go源文件組成,它們都必須聲明目錄名作為它們的包名
- package的目錄路徑?jīng)Q定導入包時import的路徑
Go和其它編程語言在組織項目的時候有所不同,其它語言一般每個項目都有一個單獨的workspace,且workspace一般和版本控制倉庫進行綁定。
現(xiàn)在設置GOPATH環(huán)境變量,假設設置為/gocode
echo 'export GOPATH=/gocode' >>/etc/profile.d/gopath.sh chmod +x /etc/profile.d/gopath.sh source /etc/profile.d/gopath.shgo env GOPATH確定是否正確:
$ go env GOPATH /gocodeworkspace目錄結構
每個workspace都是一個目錄,這個目錄下至少包含三個目錄:
- src:該目錄用于存放Go源代碼文件(也稱為命令的源文件)
- bin:該目錄用于存放可執(zhí)行命令(即構建后可執(zhí)行的二進制go程序,也稱為命令文件)
- pkg:該目錄用于存放共享庫文件(即構建后非可執(zhí)行程序的庫包,也稱為包對象文件)
括號中給的名稱是go官方文檔中常見的別名稱呼。
所以,先創(chuàng)建這3個目錄
mkdir -p /gocode/{src,pkg,bin}GOPATH和GOROOT環(huán)境變量
GOPATH環(huán)境變量指定workspace的位置,用來指示go從哪里搜索go源文件/包,例如import時從哪個路徑搜索包并導入。GOROOT環(huán)境變量用于指定go的安裝位置。go需要導入包時,會從GOPATH和GOROOT所設置的位置處搜索包。
默認位置為$HOME/go(Unix)或%USERPROFILE\go%(Windows)。可以手動設置GOPATH環(huán)境變量的路徑從而指定workspace的位置,可以指定為多個目錄,多個目錄時使用冒號分隔目錄(Unix系統(tǒng))或使用分號分隔目錄(Windows系統(tǒng))。注意,絕對不能將其設置為go的安裝目錄,即不能和GOROOT環(huán)境變量重復。
例如,windows下設置d:\gocode目錄為GOPATH的路徑:
setx GOPATH d:\gocodeUnix下設置$HOME/gocode目錄為GOPATH的路徑:
mkdir ~/gocode export GOPATH=~/gocode echo 'GOPATH=~/gocode' >>~/.bashrcgo env或go env GOPATH命令可以輸出當前有效的GOPATH路徑。
$ go env | grep GOPATH GOPATH="/root/gocode"$ go env GOPATH /root/gocodego build
先寫兩個go文件,一個是可執(zhí)行go文件test.go,一個是共享庫strutils.go,將它們放在workspace的src下。
$ mkdir -p $GOPATH/src/{hello,strutils} $ tree -C . ├── bin ├── pkg ├── src │?? ├── hello │?? │?? └── test.go │?? └── strutils │?? └── strutils.go注意,上面故意將test.go放在名為hello的目錄下,可以將其放在src下的任何非庫文件目錄下(例如不能放進strutils目錄下),名稱不要求。
hello/test.go的內容如下:
package mainimport ("fmt""strutils" )func main() {fmt.Println("Hello World")fmt.Println(strutils.ToUpperCase("hello world")) }strutils/strutils.go的內容如下:
package strutilsimport ("strings" )func ToUpperCase(s string) string{return strings.ToUpper(s) }func ToLowerCase(s string) string{return strings.ToLower(s) }go build可以用于編譯,編譯時會對import導入的包進行搜索,搜索的路徑為標準庫所在路徑$GOROOT/src、workspace下的src目錄。它只會生成額外的可執(zhí)行文件放在當前目錄下,不會生成額外的庫文件。但需要注意,生成的可執(zhí)行文件名稱可能會出乎意料:
例如進入到目錄src/hello下,對test.go的文件進行編譯,以下三種build路徑都可用成功編譯:
cd src/hello go build # 生成的可執(zhí)行文件名為hello go build . # 生成的可執(zhí)行文件名為hello go build test.go # 生成的可執(zhí)行文件名為test前兩者是等價的,當go build以目錄的形式進行編譯,則生成的可執(zhí)行文件名為目錄名。當go build以go代碼文件名的方式進行編譯,則生成的可執(zhí)行程序名為go源碼文件名(去掉后綴.go或增加后綴.exe)。
go install
go還有一個工具install,go install的操作稱為安裝,將文件安裝到合適的位置。go install時會先進行編譯,然后將編譯后的二進制文件保存到workspace的bin目錄下,將編譯后的庫文件(稱為包對象文件,以".a"為后綴)放在pkg目錄下。
注意,go install時必須先進入到$GOPATH/src下,且只能對目錄進行操作,不能對具體的go文件操作,因為go認為包和目錄名相同。給go install指定一個目錄名,就表示編譯這個包名。
例如,對src/hello下的test.go進行安裝,由于它導入了strutils包,所以會自動將strutils也安裝好:
$ cd $GOPATH/src $ go install hello $ tree $GOPATH /gocode ├── bin │?? └── hello # 二進制程序文件名為hello,而非test ├── pkg │?? └── linux_amd64 │?? └── strutils.a # 庫文件 └── src├── hello│?? └── test.go└── strutils└── strutils.go還可以單獨對庫文件進行安裝:
$ rm -rf $GOPATH/bin/* $GOPATH/pkg/* $ cd $GOPATH/src $ go install strutils /gocode ├── bin ├── pkg │?? └── linux_amd64 │?? └── strutils.a └── src├── hello│?? └── test.go└── strutils└── strutils.go如果省略目錄名,則表示對當前目錄下的包進行安裝:
$ cd $GOPATH/src/hello $ go install再次提醒,go install前先進入到$GOPATH/src目錄下。
由于go install可以直接安裝二進制文件到$GOPATH/bin,所以出于方便執(zhí)行這些二進制程序,可以將這個目錄放進PATH環(huán)境變量。
$ export PATH=$PATH:`go env GOPATH`/bin構建go程序的規(guī)范建議
1.由于可以將所有go項目放在同一個$GOPATH目錄下,為了區(qū)分src下的項目目錄和庫文件目錄,建議將每個項目目錄設置深一點。
例如:
bin pkg src|- /first/project|- main.go|- myliba|- a.go|- b.go|- mylibb|- c.go|- d.go|- /second/project|- main.go|- lib|- a.go|- b.go2.go install時,先進入到項目目錄下。
3.庫文件的名稱(也是目錄名)要選取合理,盡量短,但卻盡量見名知意,也盡量減少名稱重復的幾率。
例如util這種名稱到處都是,可以修改為numutil、nameutil等。
總結
以上是生活随笔為你收集整理的Go基础系列:构建go程序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 安装php-swoole的扩展
- 下一篇: 计算机图形软件---OpenGL简介