Home  >  Article  >  Backend Development  >  Why does Go throw an error when a concrete type implementation returns a concrete type instead of the expected interface type in an interface method?

Why does Go throw an error when a concrete type implementation returns a concrete type instead of the expected interface type in an interface method?

DDD
DDDOriginal
2024-10-30 07:33:02189browse

Why does Go throw an error when a concrete type implementation returns a concrete type instead of the expected interface type in an interface method?

Interface Method Returning Interface Mismatch with Concrete Type Implementation

When working with Go interfaces, an error can occur when an interface method that declares a return type of interface is implemented by a concrete type. This error arises because the implementation of the method does not directly return the interface type but instead returns a concrete type that implements the interface.

Consider the following example:

<code class="go">package main

import "fmt"

type Foo struct {
    val string
}

func (f *Foo) String() string {
    return f.val
}

type StringerGetter interface {
    GetStringer() fmt.Stringer
}

type Bar struct{}

func (b *Bar) GetStringer() *Foo {
    return &Foo{"foo"}
}

func Printer(s StringerGetter) {
    fmt.Println(s.GetStringer())
}

func main() {
    f := Bar{}
    Printer(&f)
}</code>

Here, the Printer function expects a StringerGetter interface, which has a GetStringer method that returns a fmt.Stringer, while the Bar type's GetStringer method returns a concrete type Foo that implements the fmt.Stringer interface. This causes the error:

prog.go:29: cannot use &f (type *Bar) as type StringerGetter in
argument to Printer: *Bar does not implement StringerGetter (wrong
type for GetStringer method) had GetStringer() *Foo want
GetStringer() fmt.Stringer

The solution to this issue lies in making the methods of the interface match the expected interface types. In this case, the GetStringer method should return fmt.Stringer instead of a concrete type:

<code class="go">func (b *Bar) GetStringer() fmt.Stringer {
    return &Foo{"foo"}
}</code>

Alternatively, one can create a wrapper type that implements the desired interface and delegates to the concrete type, as demonstrated in the following techniques:

Type Embedding with Delegation:

<code class="go">type MyBar struct{ Bar }

func (b *MyBar) GetStringer() fmt.Stringer {
    return b.Bar.GetStringer()
}</code>

Type Wrapping:

<code class="go">type MyBar Bar

func (b *MyBar) GetStringer() fmt.Stringer {
    return &Foo{"foo"}
}</code>

These techniques allow for seamless interfacing with concrete types without modifying them directly. By wrapping or embedding the concrete types, custom types can be created that adhere to the desired interface contracts.

The above is the detailed content of Why does Go throw an error when a concrete type implementation returns a concrete type instead of the expected interface type in an interface method?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn