dongluoqiu0255 2015-04-27 03:32
浏览 55
已采纳

无法理解界面/结构关系

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?

  • 写回答

1条回答 默认 最新

  • doujin4031 2015-04-27 03:45
    关注

    Slices are not covariant; even though User implements Datatype, []User does not implement []Datatype (because nothing implements []Datatype: it itself is not an interface type, it's just a slice type whose element type is an interface type).


    Edited to add: As Dave C points out in a comment above, a closely-related question appears in the Go FAQ. [link] The Go FAQ is licensed in a way that's compatible with Stack Exchange content, so, here's the question in its entirety:

    Can I convert a []T to an []interface{}?

    Not directly, because they do not have the same representation in memory. It is necessary to copy the elements individually to the destination slice. This example converts a slice of int to a slice of interface{}:

    t := []int{1, 2, 3, 4}
    s := make([]interface{}, len(t))
    for i, v := range t {
        s[i] = v
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 无线电能传输系统MATLAB仿真问题
  • ¥50 如何用脚本实现输入法的热键设置
  • ¥20 我想使用一些网络协议或者部分协议也行,主要想实现类似于traceroute的一定步长内的路由拓扑功能
  • ¥30 深度学习,前后端连接
  • ¥15 孟德尔随机化结果不一致
  • ¥15 apm2.8飞控罗盘bad health,加速度计校准失败
  • ¥15 求解O-S方程的特征值问题给出边界层布拉休斯平行流的中性曲线
  • ¥15 谁有desed数据集呀
  • ¥20 手写数字识别运行c仿真时,程序报错错误代码sim211-100
  • ¥15 关于#hadoop#的问题