数组与切片

4个月前 阅读 252 评论 1 赞 0

提问:Golang中数组与切片的区别是什么?
回答:数组是值类型,切片是引用类型。


这样的回答不是最全面的,但是是最核心和最本质的。随着学习的深入,我们要学会抓住问题的本质。切片在底层也是通过数组实现的,可以说它们是同一种数据结构。本质的区别就在于数组是值类型,而切片是引用类型。

本质上来说,我们要理解的是值类型和引用类型的区别。这一点并不难,引用类型本质上就是指针。所以在参数传递和赋值的时候,值类型会将它占用的内存复制一份,而引用类型只会复制指向这片内存的指针。

这就好比北京的中国银行要向上海的中国银行汇一笔黄金。可以用一辆武装押运车将黄金从北京运到上海,更简单的方式是开一张支票就完了。引用就相当于这张支票。

本质上来说,引用也是值。因为在传递引用的时候,引用本身也会被复制一份。引用所持有的地址也就被复制了一份,但是由于引用持有的地址没变,所以我们还能访问到正确的内存,并改变那里存储的值。在Golang中我们很容易证明这一点。

  1. package main
  2. import(
  3. "fmt"
  4. )
  5. func printAddr (p []int) {
  6. fmt.Printf("[printAddr] %p\n", &p)
  7. }
  8. func main(){
  9. i := []int{1,2,3}
  10. fmt.Printf("[ main ] %p\n", &i)
  11. printAddr(i)
  12. }

切片i是一个引用,当把它传递给函数printAddr是,这个引用会被复制一份,因此两次打印出的地址应该是不同的,结果证明了这一点。

  1. [ main ] 0xc04204a3a0
  2. [printAddr] 0xc04204a3e0

值类型与引用类型的另一个广为人知的区别就是:值类型的空值是对应的零值,引用类型的空值是nil,也就是空指针。

这就意味着当你声明了一个值类型的变量时,同时也为这个变量分配了内存空间,以后可以直接使用它。但是声明一个引用类型变量只会分配引用本身所在占的空间,这个空间中存储了一个空指针,并没有分配存储真正值的空间。所以在Golang中,引用类型一般要先初始化,然后才能使用。

以货币发行为例,如果以黄金作为储备来发行货币,那么货币与财富就是对应的,货币就等于财富。但是,如果不以任何金属或物质作为储备而随意发行货币,这时货币将不能代表财富,与一张纸没有任何区别。

你的支持将鼓励作者继续创作

评论(1)

引用内容:

  • package main
  • import(
  • "fmt"
  • )
  • func printAddr (p []int) {
  • fmt.Printf("[printAddr] %p\n", &p)
  • }
  • func main(){
  • i := []int{1,2,3}
  • fmt.Printf("[ main ] %p\n", &i)
  • printAddr(i)
  • 空间吧

    1个月前