不可能的类型切换情况

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

Impossible type switch case

问题

这个程序无法编译:

package main

type Validator struct {
}

// Error 实现了 error 接口
func (v *Validator) Error() string {
	return ""
}

func test() error {
	return &Validator{}
}

func main() {
	switch test().(type) {
	case nil:
		println("没有错误")
	case Validator:
		println("验证错误")
		return
	default:
		println("未知错误")
		return
	}
}

错误信息为:

prog.go:19: 不可能的类型切换情况:test()(类型为 error)不能具有动态类型 Validator(缺少 Error 方法)

但是 Validator 结构体有 Error 方法。

英文:

This program does not compile:

package main

type Validator struct {
}

// Error implements error interface
func (v *Validator) Error() string {
	return ""
}

func test() error {
	return &Validator{}
}

func main() {
	switch test().(type) {
	case nil:
		println("No error")
	case Validator:
		println("Validation error")
		return
	default:
		println("Unknown error")
		return
	}
}

The error is:

prog.go:19: impossible type switch case: test() (type error) cannot have dynamic type Validator (missing Error method)

But Validator struct has method Error.

答案1

得分: 16

你有两种不同的类型,Validator和指针类型*Validator,这两种类型有不同的方法集。

你只为指针类型定义了一个Error()方法,而Validator没有这个方法。

你可以进行以下更改:

// Error实现了error接口
func (v Validator) Error() string {
    return ""
}

...

case *Validator, Validator: // 实际上你得到的是一个*Validator

这样就为Validator*Validator都实现了Error()方法。正如**Go规范**所说:

任何其他类型T的方法集包含所有以接收器类型T声明的方法。
相应指针类型T的方法集是所有以接收器类型T或T声明的方法的集合(也就是说,它还包含T的方法集)。

英文:

You have two different types, Validator and the pointer type *Validator, and these two types have different method sets.

You have only defined an Error() method for the pointer while Validator doesn't have this method.

What you can do is the following change:

// Error implements error interface
func (v Validator) Error() string {
    return ""
}

...

case *Validator, Validator: // You are actually getting a *Validator

This implements Error() for both Validator and *Validator. As the Go specification says:

>The method set of any other type T consists of all methods declared with receiver type T.
>The method set of the corresponding pointer type *T is the set of all methods declared with
>receiver *T or T (that is, it also contains the method set of T)

答案2

得分: 8

编译器是正确的。Validator 类型没有实现 Error 接口,而 *Validator 实现了。Validator*Validator 是不同的类型。只需在类型切换中将前者替换为后者:

switch test().(type) {
case nil:
    println("没有错误")
case *Validator:
    println("验证错误")
    return
default:
    println("未知错误")
    return
}

在 Go Playground 上的工作示例:http://play.golang.org/p/aWqzPXweiA

英文:

The compiler is correct. Validator type does not implement Error, *Validator does. Validator and *Validator are different types. Just replace the former with the latter in the type switch:

switch test().(type) {
case nil:
	println("No error")
case *Validator:
	println("Validation error")
	return
default:
	println("Unknown error")
	return
}

Working example on the Go Playground: http://play.golang.org/p/aWqzPXweiA

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

发表评论

匿名网友

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

确定