Можно ли изменить члены структуры, хранящейся в пустом интерфейсе - PullRequest
0 голосов
/ 01 ноября 2018

У меня есть это:

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

Есть ли способ изменить pair.y член скопированной структуры в 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)

Обновление:

Я не собираюсь менять x.b, используя y. Я хочу изменить y поле b в одиночку.

Спасибо за вашу помощь, но это не простой вопрос о ценностях и ссылках.

Ответы [ 2 ]

0 голосов
/ 01 ноября 2018

Я нашел решение:

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}
}

Это действительно взломать.

Кто-нибудь может предложить более естественный / идиоматический?


Резюме:

  • присвоение конкретного значения пустому интерфейсу копирует значение
  • назначение пустого интерфейса другому пустому интерфейсу приводит к тому, что они разделяют одно и то же базовое значение
0 голосов
/ 01 ноября 2018

Вы должны знать указатель и адрес в первую очередь. Использование указателя может глубоко изменить значение. Если вы хотите, чтобы у y было то же значение, что и для x, они должны указывать на тот же адрес.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...