一 簡(jiǎn)介
Go語(yǔ)言出自Ken Thompson、Rob Pike和Robert Griesemer之手,起源于2007年,并在2009年正式對(duì)外發(fā)布,其實(shí)都是Google的,設(shè)計(jì)Go語(yǔ)言的初衷都是為了滿(mǎn)足Google的需求。Go的主要目標(biāo)是“兼具Python等動(dòng)態(tài)語(yǔ)言的開(kāi)發(fā)速度和C/C++等編譯型語(yǔ)言的性能與安全性”,旨在不損失應(yīng)用程序性能的情況下降低代碼的復(fù)雜性,具有“部署簡(jiǎn)單、并發(fā)性好、語(yǔ)言設(shè)計(jì)良好、執(zhí)行性能好”等優(yōu)勢(shì)。最主要還是為了并發(fā)而生,并發(fā)是基于goroutine的,goroutine類(lèi)似于線程,但并非線程,可以將goroutine理解為一種虛擬線程。Go語(yǔ)言運(yùn)行時(shí)會(huì)參與調(diào)度goroutine,并將goroutine合理地分配到每個(gè)CPU中,最大限度地使用CPU性能。
二 環(huán)境
我們玩Java的時(shí)候需要下載JDK,類(lèi)似于此,用Go開(kāi)發(fā)也需要下載Go,里面提供各種develop-kit、library以及編譯器。在官網(wǎng)下載mac版本pkg后直接安裝,最后用 go version 命令驗(yàn)證版本:
然后就是設(shè)置這兩個(gè)環(huán)境變量,mac系統(tǒng)是在 .bash_profile 文件里面:
export GOROOT=/usr/local/go
export GOPATH=$HOME/go
GOROOT:表示的是Go語(yǔ)言編譯、工具、標(biāo)準(zhǔn)庫(kù)等的安裝路徑,其實(shí)就相當(dāng)于配置JAVA_HOME那樣。
GOPATH:這個(gè)和Java有點(diǎn)不一樣,Java里并不需要設(shè)置這個(gè)變量,這個(gè)表示Go的工作目錄,是全局的,當(dāng)執(zhí)行Go命令的時(shí)候會(huì)依賴(lài)這個(gè)目錄,相當(dāng)于一個(gè)全局的workspace。一般還會(huì)把$GOPATH/bin設(shè)置到PATH目錄,這樣編譯過(guò)的代碼就可以直接執(zhí)行了。
1 純文本開(kāi)發(fā)
編寫(xiě)代碼,可以保存在任意地方,例如新建一個(gè)helloworld目錄,創(chuàng)建hello.go文件:
package main
import "fmt"
func main() {
fmt.Println("hello, world")
}
然后執(zhí)行 go build hello.go 就可以編譯出hello文件,在./hello就可以執(zhí)行了;或者直接 go run hello.go 合二為一去執(zhí)行。執(zhí)行這個(gè)命令并不需要設(shè)置環(huán)境變量就可以了。看起來(lái)和c差不多,但是和Java不一樣,運(yùn)行的時(shí)候不需要虛擬機(jī)。早期的GO工程也是使用Makefile來(lái)編譯,后來(lái)有了強(qiáng)大的命令 go build、go run,可以直接識(shí)別目錄還是文件。
2 GoLand
自動(dòng)import,超爽的體驗(yàn)!不用按command + /了!
運(yùn)行項(xiàng)目需要設(shè)置build config,和Android、Java的都差不多,例如創(chuàng)建一個(gè)hello-goland項(xiàng)目:
導(dǎo)入go module項(xiàng)目的時(shí)候需要勾選這項(xiàng),否則無(wú)法像maven/gradle那樣sync下載依賴(lài):
3 VSCODE
直接搜索Go插件,第一個(gè)最多安裝量的就是了,我還沒(méi)用過(guò)所以不太清楚如何。
三 工程結(jié)構(gòu)
在設(shè)置GOPATH環(huán)境變量的時(shí)候,這個(gè)目錄里面又分了三個(gè)子目錄bin、pkg、src,分別用于存放可執(zhí)行文件、包文件和源碼文件。當(dāng)我們執(zhí)行Go命令的時(shí)候,如果我們指定的不是當(dāng)前目錄的文件或者絕對(duì)路徑的目錄的話,就會(huì)去GOPATH目錄的去找。這樣在GOPATH目錄創(chuàng)建了xxx的目錄后,就可以在任意地方執(zhí)行 go build xx 命令來(lái)構(gòu)建或者運(yùn)行了。
pkg目錄應(yīng)該是在執(zhí)行 go install 后生成的包文件,包括.a這樣的文件,相當(dāng)于一個(gè)歸檔。
├── bin
│ ├── air
│ ├── govendor
│ ├── swag
│ └── wire
├── pkg
│ ├── darwin_amd64
│ ├── mod
│ └── sumdb
└── src
├── calc
├── gin-blog
├── github.com
├── golang.org
├── google.golang.org
├── gopkg.in
└── simplemath
這樣對(duì)于我們具體項(xiàng)目來(lái)說(shuō)并不好,沒(méi)有Workspace的概念來(lái)隔離每個(gè)項(xiàng)目了,所以我覺(jué)得這個(gè)GOPATH目錄放的應(yīng)該是公用的項(xiàng)目,例如開(kāi)源依賴(lài)的。我們?cè)陂_(kāi)發(fā)過(guò)程中,也會(huì)下載很多的依賴(lài),這些依賴(lài)都下載到這個(gè)目錄,和我們的項(xiàng)目文件混在一起了。
另外,通過(guò)IDE可以設(shè)置project的GOPATH,相當(dāng)于在執(zhí)行的時(shí)候給GOPATH增加了一個(gè)目錄變量,也就是說(shuō),我們創(chuàng)建一個(gè)項(xiàng)目,然后里面也有bin、src、pkg這三個(gè)目錄,和GOPATH一樣的,本質(zhì)上,IDE在運(yùn)行的時(shí)候其實(shí)就是設(shè)置了一下GOPATH:
GOPATH=/Users/fuxing/develop/testgo/calc-outside:/Users/fuxing/develop/go #gosetup
Go語(yǔ)言在尋找變量、函數(shù)、類(lèi)屬性及方法的時(shí)候,會(huì)先查看GOPATH這個(gè)系統(tǒng)環(huán)境變量,然后根據(jù)該變量配置的路徑列表依次去對(duì)應(yīng)路徑下的src目錄下根據(jù)包名查找對(duì)應(yīng)的目錄,如果對(duì)應(yīng)目錄存在,則再到該目錄下查找對(duì)應(yīng)的變量、函數(shù)、類(lèi)屬性和方法。
其實(shí)官方提供了Go Modules的方法更好解決。
1 Go Modules
從Go 1.11版本開(kāi)始,官方提供了Go Modules管理項(xiàng)目和依賴(lài),從1.13版本開(kāi)始,更是默認(rèn)開(kāi)啟了對(duì)Go Modules的支持,使用Go Modules的好處是顯而易見(jiàn)的 —— 不需要再依賴(lài)GOPATH,你可以在任何位置創(chuàng)建Go項(xiàng)目,并且在國(guó)內(nèi),可以通過(guò) GOPROXY 配置鏡像源加速依賴(lài)包的下載。也就是說(shuō),創(chuàng)建一個(gè)項(xiàng)目就是一個(gè)mod,基本上目前Go開(kāi)源項(xiàng)目都是這樣做的。其實(shí)就是類(lèi)似于Maven和Gradle。
// 創(chuàng)建mod項(xiàng)目,也是可以用IDE來(lái)new一個(gè)mod項(xiàng)目的:
go mod init calc-mod
// 一般開(kāi)源在github上面的項(xiàng)目名字是這樣的;和maven、gradle不一樣的是,開(kāi)發(fā)完成根本不需要發(fā)布到倉(cāng)庫(kù)!只要提交代碼后打tag就可以了
go mod init github.com/fuxing-repo/fuxing-module-name
// 創(chuàng)建一個(gè)模塊:執(zhí)行這個(gè)命令主要是多了一個(gè)go.mod文件,里面就一行內(nèi)容:
module calc-mod
// import以后,執(zhí)行下載依賴(lài)命令,不需要編輯go.mod文件。依賴(lài)會(huì)下載到GOPATH/pkg/mod目錄
go list
用GoLand來(lái)打開(kāi)不同的項(xiàng)目,顯示依賴(lài)的外部庫(kù)是不一樣的,如果是用GOPATH創(chuàng)建的項(xiàng)目,需要用命令下載依賴(lài)包到GOPATH:
go get -u github.com/fuxing-repo/fuxing-module-name
四 語(yǔ)法
1 包:Package 和 Import
Java里面的包名一般是很長(zhǎng)的,和文件夾名稱(chēng)對(duì)應(yīng),作用就是命名空間,引入的時(shí)候需要寫(xiě)長(zhǎng)長(zhǎng)的一串,也可以用通配符:
Go里面一般的包名是當(dāng)前的文件夾名稱(chēng),同一個(gè)項(xiàng)目里面,可以存在同樣的包名,如果同時(shí)都需要引用同樣包名的時(shí)候,就可以用alias區(qū)分,類(lèi)似于JS那樣。一般import的是一個(gè)包,不像Java那樣import具體的類(lèi)。同一個(gè)包內(nèi),不同文件,但是里面的東西是可以使用的,不需要import。這有點(diǎn)類(lèi)似于C的include吧。如果多行的話,用括號(hào)換行包起來(lái)。
Go語(yǔ)言中,無(wú)論是變量、函數(shù)還是類(lèi)屬性及方法,它們的可見(jiàn)性都是與包相關(guān)聯(lián)的,而不是類(lèi)似Java那樣,類(lèi)屬性和方法的可見(jiàn)性封裝在對(duì)應(yīng)的類(lèi)中,然后通過(guò) private、protected 和 public 這些關(guān)鍵字來(lái)描述其可見(jiàn)性,Go語(yǔ)言沒(méi)有這些關(guān)鍵字,和變量和函數(shù)一樣,對(duì)應(yīng)Go語(yǔ)言的自定義類(lèi)來(lái)說(shuō),屬性和方法的可見(jiàn)性根據(jù)其首字母大小寫(xiě)來(lái)決定,如果屬性名或方法名首字母大寫(xiě),則可以在其他包中直接訪問(wèn)這些屬性和方法,否則只能在包內(nèi)訪問(wèn),所以Go語(yǔ)言中的可見(jiàn)性都是包一級(jí)的,而不是類(lèi)一級(jí)的。
在Java里面,只有靜態(tài),或者對(duì)象就可以使用點(diǎn)運(yùn)算符,而且是極其常用的操作,而在Go里面,還可以用一個(gè)包名來(lái)點(diǎn),這就是結(jié)合了import來(lái)使用,可以點(diǎn)出一個(gè)函數(shù)調(diào)用,也可以點(diǎn)出一個(gè)結(jié)構(gòu)體,一個(gè)接口。另外區(qū)別于C,不管是指針地址,還是對(duì)象引用,都是用點(diǎn)運(yùn)算符,不需要考慮用點(diǎn)還是箭頭了!