指針
在Go語言中也存在指針绪杏,且指針保存了變量的地址,初始值為nil纽绍。定義指針與定義變量相似蕾久,不同的是在類型前面指針需要加*例如:
var p *int //此處定義了一個int類型的指針
指針也可以通過已有變量獲取,通過&操作符便可拌夏,與C語言相似Go中*指針名指向變量底層僧著,但是不同的是Go中沒有指針運算履因。示例代碼如下:
package main
import "fmt"
func main(){
i,j := 10,1000
var p *int //定義一個int指針
p = &i //從i變量中獲取指向i的指針并賦值給p
fmt.Println(i)
*p = 21 //修改p指針指向的底層存儲的數(shù)據(jù)
fmt.Println(i)
p = &j
*p = *p/10
fmt.Println(j)
}
結(jié)構(gòu)體
結(jié)構(gòu)體就是一些字段的集合,通過type來聲明定義類型盹愚,并用struct來聲明結(jié)構(gòu)體栅迄。具體實現(xiàn)如下:
package main
import "fmt"
type TestType struct{
x int
y int
}
func main(){
p := TestType{1,2}
fmt.Println(p)
p.x = 4
fmt.Println(p)
}
從上述示例代碼中可以看出結(jié)構(gòu)體的字段通過點號來訪問。
結(jié)構(gòu)體還可以通過指針來訪問皆怕,若一個結(jié)構(gòu)體指針為p那么我們可以通過(&p).x來調(diào)用結(jié)構(gòu)體的字段或者使用隱式間接引用毅舆,直接寫p.x就可以。結(jié)構(gòu)體文法可以通過直接列出字段的值來新分配一個結(jié)構(gòu)體愈腾,也可以通過Name:
語法列出部分字段憋活。
數(shù)組
類型[n]T表示擁有n個T類型的值得數(shù)組。數(shù)組的長度是數(shù)組的一部分虱黄,所以數(shù)組不能改變大小悦即。
為了解決這個限制,Go推出了切片這一類型橱乱,切片為數(shù)組元素提了供動態(tài)大小辜梳,靈活的視角,比數(shù)組更實用泳叠。切片通過[]T
來定義作瞄。切片不存儲任何數(shù)據(jù),它只是描述了底層數(shù)組中的一段析二,或者我們也可以理解為切片其實相當(dāng)于對數(shù)據(jù)中的一段的每一個元素都獲取了一個指針對象存放到另一數(shù)組中粉洼。創(chuàng)建數(shù)組與切片的方法如下:
package main
import "fmt"
func main(){
//創(chuàng)建一個數(shù)組并設(shè)置初始值Go自動推導(dǎo)類型
myArray := [10]int{1,2,3,4,5,6,7,8,9,10}
fmt.Println(myArray)
//創(chuàng)建一個數(shù)組設(shè)置初始值
var myArray1 [5]int = [5]int{6,5,4,3,2}
fmt.Println(myArray1)
//創(chuàng)建一個切片初始元素個數(shù)為5,默認(rèn)值為0叶摄,預(yù)留10個存儲空間
mySlice := make([]int,5,10)
fmt.Println(mySlice)
//從數(shù)組上直接創(chuàng)建一個切片属韧,初始元素個數(shù)與數(shù)組相同
mySlice2 := []int{1,2,3,4,5}
fmt.Println(mySlice2)
//穿件一個切片元素個數(shù)為6默認(rèn)值為0
mySlice3 := make([]int,6)
fmt.Println(mySlice3)
}
通過make方式來創(chuàng)建的切片也是創(chuàng)建動態(tài)數(shù)組的方法。
在進(jìn)行切片時蛤吓,可以利用它的默認(rèn)行為來忽略上下界宵喂,切片的下界默認(rèn)為0,上界為該切片的長度会傲。例如:
package main
import "fmt"
func main(){
var a [10]int = {1,2,3,4,5,6,7,8,9,10}
fmt.Println(a[0:10])
fmt.Println(a[:10])
fmt.Println(a[:10])
fmt.Println(a[:])
}
以上四個切片是等價的
切片擁有容量與長度兩個屬性锅棕,長度就是包含的元素個數(shù),容量就是從第一個元素開始到底層數(shù)組元素的末尾的個數(shù)淌山,長度與容量分別用len(s)和cap(s)來獲取裸燎。切片的零值為nil,nil切片的容量與長度為0泼疑,且沒有底層數(shù)組德绿。
切片可以包含任何類型,包括切片。
切片可以通過append來追加元素移稳,該函數(shù)為自建函數(shù)蕴纳,使用方式如下:
package main
import "fmt"
func main(){
var s []int
printSlice(s)
//輸出len=0 cap=0 []
//追加一個元素
s = append(s,0)
printSlice(s)
//輸出len=0 cap=0 []
//追加多個元素
s = append(s,2,3,4,5)
printSlice(s)
//輸出len=1 cap=1 [0]
}
func printSlice(s []int) {
fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}
上述代碼展示了append的兩種使用方式,添加一個元素與添加多個元素
映射(map)
映射就是將鍵映射到值个粱,映射的零值為nil古毛,nil既沒有鍵也不能添加鍵,make函數(shù)會返回給定類型的映射都许,并將其初始化備用稻薇。映射的文法與結(jié)構(gòu)體相似,但是映射必須要有鍵名梭稚。若頂級類型只有一種類型颖低,那么可以在文法元素中忽略。
package main
import "fmt"
type Vertex struct {
Lat, Long float64
}
var m = map[string]Vertex{
"Bell Labs": {40.68433, -74.39967},
"Google": {37.42202, -122.08408},
}
func main() {
fmt.Println(m)
//輸出map[Bell Labs:{40.68433 -74.39967} Google:{37.42202 -122.08408}]
//修改Bell Labs對應(yīng)的元素
m["Bell Labs"] = Vertex{2000,-74.39967}
fmt.Println(m)
//輸出map[Bell Labs:{2000 -74.39967} Google:{37.42202 -122.08408}]
//刪除Bell Labs對應(yīng)的元素
delete(m,"Bell Labs")
fmt.Println(m)
//輸出map[Google:{37.42202 -122.08408}]
//通過雙賦值來判斷鍵是否存在
v, ok := m["Google"]
fmt.Println("The value:", v, "Google?", ok)
//輸出The value: {37.42202 -122.08408} Google? true
}
range
for循環(huán)的range形式可以遍歷切片也可以遍歷映射弧烤,for循環(huán)遍歷切片時,每次遍歷都會返回兩個值蹬敲,一個是元素的下標(biāo)一個是元素的副本暇昂,通過_可以將下標(biāo)或者值忽略,當(dāng)只需要下標(biāo)時可以直接去掉,value部分伴嗡。
package main
import (
"golang.org/x/tour/wc"
"strings"
)
func WordCount(s string) map[string]int {
res := make(map[string]int)
strs := strings.Fields(s)
for _,v:= range strs{
res[v]++
}
return res
}
func main() {
wc.Test(WordCount)
}
函數(shù)值與閉包
Go中函數(shù)也是值急波,也可以作為參數(shù)或者返回值。Go函數(shù)可以是一個閉包瘪校。閉包是一個函數(shù)值澄暮,它引用了其函數(shù)體之外的變量。該函數(shù)可以訪問并賦予其引用的變量的值阱扬,換句話說泣懊,該函數(shù)被“綁定”在了這些變量上。
package main
import "fmt"
func main() {
var j int = 5
//此處創(chuàng)建了一個匿名函數(shù)麻惶,返回值為函數(shù)值馍刮,并通過匿名函數(shù)后跟()來執(zhí)行這個匿名函數(shù)將返回的函數(shù)值賦值給a變量
a := func()(func()){
var i int = 10
return func(){
fmt.Printf("i,j: %d , %d\n",i,j)
}
}()
a()
j *= 2
a()
}