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 是一个很好的参考。
我有这段代码
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 是一个很好的参考。