Go語言學習之懶人速成
在上一篇《入門篇》,已經提高了Go的安裝和使用,接下來我們一起學習一下Golang的基礎語法
為響應一起交流的朋友們的吐槽,後續文章將陸續加上目錄結構,方便大家閱讀(主要還是懶,O(∩_∩)O) orz......
- api文件
- 包 - package
- main方法
- 變數
- 常量
- iota關鍵字
- 陣列
- fmt是什麼鬼
------------------------------------------------------------------------------------
當然,可能有的朋友沒有VPN,連線不上官網,有一個本地檢視文件的方式,如下:
$> go help doc usage: go doc [-u] [-c] [package|[package.]symbol[.method]] Doc prints the documentation comments associated with the item identified by its arguments (a package, const, func, type, var, or method) followed by a one-line summary of each of the first-level items "under" that item (package-level declarations for a package, methods for a type, etc.). Flags: -c Respect case when matching symbols. -cmd Treat a command (package main) like a regular package. Otherwise package main's exported symbols are hidden when showing the package's top-level documentation. -u Show documentation for unexported as well as exported symbols and methods.
或者使用http,瀏覽器方式檢視
$> godoc -http=:8080
接下來,你就可以使用 http://localhost:8080 或 http://127.0.0.1:8080 在本地使用瀏覽器進行瀏覽api文件了。
1、什麼是包(package)?
我們在使用其它語言的情況,比如Java(本主是Java開發出身,0rz,以此為例),是有“包”這個概念的,其實,就可以簡單的理解為是便於管理和組織所有的檔案所使用的,比如java中常用的類String,它就隸屬於“java.lang”包下的類。(當然,新手不理解也沒有關係)。在Go當中,也是類似的概念,它將我們的go檔案(檔案的字尾名為“.go”)組織起來,可以方便進行歸類、複用等。
你會看到這樣的一些檔案結構,比如encoding包,下面就有base32、base64、hex、json等等,當需要使用時,則
//使用“import”關鍵字進行匯入,比如:
import "fmt"
在開篇《入門篇》中,所講到的編寫“hello world”使用了“fmt”,就使用這樣的匯入方式,當需要匯入多個包時,可以使用
import (
"fmt"
"os"
)
包的命名
go語言的包的命名,遵循簡潔、小寫、和go檔案所在目錄同名的原則,這樣就便於我們引用,書寫以及快速定位查詢。對於在企業當中開發的程式而言,我們一般採用域名作為頂級包名的方式,這樣就不用擔心和其他開發者包名重複的問題了,比如公司的域名是`www.bboyHan.com`,那麼開發的go程式都以`bboyHan.com`作為全路徑中的最頂層部分,匯入開發的工具包則可以寫為:
package main
import "bboyHan.com/utils"
------------------------------------------------------------
2、Main
我們知道,在java當中,有一個主程式的入口main()方法,而Go語言程式,也是類似。當把一個go檔案的包名宣告為main時,就等於告訴go編譯程式,這是一個可執行程式,那麼go編譯程式就會嘗試把它編譯為一個二進位制的可執行檔案。如果沒有這個函式,程式就無法執行。
//注意點:在go語言裡,同時要滿足main包和包含main()函式,才會被編譯成一個可執行檔案。
package main
import "fmt"
func main(){
fmt.Println("接下來,請在這裡搞事情。")
}
那麼,思考一個問題:Go編譯器又是如何去尋找各個檔案、包之間的依賴關係而構建程式的呢?
在上一文當中,我們提到了環境變數GOROOT和GOPATH兩個概念,這是兩個定義路徑的環境變數,GOROOT是安裝Go的路徑,比如 C:\go ;GOPATH是我們自己定義的開發者個人的工作空間,比如C:\workspace\src\bbboyHan。
編譯器會使用我們設定的這兩個路徑,再加上import匯入的相對全路徑來查詢磁碟上的包,比如我們匯入的fmt包,編譯器最終找到的是 C:\go\fmt 這個位置。對於包的查詢,是有優先順序的,編譯器會優先在GOROOT裡搜尋,其次是GOPATH,一旦找到,就會馬上停止搜尋。如果最終都沒找到,就會報編譯異常了。
------------------------------------------------------------
3、變數
Go中使用全新的關鍵字var來宣告變數。var我們並不陌生,在Javascript 和C#中均有出現。不同的是Go和C#中變數屬於強型別,在宣告變數後就不允許改變其資料型別。記住,Go屬於強資料型別
宣告及初始化
var a int //宣告一個int型別的變數
var b struct { //宣告一個結構體
i string
}
var a = 1 //宣告變數的同時賦值,編譯器自動推導其資料型別
a := 1 //這種方式,含義同上,不書寫型別,編譯時會根據value自動推導型別進行匹配
var a int = 2 //宣告變數的同時賦值
var { //批量宣告變數,簡潔
a int
b string
}
值得注意的一點,賦值時如果要確定你想要的型別,在Go中是不支援隱式轉換的。如果是定義個float64型別的變數,請寫為
//前提:需要定義一個float型別的變數時:
//正確寫法
v1 := 3.0
//錯誤寫法
v1 := 3
------------------------------------------------------------
4、常量
使用constant關鍵字進行定義,官方文件內容
const a = 2 + 3.0 // a == 5.0 (untyped floating-point constant)
const b = 15 / 4 // b == 3 (untyped integer constant)
const c = 15 / 4.0 // c == 3.75 (untyped floating-point constant)
const Θ float64 = 3/2 // Θ == 1.0 (type float64, 3/2 is integer division)
const Π float64 = 3/2. // Π == 1.5 (type float64, 3/2. is float division)
const d = 1 << 3.0 // d == 8 (untyped integer constant)
const e = 1.0 << 3 // e == 8 (untyped integer constant)
const f = int32(1) << 33 // illegal (constant 8589934592 overflows int32)
const g = float64(2) >> 1 // illegal (float64(2) is a typed floating-point constant)
const h = "foo" > "bar" // h == true (untyped boolean constant)
const j = true // j == true (untyped boolean constant)
const k = 'w' + 1 // k == 'x' (untyped rune constant)
const l = "hi" // l == "hi" (untyped string constant)
const m = string(k) // m == "x" (type string)
const Σ = 1 - 0.707i // (untyped complex constant)
const Δ = Σ + 2.0e-4 // (untyped complex constant)
const Φ = iota*1i - 1/1i // (untyped complex constant)
------------------------------------------------------------
有趣的一點,就是Go在一些情況下,會做一些調整,比如:
func main(){
a :=8
a =8.5 // 將編譯錯誤:constant 8.5 truncated to integer
fmt.Println(a)
}
func main(){
a := 3
a = 3.0 // 編譯可通過,執行無錯誤
fmt.Println(a)
}
也就是說,Go在不損失精度的情況下會把3.0這類浮點數視作整數3,如果型別顯式指定了,在表示式當中就不會產生變化。在使用的時候會根據上下文需要的型別轉化為實際型別,比如uint8(0) + 1.0就是uint8(1),但是uint8(0)+2.2就會由於2.2無法轉化為uint8而報錯。
當多個常量需要定義時,也可以使用簡易寫法:
//相同型別的情況:
const c_name1, c_name2 = value1, value2
//可以用作列舉
const (
Unknown = 0
Female = 1
Male = 2
)
-----------------------------------------------------------5、iota
iota,特殊常量,可以認為是一個可以被編譯器修改的常量。在每一個const關鍵字出現時,被重置為0,然後再下一個const出現之前,每出現一次iota,其所代表的數字會自動增加1。
const (
a = iota //a = 0
b = iota //b = 1
c = iota //c = 2
)
//可簡寫為:
const (
a = iota
b
c
)
//進階用法:
const (
i = 1<<iota //i = 1
j = 3<<iota //j = 6
k //k = 12
l //l = 24
)
-----------------------------------------------------------6、陣列
var array [5]int //宣告
array = [5]int{1,2,3,4,5} //初始化
array := [5]int{1,2,3,4,5} //宣告並初始化
array := [...]int{1,2,3,4,5} //不指定長度進行宣告及初始化
array := [5]int{1:1,3:4} //只對索引為1和3的值初始化,其餘使用預設初始化值0
因為陣列的建立在記憶體當中是一段連續的空間,所以通過索引進行直接訪問,訪問的效率非常高
func main() {
array := [5]int{1: 1, 3: 4}
for i := 0; i < 5; i++ {
fmt.Printf("索引:%d,值:%d\n", i, array[i])
}
}
-----------------------------------------------------------
看了上面的程式碼,想必會有朋友會問“fmt”還沒有講呢,下面講解一下fmt包的相關知識
7、“fmt”
fmt包實現了格式化的I/O函式,這點類似C語言中的printf和scanf,但是更加簡單,其中的格式“佔位符”衍生自 C
//常用的格式化輸出
fmt.Printf("start at number %v, end count %v\n",start, count)
佔位符
一般佔位符
符號 | 說明 |
---|---|
%v | 相應值的預設格式 |
%+v | 在列印結構體時,預設格式,會新增欄位名 |
%#v | 相應值的 Go 語法表示 |
%T | 相應值的型別的 Go 語法表示 |
%% | 字面上的百分號,並非值的佔位符 |
布林佔位符
符號 | 說明 |
---|---|
%t | 單詞 true 或 false |
整數佔位符
符號 | 說明 |
---|---|
%b | 二進位制表示 |
%c | 相應 Unicode 碼點所表示的字元 |
%d | 十進位制表示 |
%o | 八進位制表示 |
%q | 單引號圍繞的字元字面值,由 Go 語法安全地轉義 |
%x | 十六進位制表示,字母形式為小寫 a-f |
%X | 十六進位制表示,字母形式為大寫 A-F |
%U | Unicode 格式:U+1234,等同於 "U+%04X" |
浮點數及其複合構成佔位符
符號 | 說明 |
---|---|
%b | 無小數部分的,指數為二的冪的科學計數法,與 strconv.FormatFloat 的 'b' 轉換格式一致。例如 -123456p-78 |
%e | 科學計數法,例如 -1234.456e+78 |
%E | 科學計數法,例如 -1234.456E+78 |
%f | 有小數點而無指數,例如 123.456 |
%g | 根據情況選擇 %e 或 %f 以產生更緊湊的(無末尾的 0)輸出 |
%G | 根據情況選擇 %E 或 %f 以產生更緊湊的(無末尾的 0)輸出 |
字串與位元組切片佔位符
符號 | 說明 |
---|---|
%s | 字串或切片的無解譯位元組 |
%q | 雙引號圍繞的字串,由 Go 語法安全地轉義 |
%x | 十六進位制,小寫字母,每位元組兩個字元 |
%X | 十六進位制,大寫字母,每位元組兩個字元 |
指標
符號 | 說明 |
---|---|
%p | 十六進位制表示,字首 0x |
// Print 將引數列表 a 中的各個引數轉換為字串並寫入到標準輸出中。
// 非字串引數之間會新增空格,返回寫入的位元組數。
func Print(a ...interface{}) (n int, err error)
// Println 功能類似 Print,只不過最後會新增一個換行符。
// 所有引數之間會新增空格,返回寫入的位元組數。
func Println(a ...interface{}) (n int, err error)
// Printf 將引數列表 a 填寫到格式字串 format 的佔位符中。
// 填寫後的結果寫入到標準輸出中,返回寫入的位元組數。
func Printf(format string, a ...interface{}) (n int, err error)
// 功能同上面三個函式,只不過將轉換結果寫入到 w 中。
func Fprint(w io.Writer, a ...interface{}) (n int, err error)
func Fprintln(w io.Writer, a ...interface{}) (n int, err error)
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error)
// 功能同上面三個函式,只不過將轉換結果以字串形式返回。
func Sprint(a ...interface{}) string
func Sprintln(a ...interface{}) string
func Sprintf(format string, a ...interface{}) string
// 功能同 Sprintf,只不過結果字串被包裝成了 error 型別。
func Errorf(format string, a ...interface{}) error
其它關於fmt的內容未進行詳細解釋的,可以參考官方文件進行進一步研究學習有任何建議或問題,歡迎加微信一起學習交流,歡迎從事IT,熱愛IT,喜歡深挖原始碼的行業大牛加入,一起探討。
個人微訊號:bboyHan