代码之家  ›  专栏  ›  技术社区  ›  Atishay Jain

如何使用变量访问struct?

  •  -1
  • Atishay Jain  · 技术社区  · 7 年前

    我有这个功能 decodeUser . 我的任务是检查请求中是否存在密钥。这就是我所做的。我在错误处添加了一条注释。

    func decodeUser(r *http.Request) (root.User, []string, error) {
        var u root.User
        if r.Body == nil {
            return u, []string{}, errors.New("no request body")
        }
        decoder := json.NewDecoder(r.Body)
        checks := []string{
            "UserName",
            "FirstName",
            "LastName",
            "Email",
        }
        emptyFields := []string{}
        for _, check := range checks {
            // i'm having problem over here `u[check]` it's showing (invalid
               operation: u[check] (type root.User does not support 
               indexing))
            if u[check] == nil {
                emptyFields = append(emptyFields, check)
            }
        }
        err := decoder.Decode(&u)
        return u, emptyFields, err
    }
    

    以防我添加了root.User,这里是它的结构

    type User struct {
        ID                   string
        Username             string
        Password             string
        FirstName            string
        LastName             string
        Email                string
        PhoneNumber          string
        PhoneNumberExtension string
        DOB                  time.Time
        AboutMe              string
    }
    

    出现问题的原因是,它不允许我通过变量访问struct,并且我不能使用这个 u.check . 所以基本上 我该怎么做 u[check] 工作

    2 回复  |  直到 7 年前
        1
  •  0
  •   ssemilla    7 年前

    我建议您手动检查零值,因为您似乎已经知道编译时需要非零值的字段。然而,如果不是这样,这里有一个简单的函数(使用反射),它将检查结构中的零值。

    func zeroFields(v interface{}, fields ...string) []string {
    
        val := reflect.Indirect(reflect.ValueOf(v))
        if val.Kind() != reflect.Struct {
            return nil
        }
    
        var zeroes []string
    
        for _, name := range fields {
    
            field := val.FieldByName(name)
    
            if !field.IsValid() {
                continue
            }
    
            zero := reflect.Zero(field.Type())
            // check for zero value
            if reflect.DeepEqual(zero.Interface(), field.Interface()) {
                zeroes = append(zeroes, name)
            }
    
        }
    
        return zeroes
    }
    
    func main() {
    
        x := User{
            Email: "not@nil",
        }
    
        fmt.Println(zeroFields(&x, "ID", "Username", "Email", "Something", "DOB"))
    }
    

    这将产生:

    [ID Username DOB]
    

    Playground

        2
  •  0
  •   Atishay Jain    7 年前

    for _, check := range checks {
        temp := reflect.Indirect(reflect.ValueOf(&u))
        fieldValue := temp.FieldByName(string(check))
        if (fieldValue.Type().String() == "string" && fieldValue.Len() == 0) || (fieldValue.Type().String() != "string" && fieldValue.IsNil()) {
            fmt.Println("EMPTY->", check)
            emptyFields = append(emptyFields, check)
        }
    }