001 go語言入門-安裝-go基礎命令-基礎資料型別
《Go併發程式設計實戰》和線上免費教程《Go命令教程》的作者郝林
專案原始碼:
《Go 併發程式設計實戰》的示例專案。
一、go的優劣勢
二、go的安裝
http://golang.org/dl/ 下載最新的二進位制檔案包
(結合作業系統型別和位數--32 64)
linux下安裝:
解壓後 在 bin 目錄下 執行 ./go version 檢視安裝包版本
將 解壓檔案移動到 /usr/local 下即可。--方便統一管理
linux下環境變數配置:
export GOROOT=/usr/local/go
#go安裝的目錄
export GOPATh=~/golib:~/goproject
#go語言的工作區的集合
export GOBIN=~/gobin
#存放go程式的可執行檔案的目錄
export PATH=$PATH:$GOROOT/bin:$GOBIN
#path 中加入go語言命令 和go的可執行檔案目錄
export GOROOT=/usr/local/go export GOPATh=~/golib:~/goproject export GOBIN=~/gobin export PATH=$PATH:$GOROOT/bin:$GOBIN |
驗證配置結果:
go version
#檢視go 版本資訊
三、常用概念
3.1工作區和GOPATH
工作區是放置go原始碼檔案的目錄。
一般情況下,go原始碼檔案都需要存放在工作區中。
但是對於【命令原始碼檔案】來說,這不是必須的。
3.1.1工作區目錄
/home/hypermind/golib
src/
用於存放原始碼檔案
以程式碼包為組織形式
pkg/
用於存放歸檔檔案(名稱以.a為字尾的檔案)
所有歸檔檔案都會被存放到該目錄下的平臺相關目錄 中,同樣以程式碼包為組織形式。
bin/
用於存放當前工作區中的go程式的可執行檔案
兩種情況下 bin目錄會無效:
1、當環境變數GOBIN已經有效設定時,該目錄會無意義
2、當GOPATH的值中包含多個工作區的路徑時,必須設定GOBIN,否則無法成功安裝GO程式的可執行檔案
3.1.2 平臺相關目錄
兩個隱含的go語言環境變數:GOOS和GOARCH
GOOS:計算機作業系統
GOARCH:計算架構
以 $GOOS_$GOARCH 為命名方式,如:linux_amd64
3.2原始碼檔案的分類和含義
3.2.1 GO原始碼檔案
名稱以.go 為字尾,內容以Go 語言程式碼組織的檔案
多個Go 原始碼檔案是需要用程式碼包組織起來的。
3.2.2 原始碼檔案的分類和含義
分三類:
命令原始碼檔案、庫原始碼檔案、測試原始碼檔案
命令原始碼檔案:
宣告自己屬於main程式碼包、包含無引數宣告和結果宣告的main函式
被安裝後,相應的可執行檔案會被存放到 GOBIN 指向的目錄或<當前工作區目錄> /bin 下
命令原始碼檔案是Go程式的入口,但不建議把程式都寫在一個檔案中。
注意:同一個程式碼包中強烈不建議直接包含多個命令原始碼檔案。
庫原始碼檔案:
不具備命令原始碼檔案特徵的檔案。
測試原始碼檔案:
1、不具備命令原始碼檔案的那兩個特徵的檔案
2、名稱以 _test.go 為字尾
3、其中至少有一個函式的名稱以Test 或 Benchmark 為字首
並且,該函式接受一個 型別 為 *testing.T 或 *testing.B 的引數 ——指標型別
示例: func TestFind(t *testing.T){ //程式碼 } 基準測試函式、效能測試函式 |
3.3程式碼包相關知識
3.3.1 程式碼包的作用
編譯和歸檔Go程式的最基本單位
程式碼劃分、集結和依賴的有效組織形式,也是許可權控制的輔助手段
3.3.2 程式碼包的規則
一個程式碼包實際上就是一個由匯入路徑代表的目錄
匯入路徑即<工作區 目錄> /src 或 <工作區目錄> /pkg/<平臺相關目錄>之下的某子路徑
3.3.3 程式碼包的宣告
每個原始碼檔案必須宣告其所屬的程式碼包
同一個程式碼包中的所有原始碼檔案宣告的程式碼包應該是相同的。
3.3.4 程式碼包的匯入和宣告的區別
3.3.4.1 程式碼包宣告:
當前程式碼檔案的目錄名稱
package pkgtool
#
3.3.4.2 程式碼包的匯入:
1、 import ("包1","包2")
2、帶別名的匯入
iimport str "Strings"
3、本地化匯入
import . "strings" ——》Hasprefx("abc","a")
不需要再用包名稱去呼叫。
4、僅僅初始化
import _ 'strings" ==》僅執行程式碼包中的初始化函式,而不呼叫任何實體
3.3.5 程式碼包的初始化
1、程式碼包的初始化函式即: 無引數宣告和結果宣告的init 函式
init函式可以被宣告在任何檔案中,且可以有多個。
2、init函式的正時機——單元程式碼包內
對所有全域性變數進行求職——》執行所有init函式。
注意: 一次匯入多個包,所有被匯入程式碼包的init 函式 沒有先後執行順序。不能假設誰先被執行。
依賴匯入時,最先被依賴的包 最先執行。
A——》匯入B——》匯入C A匯入B,B匯入了C 在執行init的時候, Cinit最先被執行,接著是Binit 最後是 C init
每個init 函式只會 被執行一次。
四、go命令
4.1 go run
用於執行命令原始碼檔案(只能接受一個命令原始碼檔案以及若干個庫原始碼檔案作為檔案引數)
4.1.2 ds 命令 和 pds 命令
4.1.3 命令案例演示
在 goc2p/src/helper/ds/showds.go 目錄下 執行 : go run showds.go #會列印當前目錄樹。
4.1.3 go run 常用標記的使用
-a: 強制編譯先關程式碼,無論程式碼是否已經是最新編譯。
-n: 列印編譯過程中所需執行的命令,單是不真正執行他們
-pn:並行編譯,其中n為並行的數量。
n 為邏輯CPU的數量
-v :列出被編譯的程式碼包的名稱。
-a -v :列出所有被編譯的程式碼包的名稱。
-work: 顯示編譯時建立的臨時工作目錄的路徑,並且不刪除它。(預設的 go run 編譯會刪除臨時目錄)
-x:列印編譯過程中所需執行的命令
-n:列印編譯過程中所需的命令,但並不執行。
-x : 列印編譯過程中所需的命令,並執行他們。
4.2 go build 和 go install
4.2.1 go build 簡介
用於編譯原始碼檔案或程式碼包。
編譯非命令原始碼檔案不會產生任何結果檔案。
編譯命令原始碼檔案會在該命令的執行目錄中生成一個可執行檔案。
go build 不加引數時,會試圖把當前目錄作為程式碼包並編譯:
go build 以程式碼包的匯入路徑為引數時,程式碼包以及其依賴會被編譯。
-a 標記: 所有涉及到的程式碼包都會被重新編譯。
不加入-a標記,則只會編譯歸檔檔案不是最新的程式碼包。
go build 以若干原始碼檔案為引數,只有這些檔案會被編譯。————列出的原始碼檔案不全,這樣容易報錯。
4.2.2 go install
用於編譯並安裝程式碼包或原始碼檔案
安裝程式碼包會在當前工作區的pkg/<平臺相關目錄>下生成歸檔檔案
安裝命令原始碼檔案會在當前工作區的bn目錄或$GOBIN目錄下生成可執行檔案。
go install 不加引數時,會試圖把當前目錄作為程式碼包並安裝。
go install 程式碼包的匯入路徑為引數,會把匯入路徑的程式碼包以及其依賴的程式碼包 會被安裝————就可以在其他程式碼中匯入此程式碼包了
go install 以命令原始碼檔案及相關庫原始碼檔案作為引數,只有這些檔案會被編譯並安裝
4.3 go get
用於從遠端程式碼倉庫(如 github)上下載並安裝程式碼包。 (gitLlab Gogs)
受支援的程式碼版本控制系統有: git 、 Mercurial(hg) 、 SVN、Bazaar
指定的程式碼包會被下載到 $GOPATH 中包含的第一個工作區的src 目錄中。
4.3.1 go get 案例
go get -x github.com/go-errors/errors
# -x 選項 可以看到 go get的 詳細執行情況。 go get 呼叫的是 git clone 命令
echo $GOPATH 可以檢視工作區目錄情況。 會被下載到第一個工作區目錄的 src 目錄下。
4.3.2 go get 常用標記的使用(1)
-x: 顯示 go get 進度
-d: 只執行下載動作,而不執行安裝動作。
-fix: 在下載程式碼包後先執行修正動作,而後再進行編譯和安裝
-u:利用網路來更新已有的程式碼包及其依賴包
4.3.3 go get 標記案例
五、基本資料型別
5.1 go語言-程式實體和關鍵字
任何Go語言原始碼檔案都由若干個程式實體組成的。在Go語言中,變數、常量、函式、結構體和介面被統稱為“程式實體”,而它們的名字被統稱為“識別符號”。
識別符號可以是任何Unicode編碼可以表示的字母字元、數字以及下劃線“_”。不過,首字母不能是數字或下劃線。
注意:在Go語言中,我們對程式實體的訪問許可權控制只能通過它們的名字來實現。
名字首字母為大寫的程式實體可以被任何程式碼包中的程式碼訪問到。而名字首字母為小寫的程式實體則只能被同一個程式碼包中的程式碼所訪問。
go 關鍵字:
package main // 程式碼包宣告語句。 // 程式碼包匯入語句。 import ( "fmt" // 匯入程式碼包fmt。 ) // main函式。 func main() { // 列印函式呼叫語句。用於列印輸出資訊。 fmt.Println("Go語言程式設計實戰") } |
5.2 Go語言-變數和常量
var 變數名 型別 = 值
const 常量名 型別 = 值
可以宣告和賦值分開 。
var num2, num3 int = 2, 3 // 註釋:平行賦值
var ( // 註釋:多行賦值 num4 int = 4 num5 int = 5 )
注意:在實踐中發現,常量可以不用大寫, 變數可以不用顯式的宣告資料型別。但是一般按照標準的語法來。 並且如果宣告變數而未使用會編譯錯誤。
// 變數宣告和賦值語句,由關鍵字var、變數名num、變數型別uint64、特殊標記=,以及值10組成。 var num uint64 = 65535 |
// 短變數宣告語句,由變數名size、特殊標記:=,以及值(需要你來填寫)組成。 size := (64) |
5.3 go 整數型別的命名和寬度
Go語言-整數型別的命名和寬度 Go語言的整數型別一共有10個。 其中計算架構相關的整數型別有兩個,即:有符號的整數型別int和無符號的整數型別uint。 順便提一下,有符號的整數型別會使用最高位的位元(bit)表示整數的正負。顯然,這會對它能表示的整數的範圍有一定的損耗(使其縮小)。而無符號的整數型別會使用所有的位元位來表示數值。如此型別的值均為正數。這也是用“無符號的”來形容它們的原因。 言歸正傳,為什麼說這兩個整數型別是計算架構相關的呢?這是因為,在不同的計算架構的計算機之上,它們體現的寬度是不同的。寬度即指儲存一個某型別的值所需要的空間。空間的單位可以是位元,也可以是位元組(byte)。請看下錶。 我想你應該已經能夠悟到它們的對應關係了。 除了這兩個計算架構相關的整數型別之外,還有8個可以顯式表達自身寬度的整數型別。如下表所示。 可以看到,這8個整數型別的寬度已經表現在它們的名稱中了 |
5.4 Go語言型別-整數型別值的表示法
Go語言-整數型別值的表示法
我們已經知道了每個整數型別的寬度,那麼它們的寬度意味著什麼呢?下面這張表已有所描述。
如上所示,型別int8的數值表示範圍為[-128,127],而型別uint16的數值表示範圍為[0,65535],等等。
以我們的常識知道,在數學中整數一般是以10進位制來表示的,而在計算機中整數則必是以2進位制來表示和儲存的。當然,在電腦科學領域,整數的表示形式還包括了8進位制和16進位制。下面我們就來說說怎樣這幾種表示法在Go語言中表示整數。
最顯而易見的是10進製表示法。如果我們要在宣告一個名為num1的int型別變數時給它賦予12這個值,那麼這樣書寫即可:
var num1 int = 12
這是最容易被我們理解的方式了。不過,如果我們要分別以8進位制和16進製為變數num1賦值,那麼需要:
num1 = 014 // 用“0”作為字首以表明這是8進製表示法。
或:
num1 = 0xC // 用“0x”作為字首以表明這是16進製表示法。
(注意,為已宣告的變數賦值,無需再在等號左邊加入關鍵字var和變數型別)
5.5 Go語言-浮點數型別
浮點數型別有兩個,即float32和float64。你可能已經想到,儲存這兩個型別的值的空間分別需要4個位元組和8個位元組。
浮點數型別的值一般由整數部分、小數點“.”和小數部分組成。其中,整數部分和小數部分均由10進製表示法表示。不過還有另一種表示方法。那就是在其中加入指數部分。指數部分由“E”或“e”以及一個帶正負號的10進位制陣列成。比如,3.7E-2表示浮點數0.037。又比如,3.7E+1表示浮點數37。
有時候,浮點數型別值的表示也可以被簡化。比如,37.0可以被簡化為37。又比如,0.037可以被簡化為.037。
有一點需要注意,在Go語言裡,浮點數的相關部分只能由10進製表示法表示,而不能由8進製表示法
5.6 Go語言-複數型別
複數型別同樣有兩個,即complex64和complex128。儲存這兩個型別的值的空間分別需要8個位元組和16個位元組。實際上,complex64型別的值會由兩個float32型別的值分別表示複數的實數部分和虛數部分。而complex128型別的值會由兩個float64型別的值分別表示複數的實數部分和虛數部分。
複數型別的值一般由浮點數表示的實數部分、加號“+”、浮點數表示的虛數部分,以及小寫字母“i”組成。比如,3.7E+1 + 5.98E-2i。正因為複數型別的值由兩個浮點數型別值組成,所以其表示法的規則自然需遵從浮點數型別的值表示法的相關規則。我們就不在這裡贅述了。請你通過練習題來回顧一下相關表示法的規則。
5.7 byte與rune
byte與rune型別有一個共性,即:它們都屬於別名型別。byte是uint8的別名型別,而rune則是int32的別名型別。
byte型別的值需用8個位元位表示,其表示法與uint8型別無異。因此我們就不再這裡贅述了。我們下面重點說說rune型別。
一個rune型別的值即可表示一個Unicode字元。Unicode是一個可以表示世界範圍內的絕大部分字元的編碼規範。關於它的詳細資訊,大家可以參看其官網(http://unicode.org/)上的文件,或在Google上搜索。用於代表Unicode字元的編碼值也被稱為Unicode程式碼點。一個Unicode程式碼點通常由“U+”和一個以十六進位制表示法表示的整數表示。例如,英文字母“A”的Unicode程式碼點為“U+0041”。
rune型別的值需要由單引號“'”包裹。例如,'A'或'郝'。這種表示方法一目瞭然。不過,我們還可以用另外幾種形式表示rune型別值。請看下錶。
大家需要根據實際情況選用上述表示法。在一般情況下,第一種表示法更為通用。因為它是最直觀的。不過,在以其他幾種方法表示的內容出現在螢幕上的時候,大家也要明白其含義。
另外,在rune型別值的表示中支援幾種特殊的字元序列,即:轉義符。它們由“\”和一個單個英文字元組成。如下表所示。
5.8 Go語言-字串型別
顧名思義,一個字串型別的值可以代表一個字元序列。這些字元必須是被Unicode編碼規範支援的。雖然從表象上來說是字元序列,但是在底層,一個字串值卻是由若干個位元組來表現和儲存的。一個字串(也可以說字元序列)會被Go語言用Unicode編碼規範中的UTF-8編碼格式編碼為位元組陣列。
注意,我們在一個字串值或者一個字串型別的變數之上應用Go語言的內建函式len將會得到代表它的那個位元組陣列的長度。這可能與我們看到的表象是不同的。
字串的表示法有兩種,即:原生表示法和解釋型表示法。若用原生表示法,需用反引號“`”把字元序列包裹起來。若用解釋型表示法,則需用雙引號“"”包裹字元序列。
二者的區別是,前者表示的值是所見即所得的(除了回車符)。在那對反引號之間的內容就是該字串值本身。而後者所表示的值中的轉義符會起作用並在程式編譯期間被轉義。所以,如此表示的字串值的實際值可能會與我們看到的表象不相同。
最後要注意,字串值是不可變的。也就是說,我們一旦建立了一個此型別的值,就不可能再對它本身做任何修改。
兩種宣告:
1、反引號 ··
在那對反引號之間的內容就是該字串值本身。 所見即所得
2、雙引號
所表示的值中的轉義符會起作用並在程式編譯期間被轉義。 可以保函轉移符號,被轉義