GO語言學習(三):指標,切片,map對映
阿新 • • 發佈:2018-12-18
1.指標
func main() { var a int = 10 //每個變數有2層含義,變數的記憶體,變數的地址 fmt.Printf("a =%d\n", a) fmt.Printf("&a =%v\n", &a) //儲存某個變數的地址,需要指標型別, //*int儲存int的地址,**int儲存*int的地址 var p *int //宣告(定義),定義只是特殊的宣告 p = &a //指標變數指向誰,就把誰的地址賦值給指標變數 fmt.Printf("p =%v, &a =%v\n", p, &a) *p =666 //*p操作的不是記憶體,是p所指向的記憶體(就是a) fmt.Printf("p =%v, a =%v\n", *p, a) //666 666 }
go語言雖然保留指標,但與其它程式語言不同的是
1)預設值是nil,沒有NULL常量
2)操作符"&“是取變數地址,”*“通過指標訪問目標物件
3)不支援指標運算,不支援 “->” 運算子,直接用”."訪問目標成員
go語言指標定義
func main() {
var p *int
p = new(int) //new一個新空間,go語言不需要釋放
q := new(int)
}
指標交換a,b值
func swap(a, b *int){ *a, *b = *b, *a fmt.Printf("swap: a = %d, b =%d\n", a, b) } func main() { a, b := 10, 20 //通過一個函式交換a和b的內容 swap(&a, &b) //變數本身傳遞,值傳遞(站在變數角度) fmt.Printf("main: a = %d, b =%d\n", a, b) }
一維陣列賦值
func main() { //宣告定義同時賦值,叫初始化 //1.全部初始化 var a [5]int = [5]int{1, 2, 3, 4, 5} fmt.Println("a =", a) b := [5]int{1,2,3,4,5} fmt.Println("b =", b) //部分初始化,沒有初始化的元素自動賦值為0 c := [5]int{1,2,3} fmt.Println("c =", c) //指定某個元素初始化 d := [5]int{2:10, 4:10} fmt.Println("d =", d) }
二維陣列賦值
func main() {
//二維陣列初始化,可部分初始化,沒有初始化的值為0
e := [3][4]int{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 20, 32, 53}}
fmt.Println(e)
//部分初始化,只對第二行元素賦值
f := [3][4]int{1: {5, 6, 7, 8}}
fmt.Println(f)
}
兩陣列間支援比較和賦值,只支援 == 或 !=,比較是不是每個元素都一樣,兩個陣列比較,陣列型別要一樣。
2.隨機數生成與氣泡排序
func main() {
//設定種子,只需一次
//如果種子引數一樣,每次允許程式產生的隨機數都一樣
//解決辦法,用時間
rand.Seed(time.Now().UnixNano()) //以當前系統時間作為種子引數
var a [10]int
n := len(a)
for i:=0; i < n; i++{
//產生隨機數
//fmt.Println("rand = ", rand.Int()) //隨機很大的數
a[i]= rand.Intn(100)
fmt.Printf("%d, ", a[i]) //Intn函式,限定隨機數生成的範圍
}
fmt.Printf("\n")
//氣泡排序,挨著的2個元素比較,升序(大於交換)
for i :=0; i<n-1; i++{
for j :=0;j<n-1-i;j++{
if a[j]>a[j+1]{
a[j], a[j+1] = a[j+1], a[j]
}
}
}
fmt.Println("有序後:")
for i:=0; i < n; i++{
fmt.Printf("%d, ", a[i]) //Intn函式,限定隨機數生成的範圍
}
}
陣列做函式引數,它是值傳遞。實引數組的每個元素給行引數組拷貝一份。如果需要用函式改變陣列的值,用指標。
//陣列做函式引數,它是值傳遞
//實引數組的每個元素給行引數組拷貝一份
func modify(p *[5]int) {
(*p)[0] = 666
fmt.Println("*a = ", *p)
}
func main() {
a :=[5]int{1,2,3,4,5}
modify(&a)
fmt.Println(a)
}
2.切片
func main() {
array := [...]int {10, 20, 30, 0, 0}
s := array[0:3:5]
//[low:high:max]
//low下標的起點
//high下標的終點(不包括此下標),左閉右開
//len=high-low
//cap = max - low 容量
fmt.Println("s = ", s)
fmt.Println("len(s) = ", len(s)) //長度=3-0
fmt.Println("cap(s) = ", cap(s)) //容量=5-0
//切片與陣列的區別
//陣列[]裡面的長度是固定的一個常量,陣列不能修改長度,len和cap永遠固定
a := [5]int{}
fmt.Printf("len = %d, cap = %d\n", len(a), cap(a))
//切片,[]裡面為空,或者為...切片的長度或容量可以不固定
s := []int{}
fmt.Printf("len = %d, cap = %d\n", len(s), cap(s))
s = append(s, 11) //給切片末尾增加一個成員
}
切片的建立
//自動推導型別,同時初始化
s1 := []int{1, 2, 3, 4}
fmt.Println("s1 =", s1)
//藉助make函式,格式make(切片型別, 長度, 容量)
s2 := make([]int, 5, 10)
fmt.Printf("len = %d, cap = %d\n", len(s2), cap(s2))
//容量可預設,預設時容量等於長度
切片操作
array := []int{0,1,2,3,4,5,6,7,8,9}
s1 := array[:] //[0:len(array):len(array)],不指定時容量和長度一樣
fmt.Println(s1)
fmt.Printf("len = %d, cap = %d\n", len(s1), cap(s1))
//操作某個元素,和陣列操作方式一樣
data := array[0]
fmt.Println(data)
s2 := array[3:6:7]
fmt.Printf("len = %d, cap = %d\n", len(s2), cap(s2))
s3 := array[:6] //從0開始,取6個元素,容量為10
fmt.Printf("len = %d, cap = %d\n", len(s3), cap(s3))
s4 := array[3:] //從下標為3開始到結尾
fmt.Println(s4) //取7個元素,容量為7
fmt.Printf("len = %d, cap = %d\n", len(s4), cap(s4))
切片與底層陣列的關係
array := []int{0,1,2,3,4,5,6,7,8,9}
//新切片修改後原陣列也發生改變
s1 := array[2:5]
s1[1] = 666
fmt.Println(s1)
fmt.Println(array)
fmt.Printf("len = %d, cap = %d\n", len(s1), cap(s1))
//另外新切片,切片的切片
s2 := s1[2:7]
s2[2] = 777
fmt.Println(s2)
fmt.Println(array)
使用append函式,如果超過原來的容量,通常以2倍容量擴容
func test(m map[int]string){
delete(m,2)
}
func main() {
var ml map[int]string
fmt.Println("ml =", ml)
//隊友map只有len,沒有cap
fmt.Println("len =",len(ml))
//可以通過make建立
m2 := make(map[int]string)
fmt.Println("ml =", m2)
fmt.Println("len =", len(m2))
//可通過make建立指定長度,只是指定了容量,長度由map內資料決定
m3 := make(map[int]string,10)
m3[1] = "mike"
m3[20] = "c++"
m3[50] = "go"
fmt.Println("ml =", m3)
fmt.Println("len =", len(m3))
//初始化,且鍵值唯一
m4 := map[int]string{1: "mike", 2: "go", 3: "c++"}
fmt.Println("m4 =", m4)
//遍歷
for key, value := range m4 {
fmt.Printf("%d ====> %s\n", key, value)
}
//如何判斷一個key是否存在
//第一個返回值為key所對應的value,第二個返回值為key是否存在的條件,存在ok為true
value, ok := m4[1]
if ok == true{
fmt.Println("m[1] =",value)
}else{
fmt.Printf("key不存在\n")
}
//刪除某個值
delete(m4, 1) //刪除key為1的內容
fmt.Println(m4)
//將刪除操作寫在函式內部
test(m4) //在函式內部刪除某個key
fmt.Println("m4 = ", m4)
}
2.定義結構體
//結構體型別
//有時我們需要將不同資料型別的數組合成一個有機的整體
//定義一個結構體型別
type Student struct{
id int
name string
sex byte
age int
addr string
}
func main() {
//順序初始化,每個成員必須初始化
var s1 Student = Student{1,"mike", 'm', 18, "bj"}
fmt.Println("s1 =", s1)
//指定成員初始化,沒有初始化
s2 := Student{name: "mike", addr: "bj"}
fmt.Println("s2 =", s2)
//初始化指標變數
var s3 *Student = &Student{1,"mike", 'm', 18, "bj"}
fmt.Println("s3 =", *s3)
s4 := &Student{name: "mike", addr: "bj"}
fmt.Println("s4 =", *s4)
}
結構體指標變數
//1.指標有合法指向後,才操作成員
//先定義一個普通結構體變數
var s Student
//再定義一個指標變數,儲存s的地址
var p1 *Student
p1 = &s
//通過指標操作成員,p1.id和(*p).id完全等價,只能用.運算子
p1.id = 1
p1.name = "mike"
p1.sex = 'm'
p1.age = 18
p1.addr = "bj"
fmt.Println("p1 = ",p1)
//2.通過new申請一個結構體
p2 :=new(Student)
p2.id = 1
(*p2).name = "mike"
p2.sex = 'm'
p2.age = 18
p2.addr = "bj"
fmt.Println("p2 = ",p2)
如果想使用別的包的函式,結構體型別,結構體成員
函式名,型別名,結構體成員變數名,首字母必須大寫,可見
如果首字母是小寫,只能在同一個包裡使用