golang中切片的地址

时间:2015-03-23 04:59:38

标签: pointers go slice

我有这段代码

package main

import (
    "fmt"
)

func Extend(slice []int, element int) []int {
    n := len(slice)
    if n == cap(slice) {
        // Slice is full; must grow.
        // We double its size and add 1, so if the size is zero we still grow.
        newSlice := make([]int, len(slice), 2*len(slice)+1)
        copy(newSlice, slice)
        slice = newSlice
    }
    slice = slice[0 : n+1]
    slice[n] = element
    return slice
}

func main() {
    slice := make([]int, 0, 5)
    for i := 0; i < 10; i++ {
        slice = Extend(slice, i)
        fmt.Printf("len=%d cap=%d slice=%v\n", len(slice), cap(slice), slice)
        fmt.Println("address of 0th element:", &slice[0])
        fmt.Println("address of slice:", &slice) // why does this print the slice and not its address?
        fmt.Printf("address of slice: %p\n", &slice) // why is this different from below? and why does it not change when a new slice is created pointing to a different array?
        fmt.Printf("address of slice: %p\n\n", slice)
    }
}

playground:https://play.golang.org/p/PWMN-i9_z9

关于循环底部第二个Println的问题。如果你运行它,你会看到它打印出来&amp; [values ...]。为什么不打印地址?我知道你可以用Printf等方式做到这一点,并且它有效,但Println怎么样?带有&amp; slice [0]的Println工作正常,它打印的地址不是值,但带有&amp; slice的Println就像nope。

我还注意到,当我使用&amp; slice执行Printf语句%p时,我只进行切片,得到不同的地址。为什么?带有&amp; slice的地址在更改时不会改变(运行它,程序调整数组大小并创建一个新切片)。但是printf(%p,slice)确实发生了变化吗?

1 个答案:

答案 0 :(得分:4)

fmt.Println的定义是什么。

来自https://golang.org/pkg/fmt/#Println

  

Println格式使用其操作数的默认格式并写入标准输出。始终在操作数之间添加空格,并附加换行符。它返回写入的字节数和遇到的任何写入错误。

早些时候在该页面上,描述了默认格式:

  

对于复合对象,使用这些规则以递归方式打印元素,如下所示:

struct:             {field0 field1 ...}
array, slice:       [elem0 elem1 ...]
maps:               map[key1:value1 key2:value2]
pointer to above:   &{}, &[], &map[]

也许你的问题是&#34;为什么&#34;是这样的吗?答案是值得商榷的,但我认为这是因为以这种形式显示数据而不是原始指针被认为更有用。

您还要问为什么修改切片不会更改其地址。切片是一种值类型(不是引用类型),它包含指向底层数组的指针(以及它的容量和当前长度)。为切片类型的变量分配新值会覆盖该值,但不会更改其地址。 This article on slice use and internals是一个很好的参考。