Go编程基础之五
1.for循环,对于循环体内每次声明的变量来说,变量的地址都是不同的;
package main
import "fmt"
func main(){
for i := 0;i <3 ;i++{
v :=1
fmt.Println(&v)
}
}
输出:
D:\Go\src>go run hello.go
0x124100c8
0x124100cc
0x12410100
D:\Go\src>
2.切片Slice:
---其本身并不是数组,它指向底层的数组;
---作为变长数组的替代方案,可以关联底层数组的局部或全部;
----为引用类型
----可以直接创建或从底层数组获取生成
----使用len()获取元素个数,cap()获取容量、
----一般使用make()创建
----如果多个slice指向相同底层数组,其中一个的值改变会影响全部
-----make([]T,len,cap) 其中cap可以省略,则和len的值相同,len表示存数的元素个数,cap表示容量
(1)一般声明slice:
func main(){
var s1 []int //[]中既没有...也没数字表示我要的是slice类型,而不是array
fmt.Println(s1) //打印一个空的slice []
}
(2)slice依据索引取数组中的元素值:、
func main(){
a := [10]int{1,2,3,4,5,6,7,8,9}
fmt.Println(a)
s1 := a[9] //取一个索引为9的元素
s2 := a[5:10] //取a[5 6 7 8 9],从索引为5的元素一直取到数组的尾部
s3 := a[5:]
s4 := a[:5] //取前五个元素,而不会取索引为5的元素
fmt.Println(s1,s2)
}
(3)slice使用make声明:
func main(){ s1 :=make([]int,3,10) //初始化3个int类型,放到slice所指向的数组中; //第三个参数是初始容量10,会先分配给s1使用10小块连续的内存,当数组长度改变时(在10个之内),都不需要重新分配内存地址,而是一直使用初始分配的内存 //当长度超过10,内存会自动扩容为20,当长度到达22时,内存又自动扩容翻倍到40,不进行重新分配内存地址 fmt.Println(len(s1),cap(s1)) }
(4)slice与底层数之间的关系:
3.Reslice:从一个slice当中来获得另一个新的slice,这时两个slice指向的底层数组都是相同的
----Reslice时索引以被slice的切片为准;
func main(){ a := []byte{'a','b','c','d','e','f','g','h','i','j','k'} sa := a[2:5] fmt.Println(len(sa),cap(sa),string(sa)) //打印cde sb := sa[1:3] //打印de,也就是在sa的基础上再进行切片 sc := sa[3:5] //可以取出fg,因为slice是指向底层数组的某个位置,但是实际上的容量一直到数组的尾部 sd := sa[9:11] //取超出容量的部分,会报错--索引越界,因为此时就不属于内存块的位置了 fmt.Println(string(sb),string(sc)) }
----索引不可以超过被slice的切片的容量cap()值
----索引越界不会导致底层数组的重新分配而是引发错误
4.Append:函数
----可以在slice的尾部追加元素
----可以将一个slice追加在另一个slice尾部
func main(){ s1 := make([]int,3,6) fmt.Printf("%p\n",s1) //打印s1的内存地址 s1 = append(s1,1,2,3) //使用append函数追加元素,第一个参数是被追加的slice,从第二个元素开始是追加的内容 fmt.Printf("%v %p\n",s1,s1) //%v 打印值 这里使用Printf() 打印出的内存地址和之前的一样 }
----如果最终长度未超过追加到slice的容量则返回原始slice
----如果超过追加到的slice的容量则重新分配数组并拷贝原始数据
func main(){ s1 := make([]int,3,6) fmt.Printf("%p\n",s1) //打印s1的内存地址 s1 = append(s1,1,2,3) //使用append函数追加元素,第一个参数是被追加的slice,从第二个元素开始是追加的内容 fmt.Printf("%v %p\n",s1,s1) //%v 打印值 这里使用Printf(),打印出的内容地址相同 s1 = append(s1,1,2,3) //又追加3个元素,超出初始化slice的容量 fmt.Printf("%v %p\n",s1,s1) //打印的内存地址和之前不一样了 }
(1)共享底层数组的内存地址:
func main(){ a := []int{1,2,3,4,5} s1 := a[2:5] s2 := a[1:3] fmt.Println(s1,s2) //s1打印3,4,5 s2打印2,3 3是重叠部分,s1和s2共享了a数组中索引为2的部分 s1[0] = 9 fmt.Println(s1,s2) //s1和s2共享的部分,也就是索引为2的元素都变为9 }
(2)append元素超过slice的容量后,指向新的底层数组:
func main(){ a := []int{1,2,3,4,5} s1 := a[2:5] s2 := a[1:3] fmt.Println(s1,s2) //s1打印3,4,5 s2打印2,3 3是重叠部分,s1和s2共享了a数组中索引为2的部分 s2 = append(s2,1,2,1,1,2,1,2,1,5) //当append元素个数超过slice的容量,它就会指向新的底层数组,不在指向数组a s1[0] = 9 fmt.Println(s1,s2) //s2指向新的底层数组所以已经不共享了 }
5.Copy函数:
func main(){ s1 := []int{1,2,3,4,5,6} s2 := []int{7,8,91,1,1,1,1,1} copy(s2,s1) //把s1的元素拷贝到s2中 fmt.Println(s2) copy(s2[2:4],s1[1:3]) //把特定索引上的元素进行拷贝,也就是把s1中索引1到3的元素, fmt.Println(s2) }
有些人之所以不断成长,就绝对是有一种坚持下去的力量。好读书,肯下功夫,不仅读,还做笔记。人要成长,必有原因,背后的努力与积累一定数倍于普通人。所以,关键还在于自己。