避免Go复制界面数据

时间:2015-04-17 08:39:07

标签: go reference pass-by-reference

这是我正在尝试编写的真实世界代码的一部分。问题是Go复制了接口sibling,所以我无法修改数据。但是,如果我改为使用指向接口的指针,那么相等的概念就会失败。我知道我可以使用DeapEquals,但不能使用地图。

package main

import (
    "fmt"
)

type Q interface {
    modify()
}

type P struct {
    name    string
    sibling Q
}

func (x P) modify() {
    x.name = "a"
}

func main() {
    a := P{"a", nil}
    A := P{"?", nil}

    b := P{"b", a}
    B := P{"b", A}

    B.sibling.modify()

    fmt.Println(B)
    fmt.Println(b == B)
}

如何让Go让我自己修改界面数据而不复制它并修改副本?

似乎这些在结构上是互斥的:

  • 我需要能够使用地图
  • 我需要能够使用方法
  • 修改界面数据

2 个答案:

答案 0 :(得分:3)

修改数据而不复制数据的唯一方法是使用指针。

我对你所说的内容感到有点困惑,因为你的例子使用了一个结构,然后你谈论了结构,但是你说你需要能够使用地图。无论哪种方式,DeepReflect都适用于这两种方式。 Here是您修改为使用指针的示例:

package main

import (
    "fmt"
    "reflect"
)

type Q interface {
    modify()
}

type P struct {
    name    string
    sibling Q
}

func (x *P) modify() {
    x.name = "a"
}

func main() {
    a := P{"a", nil}
    A := P{"?", nil}

    b := P{"b", &a}
    B := P{"b", &A}

    B.sibling.modify()

    fmt.Println("a:", a)
    fmt.Println("A:", A)
    fmt.Println("b:", b)
    fmt.Println("B:", B)
    fmt.Println(b == B)
    fmt.Println(reflect.DeepEqual(b, B))
}

打印:

a: {a <nil>}
A: {a <nil>}
b: {b 0x10436180}
B: {b 0x10436190}
false
true

你可以看到this帖子对地图做同样的事情。

答案 1 :(得分:0)

您可以使用modify()

返回的值
package main

import (
    "fmt"
)

type Q interface {
    modify() Q           //See here
}

type P struct {
    name    string
    sibling Q
}

func (x P) modify() Q{    //Here
    x.name = "a"
    return x
}

func main() {
    a := P{"a", nil}
    A := P{"?", nil}

    b := P{"b", a}
    B := P{"b", A}

    B.sibling=B.sibling.modify() //And here

    fmt.Println(B)
    fmt.Println(b == B)
}

它有点冗长,但至少有效https://play.golang.org/p/8oM90wriN0