zoukankan      html  css  js  c++  java
  • Go编程基础之五

    1.for循环,对于循环体内每次声明的变量来说,变量的地址都是不同的;

    package main
    
    import "fmt"
    
    func main(){
       for i := 0;i <3 ;i++{
           v :=1
           fmt.Println(&v)      
        } 
    
    }

    输出:

    D:Gosrc>go run hello.go
    0x124100c8
    0x124100cc
    0x12410100
    
    D:Gosrc>

    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
    ",s1)  //打印s1的内存地址
      s1 = append(s1,1,2,3)       //使用append函数追加元素,第一个参数是被追加的slice,从第二个元素开始是追加的内容
      fmt.Printf("%v %p
    ",s1,s1) //%v  打印值  这里使用Printf()  打印出的内存地址和之前的一样
    }

    ----如果最终长度未超过追加到slice的容量则返回原始slice

    ----如果超过追加到的slice的容量则重新分配数组并拷贝原始数据

    func main(){
      s1 := make([]int,3,6)
      fmt.Printf("%p
    ",s1)  //打印s1的内存地址
      s1 = append(s1,1,2,3)       //使用append函数追加元素,第一个参数是被追加的slice,从第二个元素开始是追加的内容
      fmt.Printf("%v %p
    ",s1,s1) //%v  打印值  这里使用Printf(),打印出的内容地址相同
      s1 = append(s1,1,2,3)   //又追加3个元素,超出初始化slice的容量
      fmt.Printf("%v %p
    ",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)
    }

  • 相关阅读:
    MinDoc v0.6 发布,轻量级文档在线管理系统
    PostMessage和SendMessage有什么区别?(有EnumChildWindowsProc的例子)
    将QuickReport报表保存为图片(使用TMetaFile和TMetafileCanvas)
    如何将JPEG缩略图放到LISTVIEW中(delphi listview自绘图形)
    栈和队列
    SQL调优日志--内存问题
    Nancy之实现API
    JAVA和.NET互调用
    NET Core环境并创建运行ASP.NET网站
    React Native
  • 原文地址:https://www.cnblogs.com/hqutcy/p/10052680.html
Copyright © 2011-2022 走看看