Typed map不支持索引操作。

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

Typed map does not support indexing

问题

我想将go-validator 扩展以返回更好的类型:

type Error map[string][]error

// 当转换为字符串时,将输出第一个错误(例如用于 JSON 响应)。
func (err Error) Error() string {
    for k, errs := range err {
        return fmt.Sprintf("%s value had %s", k, errs[0].Error())
    }

    return "no error"
}

func Validate(v interface{}) error {
    if ok, errs := DefaultValidator.Validate(v); !ok {
        return Error(errs)
    }

    return nil
}

在为此编写测试时,我遇到了一个问题,即类型为 Error 的映射似乎丢失了索引功能:

err = Validate(Value{
    Foo:      "bar",
    Email:    "foo@bar.me",
    Required: "1234",
})
c.Check(err, check.IsNil)

err, ok := Validate(Value{}).(Error)
c.Check(ok, check.Equals, true)
c.Check(err["Foo"], check.DeepEquals, []error{validator.ErrMin})
c.Check(err["Email"], check.DeepEquals, []error{validator.ErrInvalid})
c.Check(err["Required"], check.DeepEquals, []error{validator.ErrZeroValue})

返回:

model/validation/validation_test.go:42: invalid operation: err["Foo"] (type error does not support indexing)
model/validation/validation_test.go:43: invalid operation: err["Email"] (type error does not support indexing)
model/validation/validation_test.go:44: invalid operation: err["Required"] (type error does not support indexing)

我还尝试将其转换为类型 map[string][]error,但得到了"impossible type assertion"的错误。

我的方法有什么问题? 如何使索引恢复正常工作?

英文:

I want to extend go-validator to return a better type:

type Error map[string][]error

// Will output the first error when stringified (e.g. for json response).
func (err Error) Error() string {
	for k, errs := range err {
		return fmt.Sprintf("%s value had %s", k, errs[0].Error())
	}

	return "no error"
}

func Validate(v interface{}) error {
	if ok, errs := DefaultValidator.Validate(v); !ok {
		return Error(errs)
	}

	return nil
}

As I am now writing tests for this I ran into the problem that it the typed map Error seems to have lost it indexing capabilities:

err = Validate(Value{
	Foo:      "bar",
	Email:    "foo@bar.me",
	Required: "1234",
})
c.Check(err, check.IsNil)

err, ok := Validate(Value{}).(Error)
c.Check(ok, check.Equals, true)
c.Check(err["Foo"], check.DeepEquals, []error{validator.ErrMin})
c.Check(err["Email"], check.DeepEquals, []error{validator.ErrInvalid})
c.Check(err["Required"], check.DeepEquals, []error{validator.ErrZeroValue})

Returns:

model/validation/validation_test.go:42: invalid operation: err["Foo"] (type error does not support indexing)
model/validation/validation_test.go:43: invalid operation: err["Email"] (type error does not support indexing)
model/validation/validation_test.go:44: invalid operation: err["Required"] (type error does not support indexing)

I also tried to cast to type map[string][]error but got "impossible type assertion".

What is wrong with my approach? How can I get indexing back to work?

答案1

得分: 2

你的 err 变量似乎是用 "error" 类型初始化的。当你执行

err, ok := Validate(Value{}).(Error)

时,你只是检查 err 是否实际上是一个 "Error" 类型。如果你将 err 改为 errs,它应该可以工作。

Playground 示例:http://play.golang.org/p/ljNroPzVbd

英文:

It seems like your err variable is initialised with error type. When you do

err, ok := Validate(Value{}).(Error)

you merely check if err is actually an Error. If you change err there to say errs, it should work.

Playground example: http://play.golang.org/p/ljNroPzVbd

huangapple
  • 本文由 发表于 2014年7月23日 15:42:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/24904548.html
匿名

发表评论

匿名网友

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

确定