天天看點

Golang中的數組Array和切片Slice

數組

數組(Array)是類型相同元素的集合。不允許在一個數組使用不同類型的元素(比如:不允許整數和字元串一起使用)。

  • 數組長度是不可變的
  • 數組是值類型
  • 數組之間可以用== 或 !=比較(但是長度也是類型的一部分,長度不同,是兩個不同類型,不能使用==和!=)
  1. 聲明方式
//聲明一個長度為3的整數類型。數組的所有元素都自動指派為元素類型的0值
var a [3]int
fmt.Println(a) // [0 0 0]

var b [3]bool
fmt.Println(b) // [false false false]

//數組的索引是從0開始,是以a[1]是給第二個元素指派
a[1] = 100
a[2] = 200
fmt.Println(a) // [0 100 200]

//速記聲明,在數組類型後面加一對大括号{},在大括号裡面寫元素初始值清單,多個值用逗号分隔
c := [5]int{1, 2, 3, 4, 5}
fmt.Println(c)  // [1 2 3 4 5]

//通過下标指派,預設指派第一個元素,剩下的自動指派0
d := [3]int{12}
fmt.Println(d) // [12 0 0]

// 指派第三個元素
e := [3]int{2:12}
fmt.Println(e) // [0 0 12]

//使用省略号,讓編譯器自動推到長度
f := [...]int{12, 78, 50}
fmt.Println(f) // [12 78 50]

           
  1. 數組是值類型,如果數組的變量被指派時,将會或者原來數組的copy,新數組中元素的改變不會影響原數組中元素的值
// 數組bb改變後沒有影響aa
aa := [...]string{"THIS", "IS", "TEST", "ARRAY"}
bb := aa
bb[0] = "THAT"
fmt.Println("aa is ", aa) // aa is  [THIS IS TEST ARRAY]
fmt.Println("bb is ", bb) // bb is  [THAT IS TEST ARRAY]

//切片dd改變後影響了cc
cc := []string{"THIS", "IS", "TEST", "ARRAY"}
dd := cc
dd[0] = "THAT"
fmt.Println("cc is ", cc) // cc is  [THAT IS TEST ARRAY]
fmt.Println("dd is ", dd) // dd is  [THAT IS TEST ARRAY]
           
  1. 通過len()擷取數組長度
aa := [...]string{"THIS", "IS", "TEST", "ARRAY"}
fmt.Println("aa length is ", len(aa)) // aa length is  4
           
  1. 資料周遊
aa := [...]string{"THIS", "IS", "TEST", "ARRAY"}

//使用 range周遊
for i, v := range aa {
	fmt.Printf("index= %d, value=%s\n", i, v)
}

// 使用len進行周遊
for i:=0; i< len(aa); i++ {
	fmt.Printf("index= %d, value=%s\n", i, aa[i])
}

// index= 0, value=THIS
// index= 1, value=IS
// index= 2, value=TEST
// index= 3, value=ARRAY

//如果隻想擷取數組的值,不需要數組的索引可以使用辨別符"_"
for _, v := range aa {
	fmt.Printf("value=%s\n", v)
}

//指針數組(首先是個數組,數組的元素都是指針)
var pa [4]*string
for i,v := range aa {
	fmt.Printf("index= %d, value=%s\n", i, v)
	pa[i] = &aa[i]
}
// index= 0, value=THIS
// index= 1, value=IS
// index= 2, value=TEST
// index= 3, value=ARRAY
// [0xc00005e100 0xc00005e110 0xc00005e120 0xc00005e130]

//數組指針(首先是個指針,它隻想一個數組)
var pa2 *[4]string
pa2 = &aa
fmt.Println(*pa2)
fmt.Println(pa2)
// [THIS IS TEST ARRAY]
// &[THIS IS TEST ARRAY]
           
  1. 多元數組
aaa := [3][2]string{
	{"1", "2"},
	{"11", "22"},
	{"111", "222"},
}

for _,v1 := range aaa {
	fmt.Printf("v1=%s\n", v1)
	for _,v2 := range v1 {
		fmt.Printf("v2=%s\n", v2)
	}
}

// v1=[1 2]
// v2=1
// v2=2
// v1=[11 22]
// v2=11
// v2=22
// v1=[111 222]
// v2=111
// v2=222
           

切片slice

切片不是數組,不存儲任何元素,它是對數組的引用。切片比數組更為友善、靈活。

切片類型的字面量表示:

[] T :T是元素類型,比如:

[] int

[]string

  1. 切片的建立
//使用make建立切片
s := make([]string, 3)
fmt.Println("emp", s) // emp [  ]

s[0] = "a"
s[1] = "b"
s[2] = "c"
fmt.Println("set", s) // set [a b c]
fmt.Println("set", s[2]) // set c
fmt.Println("set", len(s)) // set 3

var s2 = []int{1,2,3,4}
s3 := []int{1,2,3,4}
fmt.Println(s2)  // [1 2 3 4]
fmt.Println(s3) // [1 2 3 4]
           
  1. append添加元素
// 使用append追加元素
s = append(s, "d")
//使用len()擷取長度,cap()擷取容量
fmt.Println("length : ",len(s)) // length :  4

//如果添加過程中容量不夠,則自動擴容,容量是在原來的基礎上乘以2
fmt.Println("cap : ",cap(s)) // cap :  6 

s = append(s, "e", "f")
fmt.Println(s) //[a b c d e f]
s = append(s, "g")
fmt.Println("cap : ",cap(s)) // cap :  12 
           
  1. 修改切片
//修改切片會改變原來資料
darr := [...]int{57, 89, 90, 82, 100, 78, 67, 69, 59}
//含第三個元素,不含第6個元素
dslice := darr[2:5] 
fmt.Println("array before",darr) // array before [57 89 90 82 100 78 67 69 59]
for i := range dslice {
	dslice[i]++
}
fmt.Println("array after",darr) // array after [57 89 91 83 101 78 67 69 59]

//含第三個元素,不含第6個元素
sl := darr[2:5] 
fmt.Println(sl) // [90 82 100]

// 從開始到第5個元素(不含第6個)
sEnd := darr[:5] 
fmt.Println(sEnd) // [57 89 90 82 100]

// 從第3個到最後
sBegin := darr[2:]
fmt.Println(sBegin) // [90 82 100 78 67 69 59]


// 共享同一個底層數組時,對每一個切片的修改都會反映在底層數組中
dsilece1 := darr[:] // 從0到最後
dsilece2 := darr[:]

fmt.Println("array before change",darr) // array before change [57 89 90 82 100 78 67 69 59]
dsilece1[0] = 1
fmt.Println("array change 1",darr) // array change 1 [1 89 90 82 100 78 67 69 59]
dsilece2[1] = 2
fmt.Println("array change 2",darr) // array change 2 [1 2 90 82 100 78 67 69 59]
           
  1. 周遊和多元切片
var s2 = []int{1,2,3,4}
for _,v := range s2 {
	fmt.Println(v) // 1 2 3 4
}
slice3 := [][]string {
	{"C", "C++"},
	{"JavaScript"},
	{"Go", "Rust"},
}
for _, v1 := range slice3 {
	fmt.Printf("%s ", v1)
	for _, v2 := range v1 {
		fmt.Printf("%s ", v2)
		fmt.Printf("\n")
	}
}

// v1=[C C++]
// v2=C
// v2=C++
// v1=[JavaScript]
// v2=JavaScript
// v1=[Go Rust]
// v2=Go
// v2=Rust
           

平常使用切片比數組要多。