【问题标题】:Avoiding Go copying interface data避免 Go 复制接口数据
【发布时间】:2015-06-24 00:21:12
【问题描述】:

这是我正在尝试编写的真实世界代码的一部分。问题是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让我自己修改界面数据而不复制和修改副本?

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

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

【问题讨论】:

    标签: go reference pass-by-reference


    【解决方案1】:

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

    我对您所说的有点困惑,因为您的示例使用了结构并且您谈到了结构,但是您说您需要能够使用地图。无论哪种方式,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 发布的关于对地图执行相同操作的帖子。

    【讨论】:

      【解决方案2】:

      您可以使用从 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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-09-15
        • 1970-01-01
        • 1970-01-01
        • 2016-09-06
        • 1970-01-01
        • 2016-12-28
        • 2014-10-13
        相关资源
        最近更新 更多