复制golang中的指针值*a=*b

复制golang中的指针值*a=*b,go,Go,a仍然是空的,我必须这样做 type T struct { Id int Name string } func Copy(a *T, b *T) error { b.Id=5 b.Name="gert" a = b return nil } 现在a与b 为什么以及如何将*b直接复制到*a?您的第一个示例几乎是正确的。您传入指向两个对象的指针。你把这些指针放在变量A和B中。但是A和B是局部变量,所以当你说A=B时,你只是说“忘记A(局部)中的内容

a
仍然是空的,我必须这样做

type T struct {
    Id int
    Name string
}

func Copy(a *T, b *T) error {
    b.Id=5
    b.Name="gert"
    a = b
    return nil
}
现在
a
b


为什么以及如何将
*b
直接复制到
*a

您的第一个示例几乎是正确的。您传入指向两个对象的指针。你把这些指针放在变量A和B中。但是A和B是局部变量,所以当你说
A=B
时,你只是说“忘记A(局部)中的内容”。程序的其余部分仍然有指向这两个原始对象的指针

如果要将B处的数据结构复制到A处的数据结构,请执行以下操作:

func Copy(a *T, b *T) error {
    b.Id = 5
    b.Name = "gert"
    a.Id = b.Id
    a.Name = b.Name
    return nil
}
正如dmikalova在下面的评论中指出的那样,这只是复制结构——而不是结构指向的任何数据。如果您的结构有一个指针,那么它指向的数据现在由两个副本共享(因为它只复制了指针)


从技术上讲,字符串始终是指针,因此它们永远不会作为结构的一部分进行复制但是因为字符串是不可变的(Go有垃圾收集),字符串“感觉”就像是结构的一部分,您不必担心低级字符串共享会神奇地节省内存,而无需考虑它。

在Go中,参数是按值传递的

*T是一个指向T的指针。把它想象成一个int,告诉你T在哪里。 所以,“a”指向T的一个实例,b指向另一个实例

在你的复制函数中,你说的是指向b的“T”(如果有意义的话)。 你想说的是a的T应该和b的T一样

您可以通过取消对指针的引用来实现这一点

因此,代替a=b(将局部变量“a”更改为指向“b”指向的任何对象) 使用*a=*b(将a的T更改为等于b的T)

希望这是有意义的,这里有一个例子,你的应用程序修改为“做正确的事情”。请注意,您的复制功能在这里不是必需的,它只是用于演示


框架开发人员的通用解决方案:

import "fmt"

type T struct {
    Id   int
    Name string
}

func Copy(a *T, b *T) error {
    b.Id = 5
    b.Name = "gert"
    a = b
    return nil
}
func CopyThatActuallyCopies(a *T, b *T) error {
    b.Id = 5
    b.Name = "gert"
    *a = *b
    return nil
}

func main() {
    var a = &T{1, "one"}
    var b = &T{2, "two"}

    fmt.Println(a, b)
    Copy(a, b)
    fmt.Println(a, b)
    CopyThatActuallyCopies(a, b)
    fmt.Println(a, b)
}
因此:


因此,您可以在运行时传递任何类型,只要您确定source和destin都是同一类型(destin是指向该类型的指针)。

这是错误的。它不起作用

CloneValue(old, new)

lol:)尝试了
a=*b
*a=b
,而我在标题中键入的东西
*a=*b
我不是在复制数据结构,或者只是将指针a设置为指向与指针b相同的位置?完成此任务后,a是否也会更改b?如果是这样,那不是抄袭,而是简单的作业。读我写的
*a=*b
正在将数据从一个结构(由b指向)的内存复制到另一个结构(由a指向)的数据上。它们继续保留在内存的不同区域,因此更新不会传播。@NielsAbildgaard您从
a!=b
根据假设,因此
*a
*b
位于内存中的不同位置。赋值
*a=*b
不会修改
a
b
,因此您最终得到
*a==*b
,但仍然有
a!=b
。这可能会让您感到惊讶,因为它是一个浅拷贝—因此,如果b上的任何字段都是指针,那么这些指针将被复制到a。任何地图或结构都不会被深度复制。你可以在投票否决之前对其进行测试。投票否决可能是因为使用了reflect,我仍然认为它不应该被否决,所以我再次投票对其进行补偿,但可能会添加更多的文字,这不是推荐的方式,只有关于指针的额外信息。除非source和destin都是指针(如果要更新函数外部的值,destin需要是指针),否则此代码不起作用。您可以通过使用
reflect.ValueOf(destin).Elem().Set(x)
而不是
destin=x.Interface()
来修复代码,使源代码不成为指针。上述代码的工作版本:。仍然需要更多的错误检查(例如检查两者是否为同一类型)。示例在
CloneValue(old,5)
@zerkms时会出现恐慌:在这种情况下它应该会恐慌。在使用它之前,您应该注意先决条件。当您不知道要克隆的结构类型(在运行时)时,应该使用此解决方案,但不应该让应用程序的状态无效。这里的无效是指你的参数不同的情况。你应该考虑添加更多的解释,因为它是,响应看起来不清楚。请给你的解决方案添加解释。给出解决方案而不解释是没有用的。Golang核心语言只提供硬拷贝方式:
*a=*b
。如果有人想要一种更常用的面向对象的样式(例如克隆的行为是对象类型特定的),请参阅我在上提出的问题
func CloneValue(source interface{}, destin interface{}) {
    x := reflect.ValueOf(source)
    if x.Kind() == reflect.Ptr {
        starX := x.Elem()
        y := reflect.New(starX.Type())
        starY := y.Elem()
        starY.Set(starX)
        reflect.ValueOf(destin).Elem().Set(y.Elem())
    } else {
        destin = x.Interface()
    }
}
CloneValue(old, new)
func (r *Request) WithContext(ctx context.Context) *Request {
  if ctx == nil {
    panic("nil context")
  }
  r2 := new(Request)
  *r2 = *r
  r2.ctx = ctx
  return r2
}