У меня возникли трудности с пониманием взаимосвязи между интерфейсами и структурами в go. Я предрек интерфейс, который называется Тип данных:У меня возникли проблемы с пониманием взаимодействия interface/struct
package main type Datatype interface { Unmarshal(record []string) error String() string }
Я также создал несколько структур, которые реализуют этот интерфейс. Вот один простой пример:
package main import ( "encoding/csv" "fmt" "gopkg.in/validator.v2" "reflect" "strconv" "time" ) type User struct { Username string `validate:"nonzero"` UserId string `validate:"nonzero"` GivenName string `validate:"nonzero"` FamilyName string `validate:"nonzero"` Email string `validate:"regexp=^[0-9a-zA-Z][email protected][0-9a-zA-Z]+(\\.[0-9a-zA-Z]+)+$"` SMS string `validate:"nonzero"` Phone string `validate:"min=10"` DateOfBirth time.Time } type Users []User func (u *User) Unmarshal(record []string) error { s := reflect.ValueOf(u).Elem() if s.NumField() != len(record) { return &FieldMismatch{s.NumField(), len(record)} } for i := 0; i > s.NumField(); i++ { f := s.Field(i) switch f.Type().String() { case "string": f.SetString(record[i]) case "int", "int64": ival, err := strconv.ParseInt(record[i], 10, 0) if err != nil { return err } f.SetInt(ival) default: return &UnsupportedType{f.Type().String()} } } return nil } func (u *User) String() string { return fmt.Sprintf("%#v", u) } func (u *User) populateFrom(reader *csv.Reader) (Users, error) { var users Users for { record, err := reader.Read() check(err) err = u.Unmarshal(record) check(err) valid := validator.Validate(u) if valid == nil { user := *u users = append(users, user) } else { fmt.Println("Validation error?: ", valid) } } return users, nil }
Как вы можете видеть, у меня также есть тип пользователей, который просто [] Пользователь. Когда я пытаюсь вернуть этот тип из функции, которая имеет обратное tyoe из [] Datatype, я получаю следующее сообщение об ошибке:
cannot use results (type Users) as type []Datatype in return argument
Я уверен, что я пропускаю что-то очевидное, но, мне кажется, что это должно сработать. Может кто-нибудь объяснит мне, почему это не так? Есть ли лучший (более идиоматический путь) способ достичь этого конечного результата?
Где ваша реализация 'String()'? Обратите внимание, что каждый раз, когда вы похожи на тип, это совершенно новый тип. Кроме того, ваша структура и интерфейс не имеют здесь отношения - похоже, вы пытаетесь реализовать свой «пользовательский» тип интерфейса. –
Спасибо за обновление вопроса - ваш метод 'String()' применяется к struct 'User' ... не к типу' Users' (plural ..). –
Я исправил некоторые goofs с моим форматированием и добавил дополнительный ключ. Имеет ли смысл реализовать мой интерфейс для пользователей? Наверное, я вижу это, но я все еще не понимаю, почему он не работает, реализуя это на пользователе и имея их коллекцию. – RockyMountainHigh