gpt4 book ai didi

go - 从接口(interface)获取结构值

转载 作者:IT王子 更新时间:2023-10-29 02:05:23 25 4
gpt4 key购买 nike

我正在尝试创建一个可以将多种类型的数据(用户、地址等)解析为结构的文件解析器。为此,我创建了一个名为 Datatype 的接口(interface):

package main

type Datatype interface {
name() string
}

还有几个实现接口(interface)的结构体:

例如

package maintype User struct {    Username    string `validate:"nonzero"`    FirstName   string `validate:"nonzero"`    LastName    string `validate:"nonzero"`    Email       string `validate:"regexp=^[0-9a-zA-Z]+@[0-9a-zA-Z]+(\\.[0-9a-zA-Z]+)+$"`    Phone       string `validate:"min=10"`    DateOfBirth string}type Users []Userfunc (u User) name() string {    return "user"}

I then read the filename, get the type of data it contains from the name of the file and create an instance of that struct to pass to the parser:

func Parsefile(file string, dtype Datatype) ([]Datatype, error) {   // Do stuff in here to parse the file

I did this hoping I could create a parse method that took any one of the structs, detect the type and unmarshall from the csv record. However, what I am finding is that I can't do it this was as I can't seem to get the the underlying type from the interface. Or at least not with my Unmarshall function:

func Unmarshal(reader *csv.Reader, v *Datatype) error {
record, err := reader.Read()
fmt.Println("Record: ", record)
if err != nil {
return err
}
s := reflect.ValueOf(v).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":
ival, err := strconv.ParseInt(record[i], 10, 0)
if err != nil {
return err
}
f.SetInt(ival)
default:
return &UnsupportedType{f.Type().String()}
}
}
return nil
}

在上面的函数中,当它遇到试图确定数据类型中的字段数的行时,出现以下错误:

panic: reflect: call of reflect.Value.NumField on interface Value

我知道我在这方面做得不好,我觉得必须有一种方法可以实现这种模式,而不必为每种数据类型编写特定的逻辑。然而,对于我的生活,我无法弄清楚如何在 go 中实现这一目标。

最佳答案

看来您正在尝试使用来自 this question 的 csv 解码代码.当您有一个特定类型的预分配结构要传递给它时,它就可以工作。您遇到问题是因为即使传入的特定值是结构,v 仍然是静态接口(interface)类型。

我建议在您的界面和每个子类型上放置一个 Unmarshal 方法:

func (u *User) populateFrom(reader *csv.Reader) string {
Unmarshal(reader, u)
}

go 中另一个很酷的东西是 type switch :

var i interface{}
switch t := v.(type) {
case *User:
i := t // i is now a *User.
case *Address:
i := t // i is now a *Address.
default:
panic("unknown type")
}
Unmarshal(reader,i)

关于go - 从接口(interface)获取结构值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29712513/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com