Hi, I’m HHF.

Please tell the difference between slice and array.

This is like a bonus question. Now think about it, how can you answer it to make the interviewer happy?

I’m not going to post the answer to that question here. But I want to briefly analyze the difference between Slice and array in memory.

Array

func main(a) {
  as := [4]int{10.5.8.7}
  
  fmt.Println("As [0].", as[0])
  fmt.Println("As [1].", as[1])
  fmt.Println("As [2].", as[2])
  fmt.Println("As [3].", as[3])}Copy the code

This is a very simple code that declares an array. Of course, the output is simple enough.

Now let’s do a little trickery, how do we access the elements of an array by unusual means? You need to know the underlying structure of array before you can do this. A Go array is a contiguous memory space. As shown in the figure below

To write a simple piece of code, we don’t get elements by subscript access. To obtain the corresponding position of the pointer by moving the pointer.

func main(a) {
    as := [4]int{10.5.8.7}

    p1 := *(*int)(unsafe.Pointer(&as))
    fmt.Println("as[0]:", p1)

    p2 := *(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&as)) + unsafe.Sizeof(as[0])))
    fmt.Println("as[1]:", p2)

    p3 := *(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&as)) + unsafe.Sizeof(as[0]) *2))
    fmt.Println("as[2]:", p3)

    p4 := *(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&as)) + unsafe.Sizeof(as[0]) *3))
    fmt.Println("as[3]:", p4)
}
Copy the code

Results:

as[0]: 10
as[1]: 5
as[2]: 8
as[3]: 7
Copy the code

The following figure shows the process of getting the value of the corresponding position:

Slice

Also for slice this simple code:

func main(a) {
  as := []int{10.5.8.7}
  
  fmt.Println("As [0].", as[0])
  fmt.Println("As [1].", as[1])
  fmt.Println("As [2].", as[2])
  fmt.Println("As [3].", as[3])}Copy the code

To retrieve slice values by moving Pointers, you still need to know the underlying structure of slice. As shown in figure:

func main(a) {
    as := []int{10.5.8.7}

    p := *(*unsafe.Pointer)(unsafe.Pointer(&as))
    fmt.Println("as[0]:"(*, *int)(unsafe.Pointer(uintptr(p))))
    fmt.Println("as[1]:"(*, *int)(unsafe.Pointer(uintptr(p) + unsafe.Sizeof(&as[0]))))
    fmt.Println("as[2]:"(*, *int)(unsafe.Pointer(uintptr(p) + unsafe.Sizeof(&as[0]) *2)))
    fmt.Println("as[3]:"(*, *int)(unsafe.Pointer(uintptr(p) + unsafe.Sizeof(&as[0]) *3)))

    var Len = *(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&as)) + uintptr(8)))
    fmt.Println("len", Len) 

    var Cap = *(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&as)) + uintptr(16)))
    fmt.Println("cap", Cap) 
}
Copy the code

Results:

as[0]: 10
as[1]: 5
as[2]: 8
as[3]: 7
len 4
cap 4
Copy the code

The elements in slice’s underlying Data are slightly different from those in array:

  • The address of the slice variable as returns the address of the SiceHeader. Move the pointer to get the slice Data, Len, Cap.
  • So when we get the value of Data, we get the value of the first address of the array that Data points to.
  • Since this value is a pointer, we need to get the pointer value *Data to the real first address of the array
  • The value &(*Data) is then used to retrieve the real starting address, and the pointer is then moved to retrieve the slice array value

Get slice cap and len:

Get slice’s Data:

Welcome to the public account. HHFCodeRv