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)
}

 

posted @ 2018-12-02 16:45  小春熙子  阅读(197)  评论(0编辑  收藏  举报