Accept interface and return struct - When not

I have read some articles like https://medium.com/@cep21/what-accept-interfaces-return-structs-means-in-go-2fe879e25ee8. Which talks about accepting interface and return struct. I personally prefer and like this idea since this gives more readability and also supports the reason of why interfaces are not tightly couple with struct in Golang.

I want to know what are some of those cases and I have seen some articles too, where we need to return interface rather struct and whether this is a good practice or not ?

Return an interface when you need to. :slight_smile: Some examples that come to mind are functions that return behavior in the form of an interface (e.g., io.LimitReader and similar; takes an io.Reader and a length, returns a new io.Reader) and things like factory functions that can return different types that are covered by a common interface.

I think it’s good practice to return an interface when you need to return an interface. If you don’t need to, it’s probably better to return a struct type instead.

1 Like

Thanks,

I think the receiver end (caller) where it is accepting the return type from a method (be it factory) is satisfying an interface should enforce this and not the implementation end. By returning the interface from another package(for ex), we are doing a coupling between packages.

Sure. But consider something that wants to be able to connect to several different, possibly custom, protocols. Let’s say tcp, tcp+tls://, quic://. We don’t want to hardcode the list of protocols and how to connect them. Instead, we have something that takes a net.Dialer. The actual code doing the dialing ends being something like

...
uri, _ = url.Parse("tcp+tls://example.com:1234")
proto := uri.Scheme
host := uri.Host
dialer := protos.getDialer(proto)
conn, err := dialer.Dial(proto)
...

getDialer() is already something that returns an interface - the net.Dialer.

But maybe we want a registry or something underlying that getDialer method. Perhaps something as simple as a map[string]net.Dialer would do, but perhaps dialers for the various protocols can’t be reused trivially and we want a factory function for some reason. In that case it would be reasonable for the protocol manager thing to have a func registerProtocol(name string, factory func() net.Dialer) and we would pass it a function that in turn returns a dialer.

Perhaps this whole thing would be exported and called from another package.

Slightly contrived, but there are lots of reasonable times to return interfaces.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.