这个函数在哪里返回非错误值?

huangapple go评论91阅读模式
英文:

Where does this function return non error?

问题

我正在构建一个围绕数据存储的GetAll函数的封装,但是我很难找到这个函数在哪里返回非错误的情况。在我看来,除非有其他错误(例如在Done时发生错误),否则它会返回errFieldMismatch,我认为这是不正确的。

func (q *Query) GetAll(c context.Context, dst interface{}) ([]*Key, error) {
    var (
        dv               reflect.Value
        mat              multiArgType
        elemType         reflect.Type
        errFieldMismatch error
    )
    if !q.keysOnly {
        dv = reflect.ValueOf(dst)
        if dv.Kind() != reflect.Ptr || dv.IsNil() {
            return nil, ErrInvalidEntityType
        }
        dv = dv.Elem()
        mat, elemType = checkMultiArg(dv)
        if mat == multiArgTypeInvalid || mat == multiArgTypeInterface {
            return nil, ErrInvalidEntityType
        }
    }

    var keys []*Key
    for t := q.Run(c); ; {
        k, e, err := t.next()
        if err == Done {
            break
        }
        if err != nil {
            return keys, err
        }
        if !q.keysOnly {
            ev := reflect.New(elemType)
            if elemType.Kind() == reflect.Map {
                // This is a special case. The zero values of a map type are
                // not immediately useful; they have to be make'd.
                //
                // Funcs and channels are similar, in that a zero value is not useful,
                // but even a freshly make'd channel isn't useful: there's no fixed
                // channel buffer size that is always going to be large enough, and
                // there's no goroutine to drain the other end. Theoretically, these
                // types could be supported, for example by sniffing for a constructor
                // method or requiring prior registration, but for now it's not a
                // frequent enough concern to be worth it. Programmers can work around
                // it by explicitly using Iterator.Next instead of the Query.GetAll
                // convenience method.
                x := reflect.MakeMap(elemType)
                ev.Elem().Set(x)
            }
            if err = loadEntity(ev.Interface(), e); err != nil {
                if _, ok := err.(*ErrFieldMismatch); ok {
                    // We continue loading entities even in the face of field mismatch errors.
                    // If we encounter any other error, that other error is returned. Otherwise,
                    // an ErrFieldMismatch is returned.
                    errFieldMismatch = err
                } else {
                    return keys, err
                }
            }
            if mat != multiArgTypeStructPtr {
                ev = ev.Elem()
            }
            dv.Set(reflect.Append(dv, ev))
        }
        keys = append(keys, k)
    }
    return keys, errFieldMismatch
}
英文:

I'm building a wrapper around the datastore GetAll function and I have a hard time finding where this function returns a non-error. It seems to me that unless there is any other error (i.e. when it breaks on Done) it returns errFieldMismatch which I think is not correct.

func (q *Query) GetAll(c context.Context, dst interface{}) ([]*Key, error) {
var (
dv               reflect.Value
mat              multiArgType
elemType         reflect.Type
errFieldMismatch error
)
if !q.keysOnly {
dv = reflect.ValueOf(dst)
if dv.Kind() != reflect.Ptr || dv.IsNil() {
return nil, ErrInvalidEntityType
}
dv = dv.Elem()
mat, elemType = checkMultiArg(dv)
if mat == multiArgTypeInvalid || mat == multiArgTypeInterface {
return nil, ErrInvalidEntityType
}
}
var keys []*Key
for t := q.Run(c); ; {
k, e, err := t.next()
if err == Done {
break
}
if err != nil {
return keys, err
}
if !q.keysOnly {
ev := reflect.New(elemType)
if elemType.Kind() == reflect.Map {
// This is a special case. The zero values of a map type are
// not immediately useful; they have to be make'd.
//
// Funcs and channels are similar, in that a zero value is not useful,
// but even a freshly make'd channel isn't useful: there's no fixed
// channel buffer size that is always going to be large enough, and
// there's no goroutine to drain the other end. Theoretically, these
// types could be supported, for example by sniffing for a constructor
// method or requiring prior registration, but for now it's not a
// frequent enough concern to be worth it. Programmers can work around
// it by explicitly using Iterator.Next instead of the Query.GetAll
// convenience method.
x := reflect.MakeMap(elemType)
ev.Elem().Set(x)
}
if err = loadEntity(ev.Interface(), e); err != nil {
if _, ok := err.(*ErrFieldMismatch); ok {
// We continue loading entities even in the face of field mismatch errors.
// If we encounter any other error, that other error is returned. Otherwise,
// an ErrFieldMismatch is returned.
errFieldMismatch = err
} else {
return keys, err
}
}
if mat != multiArgTypeStructPtr {
ev = ev.Elem()
}
dv.Set(reflect.Append(dv, ev))
}
keys = append(keys, k)
}
return keys, errFieldMismatch
}

答案1

得分: 1

默认情况下,函数顶部声明了errFieldMismatch,但没有初始化,因此返回errFieldMismatch

如果在迭代过程中没有出现ErrFieldMismatch,则在结束时errFieldMismatch仍然为nil,因此GetAll将返回一个nil错误。

英文:

The default is to return errFieldMismatch, which is declared, but not initialized at the top of the function.

If there isn't an ErrFieldMismatch at any point during the iteration, errFieldMismatch will still be nil at the end, thus GetAll will return a nil error.

huangapple
  • 本文由 发表于 2015年10月10日 05:01:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/33047118.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定