当前位置:网站首页>Go language, array, string, slice

Go language, array, string, slice

2022-04-23 16:54:00 The interview was rejected 10000 times

Array , character string , section

Notes It's a personal summary 《Go Language advanced programming 》 Learning notes of

Basic data structure , Only when these are not satisfied will the linked list be used ,map, Structure and other data structures .

Array , character string , section Have the same memory structure , Are contiguous blocks of memory , Because of the limitation in grammar, there are different expressions , Understand the memory structure , They can be better understood and used

  • Array : Corresponding continuous byte array , Memory data can be modified , But it's a value type , Both assignment and parameter transfer are global assignment
  • character string : Corresponding continuous byte array , Memory data cannot be modified , Read-only property
  • section : Most used , An array of contiguous bytes , But the slice head contains Pointer to underlying data , Data length and capacity information , When passing parameters, you only need to pass this information , More efficient

Array

Memory block of data type of continuous memory , Follow c The difference in language is ,Go The array name in is a value type ,

  • stay c In language , The array name table shows the address of the first element of the array , In other words, array names have the concept of addresses
  int a[10],*p;
  p = a;
  p = &a[0]; // When passing parameters , Just pass the first address 
  • stay go in , The array name represents an array variable , Not the address that points to the first element of the array , When assigning or transferring parameters , The whole array is passed , Not enough efficient
   a := [...]int {
    1,2,3}  // Declare and initialize  a = {1,2,3}
   func test(a [3]int){
    
      ...
   }
   test(a) // Passing is the entire array 

Arrays can define a variety of array types , It looks fun

  • A character array
  var s1=[2]string{
    "hello", "world"}
  • Array of structs
  var line2 = [...]People.Student{
    People.Student{
    age : 30 , score :100}, People.Student{
    age : 20 , score :100}}
  • Function array
var decoder2 = [...] func (io.Reader) (image.Image, error){
    
                              png.Decode,
                              jpeg.Decode,
                            }
  • Interface array
  var unknown2 = [...] interface {
    }{
     123 , " Hello " }
  • Pipeline array
  var chanList = [2] chan int{
    }

character string

The string is It can't be changed Character sequence ,Go The definition of string in language is a structure

  type  StringHeader  struct  {
    
      Data  uintptr
      Len int
    }

Personal understanding : Open up a structure memory on the stack ,Data Character constant pointing to static area ,Len Represents character length , That is, the underlying structure of each string is also a structure , The book also says that character arrays are also structural arrays in essence

Confusion remains unsolved :

func testString() {
    
    string1 := [...]string{
    "helloooooooo", "worlddddddd"}
    fmt.Printf("arr = %p, string1[0] =%p,string1[0] =%s,len string1[0] = %d,string[1] = %p", &string1, &string1[0], string1[0], len(string1[0]), &string1[1])

    //arr = 0xc000062040, string1[0] =0xc000062040,string1[0] =helloooooooo,len string1[0] = 12,string[1] = 0xc000062050
}
// string1[0]  Is the length of the 12,
// &string1[1] - &string[0] = 10  Why is that? , I think the result will be  &string1[1] - &string[0] = 13

section

 come from Go Language advanced programming

Structure definition of slice

type  SliceHeader  struct  {
    
    Data  uintptr
    Len   int
    Cap   int
  }

Slicing is a simple dynamic array , One more than the string cap Capacity , The idea of dynamic arrays is , As long as the length is less than the capacity , When you add elements , Memory will not be reallocated if it is not larger than the capacity , Can't copy data , Exceeding the capacity will reallocate memory space , Then slice and copy . When assigning and passing parameters , Are the assignment and parameter transfer of the structure

Slice definition

   var a = []int   // nil section  a == nil
   var b = []int {
     } // Empty set  , It's not equal to  nil
   var c = []int {
    1,2,3}  //len = 3 ,cap = 3
   var d = make([]int ,2,3) //len = 2 , cap = 3

The difference between arrays

  • The same thing

Built in len Function returns the length of the valid element in the slice , Built in cap Function returns the slice size , The traversal and computation lengths are the same

  • Difference
  1. The slice capacity is greater than or equal to the length , Array must be equal to .
  2. What has a length definition is an array , Nothing is slicing .
  3. Arrays are value types , Assignment is an overall assignment , A slice is a structure , The type and length of the array should be the same as the data type , The type of slice is independent of the length , As long as the slices composed of the same data type are all slices of the same type ,

