Reflect.Value 个问题

Reflect.Value issues

在尝试测试此业务功能时:

//IsInSlice works like Array.prototype.find in JavaScript, except it
// returns -1 if `value` is not found. (Also, Array.prototype.find takes
// function, and IsInSlice takes `value` and `list`)
func IsInSlice(value interface{}, list interface{}) int {
    slice := reflect.ValueOf(list)

    for i := 0; i < slice.Len(); i++ {
        if slice.Index(i) == value {
            return i
        }
    }
    return -1
}

我发现它没有通过我的合理性测试:

func TestIsInSlice(t *testing.T) {
    digits := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    slice := digits[3:8] // returns {3,4,5,6,7}

    type args struct {
        value interface{}
        list  interface{}
    }
    tests := []struct {
        name string
        args args
        want int
    }{
        {
            name: "SanityTest",
            args: args{value: 3,
                list: []int{3, 4, 5, 6, 7},
            },
            want: 0,
        },
        {
            name: "ElementAtEnd",
            args: args{
                value: 5,
                list:  slice,
            },
            want: 3,
        },
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            if got := IsInSlice(tt.args.value, tt.args.list); got != tt.want {
                t.Errorf("IsInSlice() = %v, want %v", got, tt.want)
            }
        })
    }

}

负责修复这些错误的人不知道是什么导致了错误,更不用说如何修复了,我和高级开发人员也不知道。所以,我尝试 isolate the problem 来尝试识别它。

我以为是什么

当我记录错误时,我认为它们是因为不知何故,valueslice.Index(i) 返回的 reflect.Value 进行了比较。我试过了

reflect.DeepEqual(slice.Index(i), value)

但是那失败了。我可以通过测试的唯一方法是使用 Int() 提取值并使用

var i int64 = 3

而不是文字 3,它是片状的 af。

问题是什么以及我们如何解决它?

Index() methodreturns一个reflect.Value。 使用该值的 Interface() method 获取其基础值并与之比较:

func IsInSlice(value interface{}, list interface{}) int {
    slice := reflect.ValueOf(list)
    for i := 0; i < slice.Len(); i++ {
        if slice.Index(i).Interface() == value {
            return i
        }
    }
    return -1
}

Value.Index()return一个reflect.Value。将此与您收到的 interface{} 进行比较 永远不会 return 正确。您需要使用 slice.Index(i).Interface().

与 "real" 值进行比较

但是,你在搞黑魔法。您错过了很多安全检查 - 如果 list 实际上不是切片或数组怎么办?如果 valuelist 的元素类型不同怎么办?看一下 DeepEqual 的实现,了解您可能希望为这样的函数执行的检查类型:https://golang.org/src/reflect/deepequal.go