英文:
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()
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论