Slice 如何获取底层数组内容

47 阅读1分钟

一、来源

本文来源与将切片传递到子函数中对其进行append。发现在主函数中切片未被修改。而我又对切片结构深信不移,底层数组一定被修改。所以想办法获取底层数组值证明我猜想

二、代码验证

1 初始代码

package main
import (
    "fmt"
    "reflect"
    "unsafe"
    )
func main() {
    res := make([]int,0,100)
    for i:=0;i<5;i++ {
        res = append(res, i)
    }
    PringSliceStruct(&res) // 0,1,2,3,4
    addNumToRes(res)
    PringSliceStruct(&res) //0,1,2,3,4
                           // 不应该是上面的结果,应该是0,1,2,3,4,5,6,7,8,9?我疑问?
    addNumToRes2(res)
    PringSliceStruct(&res) //100,101,102,103,104
}
func addNumToRes(res []int) {
    for i:=10;i<20;i++ {
        res = append(res, i)
    }
   PringSliceStruct(&res) // 0,1,2,3,4,5,6,7,8,9
}
func addNumToRes2(res []int) {
    for i:=0;i<10;i++ {
        res[i]= i+100
    }
    PringSliceStruct(&res)//100,101,102,103,104
}


func PringSliceStruct(s *[]int) {
	ss := (*reflect.SliceHeader)(unsafe.Pointer(s))
	fmt.Printf("slice struct:%+v, slice is %v\n", ss, s)
}

2、换方法打印

package main
import (
    "fmt"
    "reflect"
    "unsafe"
    )
func main() {
    res := make([]int,0,100)
    for i:=0;i<10;i++ {
        res = append(res, i)
    }
    addNumToRes(res)
    fmt.Println(res)
    
	// 通过反射获取切片的底层数组地址
    //  通过内存地址+元素长度打印出所有值
	sliceValue := reflect.ValueOf(res)
	arrayAddr := unsafe.Pointer(sliceValue.Pointer())
	for i := 0; i < 25; i++ {
		elementAddr := unsafe.Pointer(uintptr(arrayAddr) + uintptr(i)*unsafe.Sizeof(res[0]))
		element := *(*int)(elementAddr)
		fmt.Println("Element", i, ":", element)
	}
   
}
func addNumToRes(res []int) {
    for i:=10;i<20;i++ {
        res = append(res, i)
    }
}

// 输出
// [0 1 2 3 4]
//Element 0 : 0
//Element 1 : 1
//Element 2 : 2
//Element 3 : 3
//Element 4 : 4
//Element 5 : 5
//Element 6 : 6
//Element 7 : 7

三、总计

slice传递是值传递,但是底层数组不变。仍然被修改 但是主函数中slice的len固定,只能获取到一段,所以打印的数据没有变化