• Golang中append与copy内置函数介绍


    append

    package a_slice_copy
    
    import (
        "fmt"
        "strconv"
        "testing"
    )
    
    // TODO append函数
    func printSlice(name string, x []string) {
        fmt.Print(name, " > ")
        fmt.Printf("addr:%p len=%d cap=%d slice=%v \n", x, len(x), cap(x), x)
    }
    
    // append 自动扩容测试
    func TestT1(t *testing.T) {
        var sa []string
        printSlice("sa", sa)
    
        // 当使用append追加元素到切片时,如果容量不够,Go会创建一个新的切片变量来存储元素
        for i := 0; i < 10; i++ {
            sa = append(sa, strconv.Itoa(i))
            printSlice("sa", sa)
        }
        printSlice("sa", sa)
    }
    
    /*
    TODO Test1 测试结果如下
    sa > addr:0x0 len=0 cap=0 slice=[]
    sa > addr:0xc000044510 len=1 cap=1 slice=[0]
    sa > addr:0xc000026080 len=2 cap=2 slice=[0 1]
    sa > addr:0xc0000106c0 len=3 cap=4 slice=[0 1 2]
    sa > addr:0xc0000106c0 len=4 cap=4 slice=[0 1 2 3]
    sa > addr:0xc00010a080 len=5 cap=8 slice=[0 1 2 3 4]
    sa > addr:0xc00010a080 len=6 cap=8 slice=[0 1 2 3 4 5]
    sa > addr:0xc00010a080 len=7 cap=8 slice=[0 1 2 3 4 5 6]
    sa > addr:0xc00010a080 len=8 cap=8 slice=[0 1 2 3 4 5 6 7]
    sa > addr:0xc00011a000 len=9 cap=16 slice=[0 1 2 3 4 5 6 7 8]
    sa > addr:0xc00011a000 len=10 cap=16 slice=[0 1 2 3 4 5 6 7 8 9]
    sa > addr:0xc00011a000 len=10 cap=16 slice=[0 1 2 3 4 5 6 7 8 9]
    */
    
    // append其他操作
    func TestT2(t *testing.T) {
        // 初始化一个slice
        lst := make([]string, 0, 20)
        printSlice("lst", lst)
    
        // 两种append的方法
        lst = append(lst, "whw", "naruto")
        printSlice("lst", lst)
        lst = append(lst, []string{"sasuke", "www", "sakurua"}...)
        printSlice("lst", lst)
    
        // 删除第一个元素
        //lst = lst[1:]
        //printSlice("lst", lst)
        //// 删除最后一个元素
        //lst = lst[:len(lst)-1]
        //printSlice("lst", lst)
        // 删除中间的元素
        mid := int(len(lst) / 2)
        lst = append(lst[:mid], lst[mid+1:]...)
        printSlice("lst", lst)
    }
    
    /*
    TODO Test2测试结果入下:
    lst > addr:0xc0000d0140 len=0 cap=20 slice=[]
    lst > addr:0xc0000d0140 len=2 cap=20 slice=[whw naruto]
    lst > addr:0xc0000d0140 len=5 cap=20 slice=[whw naruto sasuke www sakurua]
    lst > addr:0xc0000d0140 len=4 cap=20 slice=[whw naruto www sakurua]
    */

    copy函数

    string的情况

    // As a special case, it also will copy bytes from a string to a slice of bytes
    func TestT4(t *testing.T){
    
        // TODO case1:
        bs1 := []byte{'A','M'}
        s1 := "Naruto"
        count := copy(bs1, s1)
        // 只 copy 了2个
        fmt.Println("count> ", count) // 2
        fmt.Println("bs1: ", string(bs1)) // Na
    
        // TODO case2:
        s2 := "Sasuke"
        bs2 := make([]byte,len(s2))
        count2 := copy(bs2, s2)
        fmt.Println("count2: ", count2) // 6
        fmt.Println("bs2:: ", string(bs2)) // bs2::  Sasuke
    }

    源切片没有数据的情况

    // TODO 源切片没有数据的情况
    func TestT3(t *testing.T) {
        lst := make([]string, 0, 20)
        lst = append(lst, "whw", "naruto")
        lst = append(lst, []string{"sasuke", "www", "sakurua"}...)
        printSlice("lst", lst) // lst > addr:0xc0000d0140 len=5 cap=20 slice=[whw naruto sasuke www sakurua]
    
        // 创建切片 长度与容量是之前的2倍
        lst2 := make([]string, len(lst)*2, cap(lst)*2)
        count := copy(lst2, lst)
        fmt.Println("count>>> ", count) // TODO 这里count是5!!!
        printSlice("lst2", lst2)        // lst2 > addr:0xc0000d2500 len=10 cap=40 slice=[whw naruto sasuke www sakurua     ]
    
        // TODO lst2 与 lst 不存在任何关系!!!
        lst2[0] = "abc"
        printSlice("lst2", lst2) // lst2 > addr:0xc000148500 len=10 cap=40 slice=[abc naruto sasuke www sakurua     ]
        printSlice("lst", lst)   // lst > addr:0xc000146140 len=5 cap=20 slice=[whw naruto sasuke www sakurua]
    }

    源切片有数据的情况会覆盖

    // 源切片有数据的情况
    func TestT5(t *testing.T) {
        lst := make([]string, 0, 20)
        lst = append(lst, "whw", "naruto")
        lst = append(lst, []string{"sasuke", "www", "sakurua"}...)
        printSlice("lst", lst) // lst > addr:0xc0000d0140 len=5 cap=20 slice=[whw naruto sasuke www sakurua]
    
        // 创建切片 长度与容量是之前的2倍
        lst2 := make([]string, len(lst)*2, cap(lst)*2)
        // TODO 源切片追加数据
        lst2 = append(lst2, "WWW","HHH")
        // TODO 可以看到 是追加到了最后2位置了
        printSlice("lst2", lst2) // lst2 > addr:0xc0000da500 len=12 cap=40 slice=[          WWW HHH]
    
        // TODO 第一 第二 个位置,写入元素
        lst2[0] = "大王"
        lst2[1] = "小王"
        printSlice("lst2", lst2) // lst2 > addr:0xc000112500 len=12 cap=40 slice=[大王 小王         WWW HHH]
    
        count := copy(lst2, lst)
        fmt.Println("count>>> ", count) // TODO 这里count是5
        // TODO 把原来的数据覆盖了!!!
        printSlice("lst2", lst2)  // lst2 > addr:0xc0000da500 len=12 cap=40 slice=[whw naruto sasuke www sakurua      WWW HHH]
    
        // TODO lst2 与 lst 不存在任何关系!!!
        lst2[0] = "abc"
        printSlice("lst2", lst2) // lst2 > addr:0xc0000da500 len=12 cap=40 slice=[whw naruto sasuke www sakurua      WWW HHH]
        printSlice("lst", lst)   // lst > addr:0xc000146140 len=5 cap=20 slice=[whw naruto sasuke www sakurua]
    }

    二维数组copy后实际也是个浅拷贝-但是有2种情况需要注意

    Python浅拷贝的例子

    import copy
    
    lst = [123, 222, [333, 555]]
    lst2 = copy.copy(lst)
    print("lst2>>> ", lst2)
    
    lst2[2].append("whw")
    print("lst:", lst)
    print("lst2:", lst2)
    
    """
    lst2>>>  [123, 222, [333, 555]]
    lst: [123, 222, [333, 555, 'whw']]
    lst2: [123, 222, [333, 555, 'whw']]
    """

    Go的例子1: 直接改变有关系

    package a_slice_copy
    
    import (
        "fmt"
        "testing"
    )
    
    func TestS1(t *testing.T) {
    
        lst := [][]string{{"www", "naruto"}, {"ww1", "naruto1"}}
        fmt.Println("lst1: ", lst) //[[www naruto] [ww1 naruto1]]
        // 创建切片 长度与容量是原来的2倍
        lst2 := make([][]string, len(lst)*2, cap(lst)*2)
        count := copy(lst2, lst) 
        fmt.Println("count", count) // 2
        fmt.Println("lst2: ", lst2) // lst2:  [[www naruto] [ww1 naruto1] [] []]
    
        // TODO copy后的lst2与原来的lst有关系吗?二维数组是有关系的!!!
        lst2[0][1] = "ABC"
        fmt.Println("==========================")
        fmt.Println("lst: ", lst)
        fmt.Println("lst2: ", lst2)
    }

    Go的例子: append导致扩容没关系了

    func TestS1(t *testing.T) {
    
        lst := [][]string{{"www", "naruto"}, {"ww1", "naruto1"}}
        fmt.Println("lst1: ", lst) //[[www naruto] [ww1 naruto1]]
        // 创建切片 长度与容量是原来的2倍
        lst2 := make([][]string, len(lst)*2, cap(lst)*2)
        count := copy(lst2, lst)
        fmt.Println("count", count) // 2
        fmt.Println("lst2: ", lst2) // lst2:  [[www naruto] [ww1 naruto1] [] []]
    
        // TODO copy后的lst2与原来的lst有关系吗?
        // TODO ———— 如果只是改变数值是有关系的
        lst2[0][1] = "ABC"
        fmt.Println("==========================")
        fmt.Println("lst: ", lst)
        fmt.Println("lst2: ", lst2)
    
        // TODO 但是,如果append扩容的话,就不一样了!!!一定要注意
        lst2[1] = append(lst2[1], "sawuke")
        fmt.Println("==========================")
        fmt.Println("lst: ", lst)
        fmt.Println("lst2: ", lst2)
        /*
            ==========================
            lst:  [[www ABC] [ww1 naruto1]]
            lst2:  [[www ABC] [ww1 naruto1 sawuke] [] []]
        */
    }

    ~~~

  • 相关阅读:
    redis实时同步工具redis-shake
    elasticsearch单机部署
    ogg从库进程监控
    mha安装部署
    mha自定义路径安装
    gnuplot输出柱状图
    gnuplot输出曲线图
    gnuplot命令行模式不支持中文标题的解决办法
    ogg中logdump使用自动输入执行
    JDK(java se development kit)的构成
  • 原文地址:https://www.cnblogs.com/paulwhw/p/15646455.html
Copyright © 2020-2023  润新知