Используйте различные структуры в качестве значения на карте Голанга - PullRequest
0 голосов
/ 08 ноября 2018

Есть ли способ создать карту на несколько структур, а затем использовать ее?

У меня есть несколько различных структур, которые реализуют один и тот же интерфейс и соответствуют типам ввода для каждой структуры.

Я хочу прочитать данные из разных входов в структуры - не зная типа ввода во время компиляции.

type myInput struct {
    InputType  string
    data       []bytes
}

// Will get as an input after compeleation
inputs := []myInput{
    myInput{InputType: "a", data: []bytes{0x01, 0x02, 0x03}},
    myInput{InputType: "b", data: []bytes{0x01, 0x02}},
}

type StructA struct {
   A uint16
   B uint32
}

func (a StructA) name () {
    fmt.Printf("name is: %d %d", a.A, a.B)
}

type StructB struct {
   C uint32
}

func (b StructB) name () {
    fmt.Printf("name is: %d", b.C)
}

AorB map[string]<???> {
    "a": StructA,
    "b": StructB,
}

На данный момент, я не знаю, что делать. Мне нужно взять правильную структуру по типу ввода и инициализировать структуру, используя binary.Read.

for _, myInput := range (inputs) {
    // ???? :(
    myStruct := AtoB[myInput.InputType]{}
    reader :=bytes.NewReader(input1)
    err := binary.Read(reader, binary.BigEndian, &myStruct)
    fmt.Printf(myStruct.name())
}

Спасибо!

Ответы [ 3 ]

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

Определить интерфейс

type Bin interface {
    name() string
    set([]byte) // maybe returning error
}

Вы будете обрабатывать только Bin s.

type StructA struct { /* your code so far */ }
type StructB struct { /* your code so far */ }

func (a *StructA) set(b []byte) {
    a.A = b[0]<<8 + b[1] // get that right, too lazy to code this for you
    a.B = b[2]<<24 + b[3]<<16 + ...  
}
// same for StructB

Так что ваши StructA / B теперь являются бинами.

func makeBin(in myInput) Bin {
     var bin Bin
     if in.InputType == "a" {
         bin = &StructA{}
     } else {
         bin = &StructB{}
     }
     bin.set(in.data) // error handling?
     return bin
}

Если у вас более двух типов: используйте вместо этого переключатель, если if, или создайте крошечный реестр типов (отражите).

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

Сначала вы определяете interface для часто используемых func name:

type Namer interface {
    name()
}

Затем вы можете создать карту для этого интерфейса и вставить структуры:

AorB := map[string] Namer {
    "a": StructA{
        A: 42,
        B: 28,
    },
    "b": StructB{
        C: 12,
    },
}

Теперь вы можете получить доступ ко всем записям:

for _, n := range AorB {
    n.name()
} 
0 голосов
/ 08 ноября 2018

Вы можете использовать интерфейс для того же самого

AorB := map[string]interface{}{
    "a": StructA{},
    "b": StructB{},
} 

Когда вы возвращаете значение обратно, вы можете указать в A для типа A и B для типа B

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