【Go夯实基础】slice

152 阅读1分钟

1、小问题

  • 注意
    • nil问题,renums的array指向的是实际存在的空数组地址,nums指向的是nil
    func main() { 
        var nums []int 
        renums := make([]int, 0) 
        if nums == nil { 
            fmt.Println("nums is nil.") 
        }
        if renums == nil {
            fmt.Println("renums is nil.") 
        }
    }
    //output
    nums is nil.
    
    • 容量问题
      • Slice array 指向所引用的 Array。因此在 Slice 上的变更。会直接修改到原始 Array 上(两者所引用的是同一个)
      • 假设插入后,原本数组的容量就超过最大值了,这时候内部就会重新申请一块内存空间,将原本的元素拷贝一份到新的内存空间上。此时其与原本的数组就没有任何关联关系了,再进行修改值也不会变动到原始数组

2、slice使用fmt.Printf("i:%p\n",i)

func main() {
   i := []int{1,2,3}
   fmt.Printf("i:%p\n",i)
   fmt.Println("i[0]:",&i[0])
}

//outpu
i:0xc04205e0c0
i[0]: 0xc04205e0c0
  • 可以看出来使用%p输出的内存地址与slice的第一个元素的地址是一样的

  • 源码,可以看出来,slice获取指针是获取struct里面的指向底层数组的Data

//fmt.Printf p
func (p *pp) fmtPointer(value reflect.Value, verb rune) {
   var u uintptr
   switch value.Kind() {
   case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
      u = value.Pointer()
   }
   switch verb {
   case 'p':
      p.fmt0x64(uint64(u), !p.fmt.sharp)
   }
}

//获取指针
func (v Value) Pointer() uintptr {
   k := v.kind()
   switch k {
   case Slice:
      return (*SliceHeader)(v.ptr).Data 
   }
   panic(&ValueError{"reflect.Value.Pointer", v.kind()})
}