Addition and deletion of slices

First, let's look at the calculation of the length and capacity of the slice in the assignment


func SliceAssignment() {
    

	// First, let's review   What is the opening and closing interval 
	// a,b  All real numbers between ,  But does not include  a,b  Remember to do (a,b)
	// a,b  All real numbers between ,  Include a,b  And  a < b  Remember to do [a,b]

	//  Opening and closing rules of slices 
	a := []int{
    10, 20, 30, 40, 50, 60, 7, 8, 9}
	fmt.Printf(" len: %d, cap: %d , arr = %p , arr %+v \n", len(a), cap(a), a, a)
	//len: 9, cap: 9 , arr = 0xc0000ba000 , arr [10 20 30 40 50 60 7 8 9]

	d := a[:3] //  Left closed right away  [0,3)
	fmt.Printf(" len: %d, cap: %d , arr = %p , arr %+v \n", len(d), cap(d), d, d)
	//len: 3, cap: 9 , arr = 0xc0000ba000 , arr [10 20 30]

	b := a[2:]
	fmt.Printf(" len: %d, cap: %d , arr = %p , arr %+v \n", len(b), cap(b), b, b)
	// len: 7, cap: 7 , arr = 0xc0000ba010 , arr [30 40 50 60 7 8 9]

	c := a[2:6]
	fmt.Printf(" len: %d, cap: %d , arr = %p , arr %+v \n", len(c), cap(c), c, c)
	//len: 4, cap: 7 , arr = 0xc0000ba010 , arr [30 40 50 60]

}

summary

How to calculate the length and Capacity
newslice := slice[ i : j ]
Without writing Default i = 0 , j = len(slice) k= cap(slice)
len(newslice) = j - i example: len(d) = 3 - 0 , len = 6-2
cap(newslice) = k - i example: len(d) = 9 -0 , len(b) = len = 9 - 2

Additional elements append()

a := []int{
    1, 2, 3}

// Add... At the beginning 1 A slice 
a = append([]int{
    100, 200, 300}, a...)
fmt.Printf("a= len: %d, cap: %d , arr = %p , arr %+v \n", len(a), cap(a), a, a)
//a= len: 6, cap: 6 , arr = 0xc000196030 , arr [100 200 300 1 2 3]

//  stay i=3  Add a slice to the location of the , Reallocated memory space 
a = append(a[:3], append([]int{
    1000, 2000}, a[3:]...)...)
fmt.Printf("a= len: %d, cap: %d , arr = %p , arr %+v \n", len(a), cap(a), a, a)
// a= len: 8, cap: 12 , arr = 0xc0001ae000 , arr [100 200 300 1000 2000 1 2 3]


b := append([]int{
    666, 777}, a[4:]...) // Re unpacked 
fmt.Printf("b= len: %d, cap: %d , arr = %p , arr %+v \n", len(b), cap(b), b, b)
//b= len: 6, cap: 6 , arr = 0xc000196090 , arr [666 777 2000 1 2 3]

// a  It hasn't changed 
fmt.Printf("a= len: %d, cap: %d , arr = %p , arr %+v \n", len(a), cap(a), a, a)
//a= len: 8, cap: 12 , arr = 0xc0001ae000 , arr [100 200 300 1000 2000 1 2 3]

// a Changed the ,a and c  Point to the same memory space 
c := append(a[:3], []int{
    888, 999}...)
fmt.Printf("a= len: %d, cap: %d , arr = %p , arr %+v \n", len(a), cap(a), a, a)
//a= len: 8, cap: 12 , arr = 0xc0001ae000 , arr [100 200 300 888 999 1 2 3]
fmt.Printf("c= len: %d, cap: %d , arr = %p , arr %+v \n", len(c), cap(c), c, c)
//c= len: 5, cap: 12 , arr = 0xc0001ae000 , arr [100 200 300 888 999]

summary

Inserting in the header will generally reallocate space , There is a copy of the array . In the middle of the slice , Or tail insertion will create a temporary slice , take a[i:] Copy the contents of , Then add it to a[:i]

Insert slices that do not create temporary slices :
copy(des,src) function

