golang multiple case in type switch

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

golang multiple case in type switch

问题

当我运行下面的代码片段时,它会引发一个错误:

> a.test undefined (type interface {} is interface with no methods)

看起来类型切换没有生效。

package main

import (
	"fmt"
)

type A struct {
	a int
}

func (this *A) test() {
	fmt.Println(this)
}

type B struct {
	A
}

func main() {
	var foo interface{}
	foo = A{}
	switch a := foo.(type) {
	case B, A:
		a.test()
	}
}

如果我将其更改为

switch a := foo.(type) {
	case A:
		a.test()
}

现在可以正常运行了。

英文:

when I run the code snippet bellow, it raise a error

> a.test undefined (type interface {} is interface with no methods)

It seem the type switch does not take effect.

package main

import (
	"fmt"
)

type A struct {
	a int
}

func(this *A) test(){
	fmt.Println(this)
}

type B struct {
	A
}

func main() {
	var foo interface{}
	foo = A{}
	switch a := foo.(type){
		case B, A:
			a.test()
	}
}

If I change it to

    switch a := foo.(type){
		case A:
			a.test()
	}

it's ok now.

答案1

得分: 9

这是由规范定义的正常行为(重点在于我):

> TypeSwitchGuard 可以包含一个短变量声明。当使用该形式时,变量在每个子句的隐式块的开头被声明。在列出仅有一个类型的 case 子句中,变量具有该类型;否则,变量具有 TypeSwitchGuard 表达式的类型

因此,实际上,类型切换确实生效,但变量 a 保持类型 interface{}

你可以通过断言 foo 具有 test() 方法来解决这个问题,代码如下:

package main

import (
	"fmt"
)

type A struct {
	a int
}

func (this *A) test() {
	fmt.Println(this)
}

type B struct {
	A
}

type tester interface {
	test()
}

func main() {
	var foo interface{}
	foo = &B{}
	if a, ok := foo.(tester); ok {
		fmt.Println("foo has test() method")
		a.test()
	}
}
英文:

This is normal behaviour that is defined by the spec (emphasis mine):

> The TypeSwitchGuard may include a short variable declaration. When that form is used, the variable is declared at the beginning of the implicit block in each clause. In clauses with a case listing exactly one type, the variable has that type; otherwise, the variable has the type of the expression in the TypeSwitchGuard.

So, in fact, the type switch does take effect, but the variable a keeps the type interface{}.

One way you could get around this is to assert that foo has the method test(), which would look something like this:

package main

import (
	"fmt"
)

type A struct {
	a int
}

func (this *A) test() {
	fmt.Println(this)
}

type B struct {
	A
}

type tester interface {
	test()
}

func main() {
	var foo interface{}
	foo = &B{}
	if a, ok := foo.(tester); ok {
		fmt.Println("foo has test() method")
		a.test()
	}
}

huangapple
  • 本文由 发表于 2016年11月13日 22:42:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/40575033.html
匿名

发表评论

匿名网友

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

确定