是否可以更改存储在空接口中的结构的成员

时间:2018-11-01 02:07:34

标签: go

我有这个:

type pair struct {
    a, b int
}

然后我定义两个变量:

x := pair{ 3, 4 }
var y interface{} = x

我意识到y并不存储x的引用,而是通过以下代码存储它的副本:

x.b = 7
fmt.Println(x)
fmt.Println(y)
// got:
// {3 7}
// {3 4}

另请参阅:https://github.com/golang/go/blob/master/src/runtime/iface.go#L359

有什么方法可以修改y中复制的结构的pair.y成员吗?

尝试过:(失败)

// cannot assign to y.(pair).b
y.(pair).b = 7

对此进行了尝试:(也失败了)

// panic: reflect: reflect.Value.SetInt using value obtained using unexported field
v := reflect.ValueOf(y).FieldByName("b")
v.SetInt(33)

将“ b”更改为“ B” :(也失败)

type pair {
    a, B int
}
// panic: reflect: reflect.Value.SetInt using unaddressable value
v := reflect.ValueOf(y).FieldByName("B")
v.SetInt(33)

更新:

我不会使用y更改x.b。我只想更改y的字段b

感谢您的帮助,但这不是关于值和引用的简单问题。

2 个答案:

答案 0 :(得分:-1)

首先需要知道指针和地址。使用指针可以深深地改变值。如果希望y与x具有相同的值,则它们需要指向相同的地址。

答案 1 :(得分:-2)

我找到了解决方法:

package main

import (
    "unsafe"
    "fmt"
)

type pair struct {
    a, b int
}

func main() {
    x := pair{ 3, 4 }
    var y interface{} = x
    var z interface{} = y

    // change x.b
    x.b = 7

    // change y.b
    addr := (*(*[2]uintptr)(unsafe.Pointer(&y)))[1]
    pp := (*pair)(unsafe.Pointer(addr))
    pp.b = 8

    fmt.Println(x) // {3 7}
    fmt.Println(y) // {3 8}
    fmt.Println(z) // {3 8}
}

这真的是黑客。

有人可以提供更自然/惯用的吗?


摘要:

  • 将具体值分配给空接口会复制该值
  • 将一个空接口分配给另一个空接口会导致它们共享相同的基础值