func testcopy() {
    
    s1 := []int{
    1, 2, 3}
    s2 := []int{
    4, 5}
    s3 := []int{
    6, 7, 8, 9}
    // copy(s1, s2)
    // fmt.Println(s1) //[4 5 3]
    copy(s2, s1)
    fmt.Println(s2) //[1.2]
    copy(s2, s3)
    fmt.Println(s2) //[6 7]
}

Use copy() function , Do not create temporary variables

copy(a[4:], a[3:]) // a[i:] Move backward 1 A place , The length remains the same , Remove one from the tail element 
fmt.Printf(" len: %d, cap: %d , arr = %p , arr %+v \n", len(a), cap(a), a, a)
//len: 8, cap: 12 , arr = 0xc0001ae000 , arr [100 200 300 888 888 999 1 2]

// If you don't create a temporary variable 
i := 2
x := []int{
    101, 102, 103}
a = append(a, x...) // by x The slice expands enough space 
copy(a[i+len(x):], a[i:]) // a[i:] Move backward len(x) A place 
copy(a[i:], x)   //  Copy the newly added slice 

Slice deletion
General deletion

  var a = []int {
    1,2,3}
  a = a[ :len(a) - 1]  // Delete the last element 
  a = a[ :len(a) - N]  //  Delete tail  N Elements 

  a = a[1:] //  Delete the head 1 Elements 
  a = a[N:] //  Delete the head N Elements 

Use append Complete in place : The so-called in-situ completion refers to the original Some slice data are completed in the corresponding memory interval , Will not cause memory space structure The change of

func removeSlice() {
    

	var a = []int{
    1, 2, 3, 4, 5}
	fmt.Printf("removeSlice  The original address = len: %d, cap: %d , arr = %p , arr %+v \n", len(a), cap(a), a, a)
  //removeSlice  The original address = len: 5, cap: 5 , arr = 0xc0000aa0f0 , arr [1 2 3 4 5]

	a = a[:len(a)-1]
	fmt.Printf("removeSlice  Delete tail = len: %d, cap: %d , arr = %p , arr %+v \n", len(a), cap(a), a, a)
  //removeSlice  Delete tail = len: 4, cap: 5 , arr = 0xc0000aa0f0 , arr [1 2 3 4]

	a = a[1:]
	fmt.Printf("removeSlice  Delete the head = len: %d, cap: %d , arr = %p , arr %+v \n", len(a), cap(a), a, a)
  //removeSlice  Delete the head = len: 3, cap: 4 , arr = 0xc0000aa0f8 , arr [2 3 4]

	a = append(a[:0], a[1:]...)
	fmt.Printf("removeSlice  Delete the head = len: %d, cap: %d , arr = %p , arr %+v \n", len(a), cap(a), a, a)
  //removeSlice  Delete the head = len: 2, cap: 4 , arr = 0xc0000aa0f8 , arr [3 4]
}

summary
Ordinary deletion will change the address , Data mobility , The capacity gets smaller , Use append There will be no change of position , The capacity will not change ( Here's why , It's not clear ), Use append More efficient

So delete the element

  a = append(a[:i],a[i+1:]...)
  a = append(a[:i],a[i+N:]...)

Efficient operation of slicing :

  • To reduce the number of memory allocations , Try to make sure that append The operation will not exceed cap The capacity of , Reduce the number of times that trigger memory allocation
    Number and size of memory allocated each time .
  • Avoid memory leaks , Although there is an automatic recycling mechanism , But when operating the pointer , You should still optimize your code , Tell the compiler to automatically reclaim the memory space to be released as soon as possible ,
func SliceDel() {
    
  	a := []*int{
    }
  	b := 100
  	c := 10
  	a = append(a, &b, &c)
  	a[len(a)-1] = nil //  Using the pointer object   section , It is better to manually set it to nil, Ensure that the automatic collector can find the objects to be recycled 
  	a = a[:len(a)-1]
}
  • Slice type forced conversion . For the sake of safety , When two slice types []T and []Y The underlying primitive slice class Different types ,Go Languages cannot convert types directly . But security is there At a price , Sometimes this transformation has its value —— Can simplify the compilation of Code or improve the performance of code .

This Reading Note , read 《GO Language advanced programming 》 income , You can buy genuine books , It's still valuable .

版权声明
本文为[The interview was rejected 10000 times]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204231359046299.html