Go 使用reflect比较结构字段

Go 使用reflect比较结构字段,go,Go,我正在尝试对结构进行更新,以便在PUT API中使用。我需要找出新结构中的字段是否与旧结构中的同一字段具有不同的值。我以前从未使用过reflect,所以我有点困惑。这是我的代码,我希望它只打印不同的字段,但它打印每个字段 package main import ( "fmt" "reflect" ) type Permission struct { User int `json:"user" db:"user"` ObjectId int

我正在尝试对结构进行更新,以便在PUT API中使用。我需要找出新结构中的字段是否与旧结构中的同一字段具有不同的值。我以前从未使用过reflect,所以我有点困惑。这是我的代码,我希望它只打印不同的字段,但它打印每个字段

package main

import (
    "fmt"
    "reflect"
)

type Permission struct {
    User       int    `json:"user" db:"user"`
    ObjectId   int    `json:"object_id" db:"object_id"`
    ObjectType string `json:"object_type" db:"object_type"`
    Permission string `json:"codename" db:"codename"`
}

func main() {
    old := Permission{1, 1, "site", "view_site"}
    new := Permission{1, 2, "site", "edit_site"}
    v1 := reflect.ValueOf(old)
    v2 := reflect.ValueOf(new)
    t := reflect.TypeOf(old)
    for i := 0; i < v1.NumField(); i++ {
        if v2.Field(i) != v1.Field(i) {
            fmt.Printf("%v ", t.Field(i).Name)
            fmt.Printf("old: %v ", v1.Field(i))
            fmt.Printf("new: %v ", v2.Field(i))
            fmt.Println("")
        }
    }
}
主程序包
进口(
“fmt”
“反映”
)
类型权限结构{
User int`json:“User”db:“User”`
ObjectId int`json:“object\u id”db:“object\u id”`
ObjectType字符串`json:“对象类型”db:“对象类型”`
权限字符串`json:“codename”db:“codename”`
}
func main(){
旧:=权限{1,1,“站点”,“查看站点”}
新:=权限{1,2,“站点”,“编辑站点”}
v1:=反射值(旧)
v2:=反射值(新)
t:=反射.类型(旧)
对于i:=0;i

我想这是因为每个
值都是不同的结构,因此它们不相等,但我似乎无法确定如何实际执行我需要执行的操作。

请记住反射值和基础结构字段值之间的差异。这一行:

v2.Field(i) != v1.Field(i)
将一个结构的反射字段与另一个结构的反射字段进行比较。不是字段值,而是字段本身的反射。要获取这些值,您需要使用
Field(i).Interface()
,它将字段的值作为
接口{}
返回


您可以在这里看到一个工作示例:

Ha!我知道我错过了一些简单的事情。我如何处理我的结构有其他结构作为成员的情况?(特别是数据库/sql中的空类型)它是反射,所以很复杂。如果要查找特定类型的特定处理,可以使用类型断言或类型切换从
Interface()
返回的值。对于更通用的处理,您可以检查字段的
Kind()
,如果它是一个结构,则递归地处理它。对于涉及反射的任何内容,我强烈建议您寻找替代设计。反射应该是最后的解决方案。在基本库中似乎有大量的反射使用,编码和数据库包似乎都大量使用反射,用于类似于我上面提到的目的。如果我的问题域涉及序列化和从数据库读取,我不确定我是否能想出更好的设计。考虑到这个用例,我想说的是,在使用反射和编写一个帮助程序以使用
go generate
为每种类型生成静态类型的代码之间是一个两难的选择。如果性能有任何问题,后者可能更可取,但YMMV。