Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Pointers 附加到片的元素的地址_Pointers_Variables_Go_Slice - Fatal编程技术网

Pointers 附加到片的元素的地址

Pointers 附加到片的元素的地址,pointers,variables,go,slice,Pointers,Variables,Go,Slice,我想创建元素,将其添加到切片中,并根据其地址对其进行更改。我希望元素从外部的变化也会改变一个片段。但是在添加之后,会创建一个新的切片。我使用序列化,所以使用一个地址片是不合适的,而且元素的添加发生在不同的goroutine中,所以访问最后添加的元素也是不合适的 package main import ( "fmt" ) func main() { var a []int b := 1 fmt.Println("old addr:", &b) /

我想创建元素,将其添加到切片中,并根据其地址对其进行更改。我希望元素从外部的变化也会改变一个片段。但是在添加之后,会创建一个新的切片。我使用序列化,所以使用一个地址片是不合适的,而且元素的添加发生在不同的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
}

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

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

现在,关于序列化,我不确定您的想法是什么,但一般来说,您可以按照以下方式进行:

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

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

其中,
Serialize
满足序列化程序使用的接口。

这不是创建新切片标头和备份数组的问题

这是将
b
附加到切片
a
的问题,将附加
b
变量值的副本。您可以附加一个值,而不是一个变量!顺便说一下,追加(或赋值)会生成所追加(或赋值)值的副本

请注意,如果您不调用
append()
,而是预先分配片并将
b
分配给
a[0]
,则
b
a[0]
的地址也将不同:

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
a
是不同的变量;或者更准确地说,变量
b
a
的后备数组为其元素保留内存(包括
a[0]
的内存空间),因此它们的地址不能相同

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

如果要将“某物”存储在
a
切片中,通过该切片可以访问和修改“outsier”
b
变量,最简单的方法是存储其地址,其类型为
*int

例如:

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)
输出(在上尝试):


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


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

只需使用指针片段var a[]*int示例—正如@Uvelichitel所指出的—也可以使用指针片段;但是,OP必须确保它们确实有几个不同的
b
s将它们的地址放入该片中。谢谢,我必须使用指针数组并重写序列化。
b's addr: 0x10414020
addr in a[0]: 0x10414020
b: 2