Reflect.Value вопросы - PullRequest
       23

Reflect.Value вопросы

0 голосов
/ 27 сентября 2018

Пытаясь проверить эту бизнес-функцию:

//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)
            }
        })
    }

}

Человек, ответственный за исправление этих ошибок, понятия не имеет, чтовызывая ошибку, не говоря уже о том, как ее исправить, и ни я, ни старший разработчик.Итак, я попытался выделить проблему , чтобы попытаться ее идентифицировать.

То, что я думал, это было

Когда я регистрировал ошибки, я думал, что они были, потому что каким-то образом value сравнивался с reflect.Value, возвращеннымslice.Index(i).Я пытался

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

, но это не удалось.Единственный способ получить прохождение теста - это использовать Int() для извлечения значения и использовать

var i int64 = 3

вместо литерала 3, что является глупым af.

В чем проблема и как мы можем ее исправить?

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

Value.Index() возвращает reflect.Value.Сравнение с interface{}, которое вы получите, никогда не вернет true.Вам нужно сравнить с «реальным» значением, используя slice.Index(i).Interface().

Однако , вы тут возитесь с черной магией.Вам не хватает многих проверок безопасности - что если list на самом деле не является срезом или массивом?Что если value не относится к типу элементов list?Посмотрите на реализацию DeepEqual, чтобы увидеть, какие проверки вы можете выполнить для такой функции: https://golang.org/src/reflect/deepequal.go

0 голосов
/ 27 сентября 2018

Метод Index () возвращает отражение. Значение.Используйте метод Interface () этого значения , чтобы получить его базовое значение и сравнить с ним:

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
}
...