访问接口返回的类型的值时,是否需要使用类型断言?

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

Is it necessary to use a type assertion to access the values of a type returned by interface?

问题

当我有一个返回接口类型的函数时,返回的值不像我期望的那样工作。也就是说,它严格按照定义的接口行事,要访问接口中未定义的方法和值,我必须进行类型断言。为什么会这样呢?

考虑以下示例代码:

package main

import (
    "fmt"
)

type Frobnicator interface {
    Frobnicate()
}

type Foo struct {
    Value  string
}

func (f *Foo) Frobnicate() {
    fmt.Printf("The value is %s\n", f.Value)
}

func fooFactory() Frobnicator {
    return &Foo{"chicken"}
}

func main() {
    foo := fooFactory()
    foo.Frobnicate()
    // foo.Value undefined (type Frobnicator has no field or method Value)
    // fmt.Printf("foo value = %s\n", foo.Value)
    bar := foo.(*Foo)
    fmt.Printf("bar value = %s\n", bar.Value)
}

有没有更好、更简单、更符合惯例的方法来访问 foo.Value?或者类型断言真的是最好的方法吗?

英文:

When I have a function that returns an interface type, the returned value doesn't work as I would expect. That is, it acts strictly as the defined interface, and to access the methods and values not defined in the interface, I have to do a type assertion. Why?

Consider the following sample code:

package main

import (
    "fmt"
)

type Frobnicator interface {
    Frobnicate()
}

type Foo struct {
    Value  string
}

func (f *Foo) Frobnicate() {
    fmt.Printf("The value is %s\n", f.Value)
}

func fooFactory () Frobnicator {
    return &Foo{"chicken"}
}

func main() {
    foo := fooFactory( )
    foo.Frobnicate()
    // foo.Value undefined (type Frobnicator has no field or method Value)
    // fmt.Printf("foo value = %s\n", foo.Value)
    bar := foo.(*Foo)
    fmt.Printf("bar value = %s\n", bar.Value)
}

Is there a better, easier, more idiomatic way to get at foo.Value? Or is a type assertion really the best way?

答案1

得分: 2

如果您需要访问接口实现的内部值(Value),您必须通过接口本身公开它,或进行类型断言。这是因为Frobnicator中没有任何东西表明它是Foo还是其他实现结构体。

这与许多其他语言没有区别。在Java中,在类似的情况下,您也必须进行类型转换。

英文:

If you need access to inner value of interface implementation (Value), you must either expose it via interface itself or do a type assertion. That's because nothing in Frobnicator suggests whether it's Foo or some other implementing struct.

It is not different than many other languages. In Java you will have to cast also under similar circumstances.

答案2

得分: 2

这里不太确定该如何回答。也许对于接口类型有一些误解。接口类型是完全正常的类型。你可以按照接口的定义来处理接口值:调用接口方法。对于结构体类型,你可以访问字段并按照结构体类型的定义调用接口方法。所以一切都很简单明了:一个类型允许什么,就允许什么,无论是接口还是结构体。

现在发生的是,接口类型的值可能包含某个结构体值(比如说)。到目前为止,这是隐藏的。类型断言可以揭示出结构体值(此时就没有接口了)。你可以在接口中隐藏另一个结构体值(只要它实现了正确的方法),这个结构体可能没有Value字段。这就清楚了,如果没有进行类型断言,你无法访问Value字段,因为它可能不存在。

英文:

Not sure what to answer here. Maybe there is a misconception what interface types are. Interface types are absolutely normal types. And you can do with a interface value what the interface says: Invoke the interface methods. For a struct type you may access fields and invoke interface methods as defined by the struct type. So everything is plain and simple: A type allows what it allows, no matter whether interface or struct.

It now happens that a value of interface type may contain some struct value (say). Up to now this is hidden. Type asserting reveals the struct value (and there is no more interface). You may hide an other struct value in the interface (given it implements the right methods) this might not have a Value field. This makes it clear that you cannot access the Value field without a type assertion, because it might not be there.

huangapple
  • 本文由 发表于 2014年11月26日 00:26:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/27131831.html
匿名

发表评论

匿名网友

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

确定