golang中slice的地址

Address of slice in golang

我有这段代码

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)
    }
}

操场:https://play.golang.org/p/PWMN-i9_z9

我对循环底部第二个 Println 的问题。如果你 运行 它,你会看到它打印出 &[values...]。为什么它不打印出地址?我知道您可以使用 Printf 以及其他方法来完成它,并且它有效,但是 Println 呢?带有 &slice[0] 的 Println 工作正常,它打印地址而不是值,但是带有 &slice 的 Println 就像没有。

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

这就是 fmt.Println 的定义。

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

Println formats using the default formats for its operands and writes to standard output. Spaces are always added between operands and a newline is appended. It returns the number of bytes written and any write error encountered.

在该页面的前面,描述了默认格式:

For compound objects, the elements are printed using these rules, recursively, laid out like this:

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

也许你的问题是"why"是不是这样。答案值得商榷,但我想这是因为以这种形式而不是原始指针显示数据被认为更有用。

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