附加到切片的元素的地址

时间:2018-03-22 09:37:13

标签: pointers variables go slice

我想创建元素,将其添加到切片并按地址更改。我希望元素从外部的变化也会改变。但在添加之后,会创建一个新切片。我使用序列化,因此使用一片地址是不合适的,也会在不同的goroutine中添加元素,因此访问最后添加的元素也不合适。

package main

import (
    "fmt"
)

func main() {
    var a []int
    b := 1
    fmt.Println("old addr:", &b)
    // old addr: 0x10414020
    a = append(a, b)
    fmt.Println("new addr:", &a[0])
    // new addr: 0x10414028
}

play golang example

3 个答案:

答案 0 :(得分:3)

这不是append()创建新切片标头和支持数组的问题。

这是您将b附加到切片a的问题,将追加b变量值的副本。您附加,而不是变量!顺便说一句,追加(或分配)会附加(或分配)值的副本。

请注意,如果您不致电b,而是预先分配切片,只需将a[0]分配给{{1},append()b的地址也会有所不同}}:

a[0]

Go Playground上尝试。

这是因为变量var a = make([]int, 1) b := 1 fmt.Println("old addr:", &b) // old addr: 0x10414024 a[0] = b fmt.Println("new addr:", &a[0]) // new addr: 0x10414020 b是不同的变量;或者更准确地说,变量ab的后备数组为其元素保留了内存(包括a的内存空间),因此它们的地址不能相同!

您无法创建放置到另一个变量的同一内存位置的变量。为了达到这个“效果”,你手头有指针。您必须创建一个指针变量,您可以将其设置为指向另一个现有变量。通过访问和修改指向值,您可以有效地访问和修改存储在指针中的地址的变量。

如果你想在a[0]切片中存储“东西”,通过它可以访问和修改“局外人”a变量,最简单的方法是存储其地址,这将是类型b

示例:

*int

输出(在Go Playground上尝试):

var a []*int
b := 1
fmt.Println("b's addr:", &b)
a = append(a, &b)
fmt.Println("addr in a[0]:", a[0])

// Modify b via a[0]:
*a[0] = *a[0] + 1
fmt.Println("b:", b)

答案 1 :(得分:0)

引用程序行为完全正确 - 地址表示存储位置,b int是一个这样的位置,切片内的元素是另一个。

你很可能需要存储指针而不是int s。

现在关于序列化 - 我不确定你有什么样的想法,但总的来说你可以像下面这样进行:

type myArray []*int
var a myArray
//...

func (x myArray) Serialize() []byte { .... }

Serialize满足您的序列化器使用的接口。

答案 2 :(得分:0)

分配值始终允许运行时为复制的值分配新内存,并且分配的内存将具有另一个地址。如果附加到一片值,则始终复制变量。

如果必须访问来自不同go例程的元素,则必须使其成为线程安全的。无论您使用的是值还是引用,都必须这样做。