>From the perspective of "what difference would it make" the only thing that comes immediately to my mind is that if you return an interface type that is designed so that only types in your own package can or need to implement it then you could potentially add other methods to it in future without breaking compatibility with existing callers. I can't guess what the future might hold here, so I think only you can make a best guess about how this API might evolve in future. (If it were an interface intended to be implemented by others then that argument would not hold, because extending the interface would break the existing implementations.)
However, for me it feels more important to consider what it looks like at the callsite of the result. Something that seems "off" to me on first read of your example is you named your function variable clientIPStrategy, which is a "nouny" name rather than a "verby" name. I might instead have called it getClientIP, so that the final call would be: clientIP := getClientIP(req.Header, req.RemoteAddr) Since you can't control what a caller will name the result, it might help make the call site more readable to include a method with a more "verby" name: clientIP := clientIPStrategy.ClientIP(req.header, req.RemoteAddr) (note: "client IP" isn't technically a verb of course, but Effective Go calls for us to leave the "get" verb implied here <https://go.dev/doc/effective_go#Getters>, so I'm settling for just picking a noun that directly describes what this function returns.) However, that doesn't necessarily require an interface. You could define a method on your existing Strategy type to get that effect: func (s Strategy) ClientIP(headers http.Header, remoteAddr string) string { return s(headers, remoteAddr) } So this alone doesn't seem like a justification to use an interface type. If this were an interface type, I suppose it would conventionally be named something like ClientIPer rather than Strategy <https://go.dev/doc/effective_go#interface-names>, which feels idiosyncratic and leaves me to wonder what the RightmostTrustedCountStrategy function would be renamed to in that case. A *typical* reason for defining an interface type is so that other packages can define implementations of it and pass them into the package that defined the interface. In your case you are *returning* a value so presumably all of the implementations of this interface would be inside your package anyway, and it would not be useful for another package to define another implementation because that other package would not be able to coerce this function into returning an instance of it. With all of this said then, I don't find it compelling to define an interface type for this situation: the function type you defined is sufficient for what's needed here, and I prefer to do the simplest thing that can work. I might still try to finesse the callsite by fiddling with the names or by adding that optional method, along the lines I showed above, but that's a separate concern from what type this function should return. YMMV, of course. This is a pretty subjective question! Hopefully even if you don't agree with my conclusion the journey I took to get there is still useful to you. On Thursday, March 31, 2022 at 12:14:37 PM UTC-7 pritcha...@gmail.com wrote: > I’m working on a library to help get the “real” client IP from HTTP > requests: > https://github.com/realclientip/realclientip-go > https://pkg.go.dev/github.com/realclientip/realclientip-go > > Right now the “strategies” are like: > > type Strategy func(headers http.Header, remoteAddr string) string > ... > clientIPStrategy, err := > realclientip.RightmostTrustedCountStrategy("X-Forwarded-For", 1) > ... > clientIP := clientIPStrategy(req.Header, req.RemoteAddr) > > So, functions matching a signature are created that process the input. > > But I keep wondering: Should I be returning types (structs) adhering to an > interface instead? > > I’m starting to think I should, but I can’t think of what difference it > would make. > > Any feedback would be appreciated. > > Adam Pritchard > > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/11434ecd-24ef-47cd-832c-94f5b0209812n%40googlegroups.com.