Golang slice slices are appended deleted inserted etc

  • 2020-06-12 09:22:38
  • OfStack

This paper introduces the addition, deletion and insertion of Golang slice slices, and shares the details as follows:

1. 1 General operation

1, declare variables, go automatically initialized to nil, length: 0, address: 0, nil


func main(){
  var ss []string;
  fmt.Printf("length:%v \taddr:%p \tisnil:%v",len(ss),ss, ss==nil)  
}

---
Running...

length:0   addr:0x0   isnil:true
Success: process exited with code 0.

2. Add, delete and insert slices


func main(){
  var ss []string;
  fmt.Printf("[ local print ]\t:\t length:%v\taddr:%p\tisnil:%v\n",len(ss),ss, ss==nil)  
  print("func print",ss)
  // Appends elements to the end of the slice append elemnt
  for i:=0;i<10;i++{
    ss=append(ss,fmt.Sprintf("s%d",i));
  }
  fmt.Printf("[ local print ]\t:\tlength:%v\taddr:%p\tisnil:%v\n",len(ss),ss, ss==nil)  
  print("after append",ss)
  // Delete slice elements remove element at index
  index:=5;
  ss=append(ss[:index],ss[index+1:]...)
  print("after delete",ss)
  // Insert elements in the middle of the slice insert element at index;
  // Note: Save the remaining elements in the back. You must create a new one 1 A temporary section 
  rear:=append([]string{},ss[index:]...) 
  ss=append(ss[0:index],"inserted")
  ss=append(ss,rear...)
  print("after insert",ss)
}
func print(msg string,ss []string){
  fmt.Printf("[ %20s ]\t:\tlength:%v\taddr:%p\tisnil:%v\tcontent:%v",msg,len(ss),ss, ss==nil,ss)  
  fmt.Println()
}
------
Running...

[ local print ]  :   length:0  addr:0x0  isnil:true
[      func print ]  :  length:0  addr:0x0  isnil:true  content:[]
[ local print ]  :  length:10  addr:0xc208056000  isnil:false
[     after append ]  :  length:10  addr:0xc208056000  isnil:false  content:[s0 s1 s2 s3 s4 s5 s6 s7 s8 s9]
[     after delete ]  :  length:9  addr:0xc208056000  isnil:false  content:[s0 s1 s2 s3 s4 s6 s7 s8 s9]
[     after insert ]  :  length:10  addr:0xc208056000  isnil:false  content:[s0 s1 s2 s3 s4 inserted s6 s7 s8 s9]

Success: process exited with code 0.

3. Use of copy.

Before using copy to copy slices, make sure that the target slice is sufficiently large, note the size, not the volume. Again, look at the example:


func main() {
  var sa = make ([]string,0);
  for i:=0;i<10;i++{
    sa=append(sa,fmt.Sprintf("%v",i))
    
  }
  var da =make([]string,0,10);
  var cc=0;
  cc= copy(da,sa);
  fmt.Printf("copy to da(len=%d)\t%v\n",len(da),da)
  da = make([]string,5)
  cc=copy(da,sa);
  fmt.Printf("copy to da(len=%d)\tcopied=%d\t%v\n",len(da),cc,da)
   da = make([]string,10)
  cc =copy(da,sa);
  fmt.Printf("copy to da(len=%d)\tcopied=%d\t%v\n",len(da),cc,da)
  
}

---
Running...

copy to da(len=0)  []
copy to da(len=5)  copied=5  [0 1 2 3 4]
copy to da(len=10)  copied=10  [0 1 2 3 4 5 6 7 8 9]

From the above running results, it is obvious that the target slice size is 0 with a capacity of 10 and copy cannot be copied. If the target slice size is smaller than the source slice size, copy will copy according to the target slice size without error.

2. Initial size and capacity

When we initialize slices with make, size must be given. go books 1 generally tell us that append is very fast when slices are large enough. But when given the initial size, what we actually get is an empty element with this size number slice type. Look at the example:


func main(){
  var ss=make([]string,10);
  ss=append(ss,"last");
  print("after append",ss)
  
}
---
Running...

[     after append ]  :  length:11  addr:0xc20804c000  isnil:false  content:[     last]

In fact, we should have subscripted the negative elements of the slice first. But if we want to have both good efficiency and elements that want to continue using the append function without distinguishing whether they are empty or not, then we need to specify the third parameter of make, the capacity, which we pass to make by the size of 0 and a large enough capacity value.


func main(){
  var ss=make([]string,0,10);
  ss=append(ss,"last");
  print("after append",ss)
  
}

---
Running...

[     after append ]  :  length:1  addr:0xc20804a000  isnil:false  content:[last]

3. Pointer to slice.

1. When we append elements to slices with append, if the capacity is insufficient, go will create a new slice variable to see the following program's execution results:


