概述
連續(xù)三節(jié)的內(nèi)容如下:
- 第一節(jié)覆蓋了基本語法及數(shù)據(jù)結(jié)構(gòu)
- 第二節(jié)討論了方法與接口
- 第三節(jié)則簡單介紹了 Go 的并發(fā)原語。
導(dǎo)入包 import
大寫開頭,導(dǎo)出
如果一個名字以大寫字母開頭,那么它就是已導(dǎo)出的。例如,Pizza 就是個已導(dǎo)出名,Pi 也同樣,它導(dǎo)出自 math 包。
import 分組
import "fmt"
import "math"
不過使用分組導(dǎo)入語句是更好的形式。
import (
"fmt"
"math"
)
函數(shù)參數(shù)縮寫
func add(x int, y int) int {
return x + y
}
可縮寫為
func add(x, y int) int {
return x + y
}
有意義的返回值
Go 的返回值可被命名,它們會被視作定義在函數(shù)頂部的變量。
var 語句用于聲明一個變量
var c, python, java bool
短變量聲明
在函數(shù)中,簡潔賦值語句 := 可在類型明確的地方代替 var 聲明。:= 結(jié)構(gòu)不能在函數(shù)外使用。
Go 的基本類型有
bool
string
int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
byte // uint8 的別名
rune // int32 的別名
// 表示一個 Unicode 碼點
float32 float64
complex64 complex128
類型轉(zhuǎn)換
表達式 T(v) 將值 v 轉(zhuǎn)換為類型 T。
i := 42
f := float64(i)
u := uint(f)
var i int = 42
var f float64 = float64(i)
類型推導(dǎo)
在聲明一個變量而不指定其類型時(即使用不帶類型的 := 語法或 var = 表達式語法),變量的類型由右值推導(dǎo)得出。
常量
常量的聲明與變量類似,只不過是使用 const 關(guān)鍵字。
for 是 Go 中的 “while”
func main() {
sum := 1
for sum < 1000 {
sum += sum
}
fmt.Println(sum)
}
defer
defer 語句會將函數(shù)推遲到外層函數(shù)返回之后執(zhí)行。
推遲調(diào)用的函數(shù)其參數(shù)會立即求值,但直到外層函數(shù)返回前該函數(shù)都不會被調(diào)用。
推遲的函數(shù)調(diào)用會被壓入一個棧中。當(dāng)外層函數(shù)返回時,被推遲的函數(shù)會按照后進先出的順序調(diào)用。
Go 擁有指針。指針保存了值的內(nèi)存地址。
類型 *T 是指向 T 類型值的指針。其零值為 nil。
var p *int
& 操作符會生成一個指向其操作數(shù)的指針。
i := 42
p = &i
結(jié)構(gòu)體
一個結(jié)構(gòu)體(struct)就是一組字段(field)
數(shù)組
數(shù)組的長度是其類型的一部分,因此數(shù)組不能改變大小
var a [10]int
切片
類型 []T 表示一個元素類型為 T 的切片。
切片通過兩個下標(biāo)來界定,即一個上界和一個下界,二者以冒號分隔:
a[low : high]
a[1:4] 它包含 a 中下標(biāo)從 1 到 3 的元素:
切片就像數(shù)組的引用
切片并不存儲任何數(shù)據(jù),它只是描述了底層數(shù)組中的一段。
更改切片的元素會修改其底層數(shù)組中對應(yīng)的元素。
切片文法類似于沒有長度的數(shù)組文法。
這是一個數(shù)組文法:
[3]bool{true, true, false}
切片下界的默認值為 0,上界則是該切片的長度。
以下切片是等價的:
a[0:10]
a[:10]
a[0:]
a[:]
切片的長度與容量
切片擁有 長度 和 容量。
切片的長度就是它所包含的元素個數(shù)。
切片的容量是從它的第一個元素開始數(shù),到其底層數(shù)組元素末尾的個數(shù)。
切片 s 的長度和容量可通過表達式 len(s) 和 cap(s) 來獲取。
nil 切片的零值是 nil
用 make 創(chuàng)建切片,創(chuàng)建動態(tài)數(shù)組的方式。
make 函數(shù)會分配一個元素為零值的數(shù)組并返回一個引用了它的切片:
a := make([]int, 5) // len(a)=5
切片的切片,即是二維數(shù)組
board := [][]string{
[]string{"_", "_", "_"},
[]string{"_", "_", "_"},
[]string{"_", "_", "_"},
}
Range
for 循環(huán)的 range 形式可遍歷切片或映射。
當(dāng)使用 for 循環(huán)遍歷切片時,每次迭代都會返回兩個值。第一個值為當(dāng)前元素的下標(biāo),第二個值為該下標(biāo)所對應(yīng)元素的一份副本。
for i, v := range pow {
fmt.Printf("2**%d = %d\n", i, v)
}
可以將下標(biāo)或值賦予 _ 來忽略它。
for i, _ := range pow
for _, value := range pow
若你只需要索引,忽略第二個變量即可。
for i := range pow
映射 ( map )
其實就是 map 鍵值對的數(shù)據(jù)結(jié)構(gòu)實現(xiàn)
映射將鍵映射到值。
映射的零值為 nil 。nil 映射既沒有鍵,也不能添加鍵。
make 函數(shù)會返回給定類型的映射,并將其初始化備用
var m map[string]Vertex
m = make(map[string]Vertex)
m["Bell Labs"] = xxxxxxx
映射的文法
映射的文法與結(jié)構(gòu)體相似,不過必須有鍵名。
var m = map[string]Vertex{
"Bell Labs": Vertex{
40.68433, -74.39967,
},
"Google": Vertex{
37.42202, -122.08408,
},
}
若頂級類型只是一個類型名,你可以在文法的元素中省略它。
var m = map[string]Vertex{
"Bell Labs": {40.68433, -74.39967},
"Google": {37.42202, -122.08408},
}
修改映射
在映射 m 中插入或修改元素:
m[key] = elem
獲取元素:
elem = m[key]
刪除元素:
delete(m, key)
通過雙賦值檢測某個鍵是否存在:
elem, ok = m[key]
若 key 在 m 中,ok 為 true ;否則,ok 為 false。
若 key 不在映射中,那么 elem 是該映射元素類型的零值。
函數(shù)值
函數(shù)也是值。它們可以像其它值一樣傳遞。
函數(shù)值可以用作函數(shù)的參數(shù)或返回值。
PS: 其實就是函數(shù)可以當(dāng)參數(shù)傳遞
函數(shù)的閉包
Go 函數(shù)可以是一個閉包。閉包是一個函數(shù)值,它引用了其函數(shù)體之外的變量。該函數(shù)可以訪問并賦予其引用的變量的值,換句話說,該函數(shù)被這些變量“綁定”在一起。
func adder() func(int) int {
sum := 0
return func(x int) int {
sum += x
return sum
}
}
函數(shù)的命名返回值
命名返回參數(shù)
可以像python那樣返回多個結(jié)果,只是非tuple
對于不想要的返回值,可以扔垃圾桶_
如果用命名返回參數(shù),return語句可以為空。return 不為空,返回值順序是return的順序而非在函數(shù)頭聲明的順序
package main
func change(a, b int) (x, y int) {
x = a + 100
y = b + 100
return //101, 102
//return x, y //同上
//return y, x //102, 101
}
# 更多學(xué)習(xí)資料
[http://docscn.studygolang.com/doc/](http://docscn.studygolang.com/doc/)
https://go-zh.org/#
https://tour.go-zh.org/list
END