I am having difficulty understanding the relationship between interfaces and structs in go. I have declared an interface called Datatype
as follows:
package main
type Datatype interface {
Unmarshal(record []string) error
String() string
}
I have also created several structs that implement this interface. Here is one simple example:
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]+@[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
}
Problem:
As you can see, I also have a type called Users
which is just []User
. When I try to return this type from a function that has a return type of []Datatype
, I get the following error message:
cannot use results (type Users) as type []Datatype in return argument
I'm sure I'm missing something obvious but it seems to me that this should work.
Question:
Could someone please explain why it does not work? Is there a better (more idiomatic) way to achieve this end result?