美文网首页
golang-切片

golang-切片

作者: 爱吃豆包 | 来源:发表于2019-12-17 20:13 被阅读0次
package container

import "fmt"

/**
    切片
    切片本身没有值, 是对底层array的一个view(视图)
    所有的切片都是在原arr数组的范围中进行切出数据的!
    但是只能向后扩展,不能像前扩展!

    切片里面,声明的 var a []int 没有赋值上默认值, 默认是 nil,但是为nil的情况下,也可以直接往里面添加元素!

 */

/**
    切片是引用传递, 会直接修改原有的值
 */

// 修改其中的某个值
func updateSlice(s []int){
    s[0] = 100
}


func main() {

    arr := [...]int{0,1,2,3,4,5,6,7,8,9}

    // arr[2:6] =  [2 3 4 5]
    fmt.Println("arr[2:6] = ", arr[2:6])

    // arr[:6] =  [0 1 2 3 4 5]
    fmt.Println("arr[:6] = ", arr[:6])

    // arr[2:] =  [2 3 4 5 6 7 8 9]
    fmt.Println("arr[2:] = ", arr[2:])

    // arr[:] =  [0 1 2 3 4 5 6 7 8 9]
    fmt.Println("arr[:] = ", arr[:])


    /**
        通过 s1 := arr[2:6] 声明的切片  这个例子的结论:

        (1)s1 := arr[2:6] 想当于就是在原有的 arr 数组基础上,进行的一个部分内存地址的引用的指向,然后声明出的 s1 的这个变量!
        修改了 s1 里面的值,也会对原有的 arr 数组产生修改,因为他们使用的都是相同内存地址!

        (2)数组里面的每一个值在内存里面都会有一个唯一的内存地址标记!

     */


    // 自动类型,获取一个数组的部分值,转换为切片
    s1 := arr[2:6]
    updateSlice(s1)
    // s1 =  [100 1 2 3 4 5 6 7 8 9]
    fmt.Println("s1 = ", s1)
    fmt.Println("arr = ", arr)

    /**
        此时 s1 里面并没有 6~8 之间的下坐标数, 所以按照常理来说是没有值的!
        但是此时却是有值: s2 =  [8 9],
        为什么会有值?

        推论:
            (1)这 s2 =  [8 9] 的值是原arr数组的值。
            (2)这 s2 =  [8 9] 的值,是我Go语言获取到 s1 的最后一个值之后,针对最后一个值进行的加1操作!
                也就是说 s1 切片里面最后一个值是 5,那么我Go语言获取到这个 5 之后,在这个值上面往后加1,然后5的后面是6!
        (1)正确
        (2)错误

        这两个论证点哪一个是真?

        但是继续测试  s2 =  [8 9] // 报错 , 结果报错了,说切片超出范围!
        由此得知:我 s2 还是针对原arr数组获取的值!也就是说我的切片,切出的值都是基于原arr数组的范围!
        所以第一个论证点是正确的!

        所有的切片都是在原arr数组的范围中进行切出数据的!

        如果说 s1 := arr[2:6] 是这个范围,那么 s2 在s1上切片,s2 := s1[1:3] 是要出错的!因为s2受限于s1,
        但是 s2 := arr[6:8] 是受限于 原arr数组!
        也就是说 只能向后扩展,不能向前扩展!



     */
    s2 := s1[6:8]
    // s2 =  [8 9] // 报错
    fmt.Println("s2 = ", s2)

    // s1=[100 3 4 5],len(s1)=4, cap(s1)=8
    /**
        cap 表示总共有多少个可看的容量, 相当于就是从起始位置算起,只能看后面的,不能看前面的!
        也就是说 s1 是从下坐标2开始的,就只能从2开始算起,有多少个可以看的元素!
      */
    fmt.Printf("s1=%v,len(s1)=%d, cap(s1)=%d\n",s1,len(s1),cap(s1))


    /**
        切片添加元素的时候,是基于原arr元素的,
        如果超出了原arr数组的长度,Go语言会复制一份,在重新创建一个新的数组,新的数组的长度会比原arr数组要大,
        但是新数组的元素如果是旧数组的,那么就会继续使用原数组的元素的内存地址
        如果没有超出原arr数组,就把最后面的值给替换掉,那么对原arr数组本身存在数据会产生影响也会进行修改,因为内存地址相同
     */

    s3 := arr[4:9]
    fmt.Println("s3 = ", s3)
    // 往slice切片里面添加一个 元素
    s4 := append(s3, 23)
    fmt.Println("s4 = ", s4)
    fmt.Println("arr = ", arr)

    // make 分配函数
    /**
        make() 只用于映射、切片和程道,不返回指针。要明确的得到指针用 new() 分配
        make在分配的时候,不能超过总共大小的元素空间!
        比如 make([]int, 5, 10) 在分配的时候,第二个参数的不能大于第三个参数的值!
     */
    //创建一个初始元素个数为5的数组切片,元素初始值为0,并预留10个元素的存储空间
    // 相当于就是初始化5个大小的数组切片,然后共10个空间位置
    makeA := make([]int, 5, 10)    // len(makeA)=5, cap(makeA)=10
    fmt.Println("makeA = ", makeA)

    // 复制值,把 s1 的值复制到 makeA 中
    copy(makeA, s1)
    fmt.Println("复制之后的makeA = ", makeA)

    // 删除操作
    // 复制之后的makeA =  [100 3 4 5 0]
    // 删除makeA中的第3个元素,下坐标也就是2
    makeA = append(makeA[:2], makeA[3:]...)
    fmt.Println("删除元素后的 makeA = ", makeA) // [100 3 5 0]

}

相关文章

网友评论

      本文标题:golang-切片

      本文链接:https://www.haomeiwen.com/subject/oiyenctx.html