hi, Hello, I'm hhf.
There is such a Go interview question: please tell the difference between slice and array?
This is simply a sub question. But how can you answer to the interviewer's satisfaction?
I won't post the answer to this question here. However, I want to briefly analyze the difference between slice and array in terms of memory.
Array
func main() { 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]) }
This very simple code declares an array. Of course, the output is simple enough.
Now let's play some flower work. How can we access the elements in the array by abnormal means? Before doing this, you need to know the underlying structure of array. In fact, it is very simple. Go array is a continuous memory space. As shown in the figure below
Write a simple piece of code. We don't get elements through subscript access. Obtain the pointer of the corresponding position by moving the pointer.
func main() { 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) }
result:
as[0]: 10 as[1]: 5 as[2]: 8 as[3]: 7
The following figure illustrates the process of obtaining the value of the corresponding position:
Slice
Similarly, for slice this simple code:
func main() { 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]) }
If you want to get the value of the corresponding position of slice by moving the pointer, you still need to know the underlying structure of slice. As shown in the figure:
func main() { 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) }
result:
as[0]: 10 as[1]: 5 as[2]: 8 as[3]: 7 len 4 cap 4
Using the pointer to get the elements in the underlying Data of slice is slightly different from array:
-
After taking the address of slice variable as, you get the address of SiceHeader. Move this pointer to get slice data, len and cap.
-
So when we get the value of Data, we get the value of the first address of the array pointed to by Data.
-
Since this value is a pointer, you need to get the pointer value of the real first address of the array for this value * Data
-
Then, for this value & (* data), get the real first address, and then move the pointer of this value to get the value in the slice array
Get slice cap and len:
Get slice Data:
Welcome to the official account. Learn more about learning materials and pay attention to the official account reply.
-
Reply to 0 and get the Go manual
-
Reply 1: get the Go source code flow chart