func main() {
  var sa []string
fmt.Printf("addr:%p \t\tlen:%v content:%v\n",sa,len(sa),sa);
  for i:=0;i<10;i++{
    sa=append(sa,fmt.Sprintf("%v",i))
    fmt.Printf("addr:%p \t\tlen:%v content:%v\n",sa,len(sa),sa);
  }
  fmt.Printf("addr:%p \t\tlen:%v content:%v\n",sa,len(sa),sa);

}

---
Running ...
addr:0x0     len:0 content:[]
addr:0x1030e0c8     len:1 content:[0]
addr:0x10328120     len:2 content:[0 1]
addr:0x10322180     len:3 content:[0 1 2]
addr:0x10322180     len:4 content:[0 1 2 3]
addr:0x10342080     len:5 content:[0 1 2 3 4]
addr:0x10342080     len:6 content:[0 1 2 3 4 5]
addr:0x10342080     len:7 content:[0 1 2 3 4 5 6]
addr:0x10342080     len:8 content:[0 1 2 3 4 5 6 7]
addr:0x10324a00     len:9 content:[0 1 2 3 4 5 6 7 8]
addr:0x10324a00     len:10 content:[0 1 2 3 4 5 6 7 8 9]
addr:0x10324a00     len:10 content:[0 1 2 3 4 5 6 7 8 9]

// Obviously, the address of the slice has changed several times. 

2. If sufficient capacity is given when make initializes the slice, the append operation will not create a new slice:


func main() {
  var sa = make ([]string,0,10);
fmt.Printf("addr:%p \t\tlen:%v content:%v\n",sa,len(sa),sa);
  for i:=0;i<10;i++{
    sa=append(sa,fmt.Sprintf("%v",i))
    fmt.Printf("addr:%p \t\tlen:%v content:%v\n",sa,len(sa),sa);
  }
  fmt.Printf("addr:%p \t\tlen:%v content:%v\n",sa,len(sa),sa);

}

addr:0x10304140     len:0 content:[]
addr:0x10304140     len:1 content:[0]
addr:0x10304140     len:2 content:[0 1]
addr:0x10304140     len:3 content:[0 1 2]
addr:0x10304140     len:4 content:[0 1 2 3]
addr:0x10304140     len:5 content:[0 1 2 3 4]
addr:0x10304140     len:6 content:[0 1 2 3 4 5]
addr:0x10304140     len:7 content:[0 1 2 3 4 5 6]
addr:0x10304140     len:8 content:[0 1 2 3 4 5 6 7]
addr:0x10304140     len:9 content:[0 1 2 3 4 5 6 7 8]
addr:0x10304140     len:10 content:[0 1 2 3 4 5 6 7 8 9]
addr:0x10304140     len:10 content:[0 1 2 3 4 5 6 7 8 9]

// See, the address of the slice 1 It stays the same 

3, if can't accurately estimate the size of the slices, and don't want to change variables (such as: in order to share data change), then will please with the help of a pointer, the following program, sa osa this slice of a pointer, we Shared biopsy data and operations are using the slice address ok, its essence is: append versa operation will be in need of constructing new section, but is to address are stored in sa, so we through the pointer always can access to the real data.


func main() {
  var osa = make ([]string,0);
  sa:=&osa;
  for i:=0;i<10;i++{
    *sa=append(*sa,fmt.Sprintf("%v",i))
    fmt.Printf("addr of osa:%p,\taddr:%p \t content:%v\n",osa,sa,sa);
  }
  fmt.Printf("addr of osa:%p,\taddr:%p \t content:%v\n",osa,sa,sa);
  
}

---
Running...

addr of osa:0xc20800a220,  addr:0xc20801e020   content:&[0]
addr of osa:0xc20801e0a0,  addr:0xc20801e020   content:&[0 1]
addr of osa:0xc20803e0c0,  addr:0xc20801e020   content:&[0 1 2]
addr of osa:0xc20803e0c0,  addr:0xc20801e020   content:&[0 1 2 3]
addr of osa:0xc208050080,  addr:0xc20801e020   content:&[0 1 2 3 4]
addr of osa:0xc208050080,  addr:0xc20801e020   content:&[0 1 2 3 4 5]
addr of osa:0xc208050080,  addr:0xc20801e020   content:&[0 1 2 3 4 5 6]
addr of osa:0xc208050080,  addr:0xc20801e020   content:&[0 1 2 3 4 5 6 7]
addr of osa:0xc208052000,  addr:0xc20801e020   content:&[0 1 2 3 4 5 6 7 8]
addr of osa:0xc208052000,  addr:0xc20801e020   content:&[0 1 2 3 4 5 6 7 8 9]
addr of osa:0xc208052000,  addr:0xc20801e020   content:&[0 1 2 3 4 5 6 7 8 9]


Related articles: