Добавить структуру или указатель на структуру в слайс - PullRequest
0 голосов
/ 02 декабря 2018

Скажем, у меня есть такие структуры:

type Foo struct {
  F string `zoom:"1"`
}

type Bar struct {
  F string `zoom:"2"`
}

type Baz struct {
  F string `zoom:"3"`
}

Скажем, я хотел создать функцию, которая может извлекать поле f из каждой структуры, это может выглядеть так:

func extractField(s []struct{}){
  for _, v := range s {
    t := reflect.TypeOf(v{})
    f, _ := t.FieldByName("F")
    v, ok := f.Tag.Lookup("zoom")
  }
}

Есть ли способ передать структуры в extractField?Если я сделаю это:

extractField([]struct{}{Foo, Bar, Baz})

Я получу эту ошибку:

Type Foo is not an expression
Type Bar is not an expression
Type Baz is not an expression

Я просто хочу передать 3 структуры в функцию extractField.

Ответы [ 3 ]

0 голосов
/ 02 декабря 2018

Общая проблема выглядит намного лучше для типа интерфейса.

type HasF interface {
    GetF() string
}

Определить эти методы достаточно просто, например

func (foo Foo) GetF() string { return foo.F }

Ваш метод итерации по ним становится почти тривиальным

func extractField(s []HasF) {
    for _, v := range s {
        fmt.Printf(v.GetF())
    }
}

func main() {
    extractField([]HasF{Foo{},Bar{},Baz{}})
}

https://play.golang.org/p/uw0T7TGVC0n имеет полную версию этого.

0 голосов
/ 02 декабря 2018

Исходный код выглядит так, как будто он придерживается подхода JavaScript, где функция будет мутировать объект.Go - это немного другое, где чаще всего происходит самовоспроизведение.

Например:

type Generic struct {
  field string
}

func (generic *Generic) Value () string {
  return generic.field
}

someObject := &Generic{
  field: "some value",
}

log.Print(someObject.Value()) // Outputs "some value"

Если вы пришли из мира JavaScript, подумайте немного о структурахкак объект / класс, который может содержать атрибуты и функции.Структуры являются просто определением, пока экземпляр не будет создан.Это отличается от JavaScript, где определение объекта и данных определяются одновременно.

Как указывает другой ответ, интерфейс является еще одним аналогичным подходом к решению этой проблемы.

Разъяснение

В терминах JavaScript OP пытается сделать что-то похожее на:

class Foo {...}
class Bar {...}
class Baz {...}

extractField(Foo, Bar, Baz)

В языке JS это передало бы определение класса вметод extractField.Вам все равно придется создавать экземпляр класса, если вы хотите манипулировать им или читать из него, например:

extractField(new Foo(), new Bar(), new Baz())

Это в основном то, что достигается с помощью

extractField([]interface{}{Foo{},Bar{},Baz{}})

Iдумаю, что проблема, с которой вы сталкиваетесь, заключается в том, что создаются структуры Foo / Bar / Baz, а вложенная структура F - нет.

0 голосов
/ 02 декабря 2018

Единственный способ выяснить, как это сделать, заключается в следующем:

type Foo struct {
    F string `zoom:"1"`
}

type Bar struct {
    F string `zoom:"2"`
}

type Baz struct {
    F string `zoom:"3"`
}


func extractField(s []interface{}){
    for _, v := range s {
        t := reflect.TypeOf(v)
        f, _ := t.FieldByName("F")
        v, ok := f.Tag.Lookup("zoom")
        fmt.Println(v,ok)
    }
}

func main(){

    extractField([]interface{}{Foo{},Bar{},Baz{}})  // <<<< here

}

не уверен, есть ли способ передать структуру без "ее инициализации".

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