数组
数组:是同一种数据类型的固定长度的序列
数组定义:var a [len]int,比如:var a[5]int,一旦定义,长度不能变
长度是数组类型的一部分,因此,var a[5] int和var a[10]int是不同的类型
数组可以通过下标进行访问,下标是从0开始,最后一个元素下标是:len-1
访问越界,如果下标在数组合法范围之外,则触发访问越界,会panic
数组是值类型,因此改变副本的值,不会改变本身的值
package@H_301_14@ main
import@H_301_14@(
"fmt"@H_301_14@
)
func@H_301_14@ main() {
//为数组索引赋值@H_301_14@
var@H_301_14@ a [5@H_301_14@]int@H_301_14@
a[0@H_301_14@] = 10@H_301_14@
fmt.Println(a)
//遍历数组2种方法@H_301_14@
for@H_301_14@ i:=0@H_301_14@;i<len@H_301_14@(a);i++{
fmt.Println(a[i])
}
for@H_301_14@ i,v := range@H_301_14@ a{
fmt.Println(i,v)
}
//值传递@H_301_14@
test()
var@H_301_14@ aa [5@H_301_14@]int@H_301_14@
//通过方法参数值传递@H_301_14@
test1(aa)
fmt.Println(aa)
//传递地址值@H_301_14@
test2(&aa)
fmt.Println(aa)
//数组初始化5种方式@H_301_14@
var@H_301_14@ arr1 [5@H_301_14@]int@H_301_14@ = [5@H_301_14@]int@H_301_14@{1@H_301_14@,2@H_301_14@,3@H_301_14@,4@H_301_14@,5@H_301_14@}
fmt.Println(arr1)
var@H_301_14@ arr2 = [5@H_301_14@]int@H_301_14@{1@H_301_14@,5@H_301_14@}
fmt.Println(arr2)
var@H_301_14@ arr3 = [...]int@H_301_14@{1@H_301_14@,5@H_301_14@,6@H_301_14@}
fmt.Println(arr3)
var@H_301_14@ arr4 = [...]int@H_301_14@{1@H_301_14@:1@H_301_14@,2@H_301_14@:2@H_301_14@}
fmt.Println(arr4)
var@H_301_14@ arr5 = [5@H_301_14@]int@H_301_14@{1@H_301_14@:2@H_301_14@,3@H_301_14@:4@H_301_14@}
fmt.Println(arr5)
}
func@H_301_14@ test(){
var@H_301_14@ a [5@H_301_14@]int@H_301_14@
b := a
b[0@H_301_14@] = 100@H_301_14@
fmt.Println(a)
}
func@H_301_14@ test1(arr [5@H_301_14@]int@H_301_14@){
arr[0@H_301_14@] = 100@H_301_14@
}
func@H_301_14@ test2(arr *[5@H_301_14@]int@H_301_14@){
(*arr)[0@H_301_14@] = 100@H_301_14@
}
输出如下:
[10@H_301_14@ 0@H_301_14@ 0@H_301_14@ 0@H_301_14@ 0@H_301_14@]
10@H_301_14@
0@H_301_14@
0@H_301_14@
0@H_301_14@
0@H_301_14@
0@H_301_14@ 10@H_301_14@
1@H_301_14@ 0@H_301_14@
2@H_301_14@ 0@H_301_14@
3@H_301_14@ 0@H_301_14@
4@H_301_14@ 0@H_301_14@
[0@H_301_14@ 0@H_301_14@ 0@H_301_14@ 0@H_301_14@ 0@H_301_14@]
[0@H_301_14@ 0@H_301_14@ 0@H_301_14@ 0@H_301_14@ 0@H_301_14@]
[100@H_301_14@ 0@H_301_14@ 0@H_301_14@ 0@H_301_14@ 0@H_301_14@]
[1@H_301_14@ 2@H_301_14@ 3@H_301_14@ 4@H_301_14@ 5@H_301_14@]
[1@H_301_14@ 2@H_301_14@ 3@H_301_14@ 4@H_301_14@ 5@H_301_14@]
[1@H_301_14@ 2@H_301_14@ 4@H_301_14@ 5@H_301_14@ 6@H_301_14@]
[0@H_301_14@ 1@H_301_14@ 2@H_301_14@]
[0@H_301_14@ 2@H_301_14@ 0@H_301_14@ 4@H_301_14@ 0@H_301_14@]
切片
切片:切片是数组的一个引用,因此切片是引用类型
切片的长度可以改变,因此,切片是一个可变的数组
切片遍历方式和数组一样,可以用len()求长度
cap可以求出slice最大的容量,0 <= len(slice) <= (array),其中array是slice引用的数组
切片的定义:var 变量名 []类型,比如 var str []string var arr []int
package@H_301_14@ main
import@H_301_14@(
"fmt"@H_301_14@
)
func@H_301_14@ main() {
var@H_301_14@ slice []int@H_301_14@
var@H_301_14@ arr [5@H_301_14@]int@H_301_14@ = [5@H_301_14@]int@H_301_14@{1@H_301_14@,5@H_301_14@}
slice = arr[2@H_301_14@:5@H_301_14@]
fmt.Println(slice)
//长度@H_301_14@
fmt.Println(len@H_301_14@(slice))
//最大容量@H_301_14@
fmt.Println(cap@H_301_14@(slice))
slice = slice[0@H_301_14@:1@H_301_14@]
fmt.Println(len@H_301_14@(slice))
fmt.Println(cap@H_301_14@(slice))
//切片的其他声明方法@H_301_14@
var@H_301_14@ slice1 []int@H_301_14@ = arr[:]
fmt.Println(slice1)
var@H_301_14@ slice2 []int@H_301_14@ = arr[0@H_301_14@:3@H_301_14@]
fmt.Println(slice2)
var@H_301_14@ slice3 []int@H_301_14@ = []int@H_301_14@{1@H_301_14@,4@H_301_14@}
fmt.Println(slice3)
}
输出如下:
2017@H_301_14@/10/24 13:46:43 debugger.go:499: continuing [3 4 5]@H_301_14@
3@H_301_14@
3@H_301_14@
1@H_301_14@
3@H_301_14@ [1 2 3 4 5]@H_301_14@ [1 2 3]@H_301_14@ [1 2 4]@H_301_14@
切片内存如何变化的?
package@H_301_14@ main
import@H_301_14@(
"fmt"@H_301_14@
)
func@H_301_14@ main() {
var@H_301_14@ a [5@H_301_14@]int@H_301_14@ = [...]int@H_301_14@{1@H_301_14@,5@H_301_14@}
//切片@H_301_14@
s:= a[1@H_301_14@:]
s[1@H_301_14@] = 100@H_301_14@
//内存地址一样,修改了s的索引值,也就修改了a的索引值@H_301_14@
fmt.Printf("%p %p\n"@H_301_14@,s,&a[1@H_301_14@])
fmt.Println("before a:"@H_301_14@,a)
fmt.Println(s)
s = append@H_301_14@(s,10@H_301_14@)
s = append@H_301_14@(s,10@H_301_14@)
s[1@H_301_14@] = 1000@H_301_14@
fmt.Println("after a:"@H_301_14@,a)
fmt.Println(s)
//容量改变,重新分配内存 @H_301_14@
fmt.Printf("%p %p\n"@H_301_14@,&a[1@H_301_14@])
}
输出如下:
0xc04204c1e8@H_301_14@ 0xc04204c1e8@H_301_14@
before@H_301_14@ a@H_301_14@: [1 2 100 4 5]@H_301_14@
[2 100 4 5]@H_301_14@
after@H_301_14@ a@H_301_14@: [1 2 100 4 5]@H_301_14@
[2 1000 4 5 10 10 10 10 10]@H_301_14@
0xc042014200@H_301_14@ 0xc04204c1e8@H_301_14@
PS@H_301_14@ E@H_301_14@:\golang@H_301_14@\go_pro@H_301_14@\src@H_301_14@\safly@H_301_14@>
简单解释下:
创建一个数组a,初始值为{1,2,3,4,5},然后构造一个从索引1开始的数组切片,{2,3,4,5},这里的切片、数组都是同一块内存地址,然后将s[1]赋值为100,由于内存地址是一样的,所以a为{1,2,100,4,5}
s为[2,100,4,5]
接下来为s切片扩充容量,然后修改了s[1] = 1000,最后s为2 1000 4 5 10 10 10 10 10,a依然是[1 2 100 4 5]
,由于底层算法,扩容后,内存地址a和s的就不同了,s从新创建了一个内存地址0xc042014200
切片的底层代码实现
package@H_301_14@ main
import@H_301_14@(
"fmt"@H_301_14@
)
/*切片底层形式*/@H_301_14@
type@H_301_14@ slice struct@H_301_14@{
ptr *[5@H_301_14@]int@H_301_14@
len@H_301_14@ int@H_301_14@
cap@H_301_14@ int@H_301_14@
}
/*构造一个slice*/@H_301_14@
func@H_301_14@ makeSlice(s slice,cap@H_301_14@ int@H_301_14@) slice{
s.ptr = new@H_301_14@([5@H_301_14@]int@H_301_14@)
s.cap@H_301_14@ = cap@H_301_14@
s.len@H_301_14@ = 0@H_301_14@
return@H_301_14@ s
}
func@H_301_14@ testSlice(){
//slice类型@H_301_14@
var@H_301_14@ a slice
a = makeSlice(a,5@H_301_14@)
a.ptr[0@H_301_14@] = 100@H_301_14@
fmt.Println(a.ptr)
}
func@H_301_14@ main() {
testSlice()
}
输出如下:
&[100 0 0 0 0]@H_301_14@
修改切片值、演示切片内存地址
package@H_301_14@ main
import@H_301_14@(
"fmt"@H_301_14@
)
/*切片会被修改*/@H_301_14@
func@H_301_14@ modify(b []int@H_301_14@){
b[1@H_301_14@] = 200@H_301_14@
}
func@H_301_14@ modify1(b *[]int@H_301_14@){
(*b)[1@H_301_14@] = 2000@H_301_14@
}
func@H_301_14@ main() {
var@H_301_14@ b []int@H_301_14@ = []int@H_301_14@{1@H_301_14@,3@H_301_14@}
fmt.Println(b)
//修改切片方法1--直接穿切片@H_301_14@
modify(b)
fmt.Println(b)
//修改切片方法2--传地址值@H_301_14@
modify1(&b)
fmt.Println(b)
//数组不会被修改,参数为数组@H_301_14@
var@H_301_14@ d [3@H_301_14@]int@H_301_14@ = [...]int@H_301_14@{3@H_301_14@,5@H_301_14@}
modify3(d)
fmt.Println(d)
/*演示切片的内存布局*/@H_301_14@
testSlice5()
}
func@H_301_14@ modify3(b [3@H_301_14@]int@H_301_14@){
b[1@H_301_14@] = 200@H_301_14@
}
/*演示切片的内存布局*/@H_301_14@
func@H_301_14@ testSlice5(){
fmt.Println("----------------"@H_301_14@)
var@H_301_14@ a = [10@H_301_14@]int@H_301_14@{1@H_301_14@,4@H_301_14@}
b :=a[1@H_301_14@:5@H_301_14@]
fmt.Printf("%p\n"@H_301_14@,b)
fmt.Printf("%p\n"@H_301_14@,&a[1@H_301_14@])
fmt.Println(a,b)
}
输出如下:
[1 2 3]@H_301_14@
[1 200 3]@H_301_14@
[1 2000 3]@H_301_14@
[3 4 5]@H_301_14@
----------------@H_301_14@
0xc0420101e8@H_301_14@
0xc0420101e8@H_301_14@
[1 2 3 4 0 0 0 0 0 0]@H_301_14@ [2 3 4 0]@H_301_14@
PS@H_301_14@ E@H_301_14@:\golang@H_301_14@\go_pro@H_301_14@\src@H_301_14@\safly@H_301_14@>
切片拷贝make\copy\append
package@H_301_14@ main
import@H_301_14@(
"fmt"@H_301_14@
)
func@H_301_14@ main() {
var@H_301_14@ a []int@H_301_14@= []int@H_301_14@{1@H_301_14@,6@H_301_14@}
fmt.Println(a)
b:= make@H_301_14@([]int@H_301_14@,1@H_301_14@)
fmt.Println(b)
//将a的值拷贝到b@H_301_14@
copy@H_301_14@(b,a)
fmt.Println(b)
//将a拷贝到c@H_301_14@
c:=make@H_301_14@([]int@H_301_14@,10@H_301_14@)
copy@H_301_14@(c,a)
fmt.Println(c)
//append自己@H_301_14@
d :=append@H_301_14@(c,c...)
fmt.Println(d)
//append元素@H_301_14@
e:=append@H_301_14@(c,4@H_301_14@)
fmt.Println(e)
}
输出如下:
PS E:\golang@H_301_14@\go@H_301_14@_pro\src@H_301_14@\safly@H_301_14@> go run demo.go
[@H_301_14@1 2 3 4 5 6]@H_301_14@
[@H_301_14@0]@H_301_14@
[@H_301_14@1]@H_301_14@
[@H_301_14@1 2 3 4 5 6 0 0 0 0]@H_301_14@
[@H_301_14@1 2 3 4 5 6 0 0 0 0 1 2 3 4 5 6 0 0 0 0]@H_301_14@
[@H_301_14@1 2 3 4 5 6 0 0 0 0 2 4]@H_301_14@
PS E:\golang@H_301_14@\go@H_301_14@_pro\src@H_301_14@\safly@H_301_14@>
string与slice
string底层就是一个byte的数组,因此,也可以进行切片操作
string本身是不可变的,因此要改变string中字符,需要如下操作
package@H_301_14@ main@H_301_14@
import@H_301_14@(
"fmt@H_301_14@"
)
func@H_301_14@ main@H_301_14@() { s@H_301_14@:="hellogo"@H_301_14@ s1:=s[0@H_301_14@:3@H_301_14@] s2:=s[2@H_301_14@:] fmt.Println(s1)@H_301_14@ fmt.Println(s2)@H_301_14@ testModifyStr()@H_301_14@ @H_301_14@@H_301_14@@H_301_14@}
func@H_301_14@ testModifyStr@H_301_14@(){ //带中文的 s@H_301_14@:="我的hellogo"@H_301_14@ s1:=[]rune(s)@H_301_14@ s1[1@H_301_14@] = 'a'@H_301_14@ str:=string(s1)@H_301_14@ fmt.Println(str)@H_301_14@ aaa := "hello world"@H_301_14@ bbb := []byte(aaa)@H_301_14@ bbb[0@H_301_14@] = 'o'@H_301_14@ str = string(bbb)@H_301_14@ fmt.Println(str)@H_301_14@ @H_301_14@@H_301_14@@H_301_14@}
输出如下:
hel
llogo
我ahellogo
oello world
PS E:\golang@H_301_14@\go@H_301_14@_pro\src@H_301_14@\safly@H_301_14@>
切片循环
package@H_301_14@ main
import@H_301_14@(
"fmt"@H_301_14@
)
func@H_301_14@ main() {
var@H_301_14@ a []int@H_301_14@= []int@H_301_14@{1@H_301_14@,6@H_301_14@}
fmt.Println(a)
for@H_301_14@ index,val := range@H_301_14@ a {
fmt.Println(index,val)
}
for@H_301_14@ _,val := range@H_301_14@ a {
fmt.Print` n(val) } } @H_301_14@
输出如下:
PS E:\golang@H_301_14@\go@H_301_14@_pro\src@H_301_14@\safly@H_301_14@> go run demo.go
[@H_301_14@1 2 3 4 5 6]@H_301_14@
0 1
1 2
2 3
3 4
4 5
5 6
1
2
3
4
5
6
PS E:\golang@H_301_14@\go@H_301_14@_pro\src@H_301_14@\safly@H_301_14@>