Хранить и получать интерфейсы в Голанге - PullRequest
0 голосов
/ 30 июня 2018

Как мы можем сохранить массив различных структур в некотором файле и получить его обратно в том же формате, не теряя его свойства (методы, которые он предоставляет).

Например: у меня есть данные struct A и struct B, оба реализуют общий interface X {} с некоторыми методами.

Один из вариантов - написать как метод сохранения, так и метод получения, чтобы принять фрагмент интерфейса X.

Однако проблема заключается в том, как восстановить его каким-то общим способом, который не привязан к моей структуре данных. то есть, каждый раз, когда я добавляю новую структуру данных, мне не нужно менять свои функции сохранения или извлечения для извлечения фрагмента интерфейса X, чтобы его методы могли использоваться независимо от структуры данных.

Пример, где Unmarshaling выбрасывает ошибку:

Go PlayGround Link с небольшим примером

Ответы [ 3 ]

0 голосов
/ 30 июня 2018

Однако проблема заключается в том, как восстановить его каким-то общим способом, не связанным с моей структурой данных.

Да, это невозможно отменить. Редизайн.

0 голосов
/ 01 июля 2018

Это проще, если вы думаете только о данных ...

Ваш X должен быть не интерфейсом, а структурой, чтобы вы могли его маршалировать.

Чтобы сделать процесс общим, вы можете считать, что X содержит выбор

type A struct {
    A int64
}

type B struct {
    S string
}

type Choice int

const (
    XisA Choice = iota
    XisB
)

type X struct {
    Choice
    A
    B
}

Перед маршалингом вам просто нужно установить выбор для каждого элемента вашего массива

a := A{
    A: 1,
}

b := B{
    S: "2",
}

x1 := X{
    Choice: XisA,
    A:      a,
}
x2 := X{
    Choice: XisB,
    B:      b,
}
x := [2]X{x1, x2}

После демаршаллинга вам просто нужно получить выбор, который вы сделали для каждого элемента массива

for _, item := range decoded {
    switch {
    case item.Choice == XisA:
        println(item.A.GetKey())
    case item.Choice == XisB:
        println(item.B.GetKey())
    }
}

Вот пример: https://play.golang.org/p/RtzF6DmNlKL

0 голосов
/ 30 июня 2018

Интересный вопрос, как говорит Волкель, нельзя отменить, как вы этого хотите. Но, как вы измените дизайн, есть возможности. Обычно старайтесь избегать использования отражения. Это не идиоматично, но очень мощно в конкретных случаях, и, может быть, это именно то, что вы ищете, особенно, часто не так много кандидатов на подходящие структуры, и вы можете оставить внутри своего приложения универсальный в своем параметре метод unmarshall, потому что процедура обнаружения типа находится внутри функции и не видна в вызове функции.

Так что иногда вы можете решить эту проблему, используя ее внутри функции UnMarshall.

if (f.Type() == reflect.TypeOf(Entity{})) {
  //reflected type is of type "Entity", you can now Unmarshal
}
...