標籤:切片 ack class tps 刪除 VID 預設值 變數 cap
主要內容來自中文版的官方教程Go語言之旅
目的為總結要點
指標
Go 擁有指標。指標儲存了值的記憶體位址。
類型 *T
是指向 T
類型值的指標。其零值為 nil
。
var p *int
&
操作符會產生一個指向其運算元的指標。
i := 42p = &i
*
操作符表示指標指向的底層值。
fmt.Println(*p) // 通過指標 p 讀取 i*p = 21 // 通過指標 p 設定 i
這也就是通常所說的“間接引用”或“重新導向”。
與 C 不同,Go 沒有指標運算。
package mainimport "fmt"func main() { i, j := 42, 2701 p := &i // point to i fmt.Println(*p) // read i through the pointer fmt.Println(p) *p = 21 // set i through the pointer fmt.Println(i) // see the new value of i p = &j // point to j *p = *p / 37 // divide j through the pointer fmt.Println(j) // see the new value of j}// output// 42// 0xc420084010// 21// 73
結構體
結構體是一些變數的集合,可以用以下方式建立一個結構體。修改結構體可以採用.
符號,指向結構體的指標也可以用同樣的方法來訪問。
package mainimport "fmt"type Vertex struct { X int Y int}func main() { v := Vertex{1,2} fmt.Println(v) v.X = 4 fmt.Println(v) p := &v p.X = 8 fmt.Println(v)}//output {1 2} {4 2} {8 2}
結構體與結構體的指標都可以用以下的方法初始化
package mainimport "fmt"type Vertex struct { X, Y int}var ( v1 = Vertex{1, 2} // has type Vertex v2 = Vertex{X: 1} // Y:0 is implicit v3 = Vertex{} // X:0 and Y:0 p = &Vertex{1, 2} // has type *Vertex)func main() { fmt.Println(v1, p, v2, v3)}
數組與切片
數組的聲明也是從做到右的,以var
開頭的或者短聲明
var a [2] stringvar a [10] intprimes := [6]{2, 3, 5, 7}
切片
類型[]T
表示一個元素類型為T
的切片。切片通過兩個下標界定a[low:high]
,這種切片會選擇一個半開區間,包含第一個元素但是排除最後一個元素。切片下界的預設值是0,上界的預設值是該切片的長度。這裡注意,如果制定了長度,那麼得到的就是數組,在Go中數組是作為值傳遞的,會耗費很多的記憶體。
package mainimport "fmt"func main() { primes := [6]int{2, 3, 5, 7, 11, 13} // 這是一個數組 var s []int = primes[1:4] // 這是在聲明一個切片 fmt.Println(s) names := [4]string{ "John","Paul","George","Ringo", } // 這是一個數組 fmt.Println(names) a := names[0:2] // 這也是一個切片 b := names[1:3] // 這也是一個切片 fmt.Println(a, b) // output [John Pul] [Paul George] b[0] = "XXX" fmt.Println(a, b) // output [John XXX] [XXX George] fmt.Println(names) // output [John XXX George Ringo]}
一個切片本身是底層數組的引用,多個切片可以共用一個底層數組,在一個切片上的修改可以影響到底層數組,進而影響到所有切片
切片擁有 長度 和 容量。對於切片s
,長度是切片的長度,可以用len(s)
獲得,容量是從切片的第一個元素開始數一直到底層數組的長度,可以用cap(s)
獲得。
從底層數組的視角來看,切片中有意義的量只有三個,分別是起始位置,長度和容量。其中長度和容量是反映在切片自身重點,起始位置是用於錨定切片在底層數組中的位置。一旦切片建立,那麼底層數組在起始位置之前的部分就會被扔掉。
在做切片的時候,其實s[low: high]
中的low
就選擇了在當前的底層數組中的起始位置,high
選擇了終止位置,進而定義了長度high-low
。在簡曆切片之後,底層數組精簡原底層數組中low
到末尾的部分。
nil
切片是切片長度和容量都為零,且沒有底層數組的切片,例如它可以這樣聲明var s []int
。其實在這個意義上,數組自身就是長度和容量相等的切片。
切片可以包含任何類型,甚至其他的切片(多維陣列)
board := [][]string{ []string{"_", "_", "_"}, []string{"_", "_", "_"}, []string{"_", "_", "_"},}
用
range
遍曆切片
package mainimport "fmt"var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}func main() { for i, v := range pow { fmt.Printf("2**%d = %d\n", i, v) } for _, value := range pow { fmt.Printf("%d\n", value) } for value, _ := range pow { fmt.Printf("%d\n", value) }}
映射
映射將key映射到value。用make
函數可以建立給定類型的映射,並將其初始化備用。
映射的零值為nil
,需要注意的是nil
既沒有鍵,也不能添加鍵
package mainimport "fmt"type Vertex struct { Lat, Long float64}var m map[string]Vertexfunc main() { m = make(map[string]Vertex) m["Bell Labs"] = Vertex{ 40.68433, -74.39967, } fmt.Println(m["Bell Labs"])}
映射的文法和結構體類似,但是一定要有鍵名
package mainimport "fmt"type Vertex struct { Lat, Long float64}var m = map[string]Vertex{ "Bell Labs": Vertex{ 40.68433, -74.39967, }, "Google": Vertex{ 37.42202, -122.08408, },}func main() { fmt.Println(m)}
映射可以用下標訪問或修改元素
用delete
函數刪除元素
用雙賦值可以檢測某個鍵的是否存在
package mainimport "fmt"func main() { m := make(map[string]int) m["Answer"] = 42 fmt.Println("The value:", m["Answer"]) m["Answer"] = 48 fmt.Println("The value:", m["Answer"]) delete(m, "Answer") fmt.Println("The value:", m["Answer"]) v, ok := m["Answer"] fmt.Println("The value:", v, "Present?", ok) // ok 是是否存在的boolean值}
函數值
函數本身也可以作為值,稱為函數值,可以作為函數的參數或者傳回值
package mainimport ( "fmt" "math")func compute(fn func(float64, float64) float64) float64 { return fn(3, 4)}func main() { hypot := func(x, y float64) float64 { return math.Sqrt(x*x + y*y) } fmt.Println(hypot(5, 12)) fmt.Println(compute(hypot)) fmt.Println(compute(math.Pow))}
Go函數可以使一個閉包。閉包是一個函數值,它引用了函數體之內的變數。該函數可以訪問並賦予其引用的變數的值。例如下面的例子中adder
函數傳回值為一個閉包。每個閉包都被綁定在各自的sum
變數上。
package mainimport "fmt"func adder() func(int) int { sum := 0 //這是閉包的函數體之外的變數,它也被綁定在閉包內了 return func(x int) int { //這是閉包 sum += x return sum }}func main() { pos, neg := adder(), adder() for i := 0; i < 10; i++ { fmt.Println( pos(i), neg(-2*i), ) }}
make函數
用make函數建立切片(動態數組),有兩種用法
a := make([]int, 5) // 長度為5,容量預設為5b := make([]int, 0, 5) // 長度為0, 容量為5
func make([]T, len, cap) []T
用make
函數可以建立給定類型的映射,並將其初始化備用
Go 入門 - Go中的複雜類型