copy pointer values *a = *b in golang

huangapple go评论83阅读模式
英文:

copy pointer values *a = *b in golang

问题

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仍然为空,我必须这样做

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

现在ab是相同的

为什么我不能直接将*b复制到*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 is still empty, I have to do it like this

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

now a is the same as b

Why and how can I copy *b to *a directly?

答案1

得分: 98

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

如果你想将B的数据结构复制到A的数据结构中,请改用以下方式:

*a = *b;

正如dmikalova在下面的评论中指出的那样,这只是复制了结构体,但没有复制结构体指向的任何数据。如果你的结构体有一个指针,那么它指向的数据现在被这两个副本共享(因为它只复制了指针)。

从技术上讲,字符串始终是指针,因此它们永远不会作为结构体的一部分被复制。但是,由于字符串是不可变的(并且Go有垃圾回收机制),字符串“感觉”就像是结构体的一部分,你不必担心低级别的字符串共享,它会在你不用考虑的情况下神奇地节省内存。

英文:

Your first example is almost right. You pass in pointers to two objects. You put those pointers into variables A and B. But A and B are local variables, so when you say a=b you are merely saying "forget what was in A (locally)". The rest of the program still has pointers to those two original objects.

If you want to copy the data structure at B into the data structure at A, do this instead:

*a = *b;

As dmikalova pointed out in the comments below, this merely copies the structs -- but not any data the struct points to. If your struct has a pointer, the data it points to is now shared by the two copies (because it only copied the pointer).

Technically, strings are always pointers, so they are never copied as part of your struct. But because strings are immutable (and Go has Garbage Collection), strings "feel" like they are part of your struct, and you don't have to worry about the low-level string sharing that magically saves you memory without you having to think about it.

答案2

得分: 21

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

func Copy(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()
    }
}

所以:

Copy(old, new)

你可以在运行时传递任何类型,只要你确保source和destin都是相同类型(并且destin是该类型的指针)。

英文:

Generic solution for framework developers :

func Copy(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()
	}
}

So:

Copy(old, new)

<iframe src="http://play.golang.org/p/b1lylpDL98" frameborder="0" style="width: 100%; height: 100%"><a href="http://play.golang.org/p/b1lylpDL98">see this code in play.golang.org</a></iframe>
So you can pass any type at run time as long as you're sure that source and destin are both of the same type, (and destin is a pointer to that type).

答案3

得分: 16

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

而*T是指向T的指针。可以将其视为一个int,告诉你T所在的位置。
所以,"a"指向T的一个实例,而b指向另一个实例。

在你的复制函数中,你是在说让a指向b的"T"(如果这样说有意义的话)。
你想要的是说a的T应该与b的T相同。

你可以通过解引用指针来实现这一点。

所以,不要使用a = b(将我的局部变量"a"更改为指向"b"指向的内容),
而是使用*a = *b(将a的T更改为等于b的T)。

希望这样讲清楚了,下面是修改后的示例代码,以实现"正确的操作"。请注意,你的Copy函数在这里是不必要的,它只是为了说明。示例代码

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)
}
英文:

In go, arguments are passed by value.

and *T is a pointer to a T. Think of it as an int that tells you where that T is.
So, "a" points to one instance of T and b points to another.

in your copy function, you are saying make a point to b's "T" (if that made sense).
What you wanted was to say that a's T should be the same as b's T

You do that by dereferencing the pointers.

so, instead of a = b (change my local variable "a" to point to whatever "b" points to)
you use *a = *b (change a's T to be equal b's T)

Hopefully that made sense, here's an example of your app modified to "do the right thing". Note, your Copy function isn't necessary in this, it's there for illustration. Play example

import &quot;fmt&quot;

type T struct {
	Id   int
	Name string
}

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

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

	fmt.Println(a, b)
	Copy(a, b)
	fmt.Println(a, b)
	CopyThatActuallyCopies(a, b)
	fmt.Println(a, b)
}

答案4

得分: -4

这是错误的。它不起作用。

func (r *Request) WithContext(ctx context.Context) *Request {
  if ctx == nil {
    panic("nil context")
  }
  r2 := new(Request)
  *r2 = *r
  r2.ctx = ctx
  return r2
}
英文:

This is wrong.It does not work

func (r *Request) WithContext(ctx context.Context) *Request {
  if ctx == nil {
	panic(&quot;nil context&quot;)
  }
  r2 := new(Request)
  *r2 = *r
  r2.ctx = ctx
  return r2
}

huangapple
  • 本文由 发表于 2014年1月9日 11:14:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/21011023.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定