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

197 views Asked by At

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?

2

There are 2 answers

0
Volker On BEST ANSWER

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.

2
Alex Gitelman On

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.