• 【2018夏季达沃斯】未来就业报告发布:机器将比人更“能干” 哪些职位更“吃香”? 2018-09-19
  • 西安市民:本想买点香菜吃火锅?比较后还是买了些肉 2018-09-19
  • 安吉发布乡村治理标准规范 2018-09-19
  • 华北能源监管局开展电网运行风险管控专项督查 2018-09-18
  • 马来西亚新山依斯干达特区吸资2531亿马币 ——凤凰网房产马来西亚 2018-09-18
  • 繁星戏剧挑战浸没式独角戏 2018-09-18
  • 领导干部自然资源资产离任审计制度试点 让福建省光泽县绿意盎然(图)-地方新闻-时政频道-中工网 2018-09-08
  • 人民日报评留美生数落父母:为亲情拓对话空间 2018-09-07
  • 网友给四川省委书记、省长留言获回复 共计25条 2018-09-07
  • 娱乐城新优惠 2018-09-06
  • 无人售货架现身出租车内 乘客扫码付款随时取走零食 2018-09-06
  • 江西公布拖欠劳动报酬典型案例 最高拖欠近200万元 2018-09-06
  • 做学习宣传贯彻人民领袖思想的排头兵 2018-09-06
  • 华夏幸福荣获2018中国品牌先锋大奖之杰出企业奖 2018-09-05
  • 10大路口因礼让斑马线致堵 济南交警推新规约束行人 ——凤凰网房产济南 2018-09-05
  • GO学习笔记:GO基础--slice

    栏目: GO语言 发布于: 2014-08-20 10:25:32

    GO学习笔记:GO基础--slice

    在很多应用场景中,数组并不能满足我们的需求。在初始定义数组时,我们并不知道需要多大的数组,因此我们就需要“动态数组”。在Go里面这种数据结构叫slice

    slice并不是真正意义上的动态数组,而是一个引用类型。slice总是指向一个底层array,slice的声明也可以像array一样,只是不需要长度。

    // 和声明array一样,只是少了长度
    var fslice []int
    接下来我们可以声明一个slice,并初始化数据,如下所示:
    slice := []byte {'a', 'b', 'c', 'd'}
    slice可以从一个数组或一个已经存在的slice中再次声明。slice通过array[i:j]来获取,其中i是数组的开始位置,j是结束位置,但不包含array[j],它的长度是j-i。
    // 声明一个含有10个元素元素类型为byte的数组
    var ar = [10]byte {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
    
    // 声明两个含有byte的slice
    var a, b []byte
    
    // a指向数组的第3个元素开始,并到第五个元素结束,
    a = ar[2:5]
    //现在a含有的元素: ar[2]、ar[3]和ar[4]
    
    // b是数组ar的另一个slice
    b = ar[3:5]
    // b的元素是:ar[3]和ar[4]
    注意:slice和数组在声明时的区别:声明数组时,方括号内写明了数组的长度或使用...自动计算长度,而声明slice时,方括号内没有任何字符。

    它们的数据结构如下所示:

    slice和array的对应关系图

    slice有一些简便的操作:

        1、slice的默认开始位置是0,ar[:n]等价于ar[0:n]

        2、slice的第二个序列默认是数组的长度,ar[n:]等价于ar[n:len(ar)]

        3、如果从一个数组里面直接获取slice,可以这样ar[:],因为默认第一个序列是0,第二个是数组的长度,即等价于ar[0:len(ar)]

    下面这个例子展示了更多关于slice的操作:

    // 声明一个数组
    var array = [10]byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
    // 声明两个slice
    var aSlice, bSlice []byte
    
    // 演示一些简便操作
    aSlice = array[:3] // 等价于aSlice = array[0:3] aSlice包含元素: a,b,c
    aSlice = array[5:] // 等价于aSlice = array[5:10] aSlice包含元素: f,g,h,i,j
    aSlice = array[:]  // 等价于aSlice = array[0:10] 这样aSlice包含了全部的元素
    
    // 从slice中获取slice
    aSlice = array[3:7]  // aSlice包含元素: d,e,f,g,len=4,cap=7
    bSlice = aSlice[1:3] // bSlice 包含aSlice[1], aSlice[2] 也就是含有: e,f
    bSlice = aSlice[:3]  // bSlice 包含 aSlice[0], aSlice[1], aSlice[2] 也就是含有: d,e,f
    bSlice = aSlice[0:5] // 对slice的slice可以在cap范围内扩展,此时bSlice包含:d,e,f,g,h
    bSlice = aSlice[:]   // bSlice包含所有aSlice的元素: d,e,f,g
    slice是引用类型,所以当引用改变其中元素的值时,其它的所有引用都会改变该值,例如上面的aSlice和bSlice,如果修改了aSlice中元素的值,那么bSlice相对应的值也会改变。

    从概念上面来说slice像一个结构体,这个结构体包含了三个元素:

        1、一个指针,指向数组中slice指定的开始位置

        2、长度,即slice的长度

        3、最大长度,也就是slice开始位置到数组的最后位置的长度

    Array_a := [10]byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
    Slice_a := Array_a[2:5]
    上面代码的真正存储结构如下图所示:

    slice对应数组的信息

    对于slice有几个有用的内置函数:

        1、len 获取slice的长度

        2、cap 获取slice的最大容量

        3、append 向slice里面追加一个或者多个元素,然后返回一个和slice一样类型的slice

        4、copy 函数copy从源slice的src中复制元素到目标dst,并且返回复制的元素的个数

    注:append函数会改变slice所引用的数组的内容,从而影响到引用同一数组的其它slice。 但当slice中没有剩余空间(即(cap-len) == 0)时,此时将动态分配新的数组空间。返回的slice数组指针将指向这个空间,而原数组的内容将保持不变;其它引用此数组的slice则不受影响。

    这句话什么意思呢?让我们来看几个示例:

    示例1:

    package main
    
    import "fmt"
    
    func main() {
    	Array_a := [8]int{1, 2, 3, 4, 5, 6, 7, 8}
    	Slice_a := Array_a[2:5]
    	fmt.Println(Slice_a)
    	fmt.Println(Array_a)
    
    	Slice_a = append(Slice_a, 9, 10)
    	fmt.Println(Slice_a)
    	fmt.Println(Array_a)
    }
    输出结果:
    [3 4 5]
    [1 2 3 4 5 6 7 8]
    [3 4 5 9 10]
    [1 2 3 4 5 9 10 8]
    我们可以看到,对Slice_a进行追加元素后,原来的数组Array_a也随着发生了变化。

    示例2:

    package main
    
    import "fmt"
    
    func main() {
    	Array_a := [8]int{1, 2, 3, 4, 5, 6, 7, 8}
    	Slice_a := Array_a[2:5]
    	fmt.Println(Slice_a)
    	fmt.Println(Array_a)
    
    	Slice_a = append(Slice_a, 9, 10, 11, 12, 13, 14)
    	fmt.Println(Slice_a)
    	fmt.Println(Array_a)
    }
    输出结果:
    [3 4 5]
    [1 2 3 4 5 6 7 8]
    [3 4 5 9 10 11 12 13 14]
    [1 2 3 4 5 6 7 8]
    可以看到,对Slice_a进行追加元素后,当追加后的长度超出原来的CAP时,原来的数组Array_a将保持不变。
    本站文章除注明转载外,均为本站原创或编译?;队魏涡问降淖?,但请务必注明出处。
    转载请注明:文章转载自 七星彩票平台
    本文标题:GO学习笔记:GO基础--slice
    IT技术书籍推荐:
    GitHub入门与实践
    GitHub入门与实践
    大塚弘记 (作者), 支鹏浩 (译者), 刘斌 (译者)
    《GitHub入门与实践》从Git的基本知识和操作方法入手,详细介绍了GitHub的各种功能,GitHub与其他工具或服务的协作,使用GitHub的开发流程以及如何将GitHub引入到企业中。在讲解GitHub的代表功能Pull Request时,本书专门搭建了供各位读者实践的仓库,邀请各位读者进行Pull Request并共同维护。 《GitHub入门与实践》旨在指导各位读者如何在开发现场使用GitHub进行高效开发,适合所有想要使用GitHub进行开发的程序员或团队阅读。