這是Go語言學(xué)習(xí)筆記的第四篇
Go語言學(xué)習(xí)筆記參考書籍「Go語言圣經(jīng)」以及Go官方標準庫
數(shù)組
數(shù)組是指一系列同類型元素的集合。Go語言中,數(shù)組使用前必須指定長度,數(shù)組長度在定義以后就不可以更改。
//數(shù)組的聲明
var arr1 [2] int
var arr2 [10] int
var arr3 [2][3]int //二維數(shù)組
var arr4 [2]*int //指針數(shù)組
//數(shù)組賦值
arr1[0] = 0
arr1[1] = 1
//指針數(shù)組賦值
v0 := 1
v1 := 2
arr4[0] = &v0
arr4[1] = &v1
//上述賦值適應(yīng)于數(shù)組元素較少時,當數(shù)組元素較多,可以用for循環(huán)來處理
for i:=0; i<2; i++ {
for j:=0; j<3; j++ {
arr3[i][j] = i + j
}
}
//數(shù)組初始化
var arr5 = [5]float32{1.0, 2.0, 3.4, 5.6, 7.8}
arr6 := [2]int{0,1}
//[]中的數(shù)組可以忽略,編譯器會根據(jù)元素個數(shù)來設(shè)置
var arr7 = [...]string{"first name", "second name", "third name"}
可以使用內(nèi)置函數(shù)len(arry)來獲取數(shù)組長度,如果想訪問數(shù)組元素,一般使用數(shù)組下標。數(shù)組下標從0開始,len(array)-1表示最后一個元素。除此之外,還可以使用關(guān)鍵字range:
for i, v := range array {
fmt.Println("Array element[", i, "]=", v)
}
//range 具有兩個返回值,第一個返回元素的數(shù)組下標,第二個返回元素值
需要特別注意,在Go語言中數(shù)組是一個值類型。值類型就是變量在賦值或作為參數(shù)傳遞時會產(chǎn)生copy動作。因此,若函數(shù)的參數(shù)類型是數(shù)組,則函數(shù)調(diào)用時會發(fā)生數(shù)據(jù)copy,傳入函數(shù)的其實只是數(shù)組的一個副本,也就無法在函數(shù)內(nèi)部更改數(shù)組內(nèi)容。
func modifyArray(arr [5]int) {
for i:=0; i<len(arr); i++ {
arr[i] = i + 1
}
fmt.Println("In modifyArray(), array values: ", arr)
}
func main() {
arr := [5]int{1,2,3,4,5}
modifyArray(arr)
fmt.Println("In main(), array values")
}
程序執(zhí)行結(jié)果為:
In modify Array(), array values: [3 4 5 6 7]
In main(), array values: [1 2 3 4 5]
那么問題來了,如果想在函數(shù)內(nèi)部修改數(shù)組內(nèi)的數(shù)據(jù)怎么辦呢?這時候則使用數(shù)組切片。
數(shù)組切片
數(shù)組切片初看就像一個指向數(shù)組的指針,實際上它也有自己的數(shù)據(jù)結(jié)構(gòu),數(shù)組切片抽象為3個變量:
- 一個指向原生數(shù)組的指針
- 數(shù)組切片中的元素個數(shù)
- 數(shù)組切片已分配的存儲空間
基于數(shù)組,數(shù)組切片添加了一系列管理功能,可以隨時動態(tài)擴展存儲空間,并且可以被隨意傳遞而不會導(dǎo)致管理的元素被重復(fù)復(fù)制。
創(chuàng)建數(shù)組切片
創(chuàng)建數(shù)組切片有兩種方式,基于數(shù)組(數(shù)組切片)和直接創(chuàng)建(使用內(nèi)置函數(shù)make())。我們通過例子來看兩種創(chuàng)建方式:
arr := [10]int{1,2,3,4,5,6,7,8,9,10}
var slice0 [] = arr[:5]//從數(shù)組創(chuàng)建
//創(chuàng)建個數(shù)為5,初始值為0的切片
var slice1 := make([]int, 5)
//創(chuàng)建個數(shù)為5,初始值為0,并預(yù)留10個存儲空間的切片
var slice2 := make([]int, 5, 10)
//直接創(chuàng)建5個元素切片
var slice3 := []int{1,2,3,4,5}
從上面看出,Go語言使用array[first:last]方式來生成數(shù)組切片,例如下面幾種都是合法的:
//基于arr的所有元素創(chuàng)建數(shù)組切片
var mySlice = arr[:]
//基于arr的前5個元素創(chuàng)建
var mySlice = arr[:5]
//基于從第5個開始創(chuàng)建后面所有的數(shù)組切片
var mySlice = arr[5:]
//創(chuàng)建從第2個到第5個的數(shù)組切片
var mySlice = arr[2:5]
//甚至創(chuàng)建的數(shù)組切片元素可以超過原數(shù)組元素個數(shù),只要不超過原數(shù)組的存儲能力(cap()返回的值),超出部分會填0
var mySlice = slice2[2:7] //slice2數(shù)組有5個元素,儲存能力為10
動態(tài)擴展元素
數(shù)組的所有操作同樣適應(yīng)于數(shù)組切片,例如len()獲取元素個數(shù),range()快速遍歷:
數(shù)組切片還有一個重要的功能就是可動態(tài)增減元素。數(shù)組切片支持內(nèi)置的cap()函數(shù),返回數(shù)組切片分配空間的大小??磦€例子:
func main() {
mySlice := make([]int, 5, 10)
fmt.Println("len(mySlice): ", len(mySlice))
fmt.Println("cap(mySlice): ", cap(mySlice))
//往mySlice元素后追加新元素,形成新數(shù)組切片
mySlice = append(mySlice, 1,2,3)
mySlice2 := []int{8,9,10}
mySlice = append(mySlice, mySlice2...)
/* 上面這行代碼mySlice2后面的三個點如果缺少,會編譯錯誤。*/
/* 原因是append的函數(shù)定義從第二個參數(shù)起,都是可增加參數(shù)。*/
/* mySlice的元素類型是init, 直接傳遞的mySlice2是數(shù)組切片,類型錯誤。*/
/* 加上省略號即三個點相當于把mySlice2包含的所有元素打散后傳入 */
/* 相當于 mySlice = append(mySlice, 8,9,10) */
fmt.Println("mySlice: ", mySlice)
/*上面追加的元素超過了原來的10個元素容量,此時數(shù)組切片會重新自動處理存儲空間不足,自動分配一塊足夠大的內(nèi)存*/
}
內(nèi)容復(fù)制
slice1 := []int{1,2,3,4,5}
slice2 := []int{5,4,3}
copy(slice2, slice1) //只復(fù)制slice1的前三個元素
copy(slice1, slice2) //只復(fù)制slice2的3個元素到slice1的前三個位置
數(shù)組切片支持內(nèi)置函數(shù)copy(), 用于將內(nèi)容在數(shù)組切片之間復(fù)制。上面的例子表明:如果兩個數(shù)組切片不一樣大,就會按照其中較小的數(shù)組切片的元素個數(shù)進行復(fù)制。
map
map是一堆鍵值對的未排序集合。先看一個例子:
//定義一個struct
type bookInfo struct {
ID string
Name string
Price string
}
func main() {
var bookDB map[string] bookInfo
bookDB = make(map[string] bookInfo)
//插入數(shù)據(jù)
bookDB["1"] = bookInfo{"1", "Harry Potter", "$20"}
bookDB["123"] = bookInfo{"123", "Steve Jobs:A Biography","$12"}
//在map中查找
book, ok := bookDB["1234"]
if ok {
fmt.Println("find the book: ", book.Name, "the price is: ", book.Price)
} else {
fmt.Println("sorry, didn't find the book.")
}
}
上面例子涉及到了map的聲明、初始化、賦值,查找。
變量聲明
第8行聲明了一個map, 其中變量名為bookDB, map的鍵類型為string, 存放的值類型為bookInfo.
創(chuàng)建
用內(nèi)置函數(shù)make()創(chuàng)建一個map,像第9行代碼。也可以在創(chuàng)建的時候指定map的存儲能力:
bookDB = make(map[string]bookInfo, 100), 同樣也可以在創(chuàng)建map的時候初始化:
bookDB = map[string]bookInfo{"1": bookInfo{"1", "Harry Potter", "$20"}}
刪除元素
使用內(nèi)置函數(shù)delete()來刪除map中的元素。例如:delete(bookDB, "123"),如果“123”不存在,則什么都不會發(fā)生,如果存在,則會刪除key為“123”的value。
查找元素
go語言中查找map中值非常方便,代碼如下:
value, ok := bookInfo["123"]
if ok {
//找到了,處理找到的value
}
本文中的代碼均整合上傳至github, 請參考源文件