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] [] []] */ }
~~~