This is called "covariance" and the FAQ attempts to answer this question: https://go.dev/doc/faq#covariant_types Personally, I'm not fully convinced Go shouldn't have co/contravariant `func`, but I feel this has been ingrained for over ten years now and it's unlikely to change.
On Fri, Jun 17, 2022 at 9:11 PM Deividas Petraitis <h...@deividaspetraitis.lt> wrote: > Today while working on my side project I have encountered interesting > issue and despite I was able to overcome it I have realised that I might be > missing some import concepts about Go. > Let me share example code to demostrate the issue I am referring to: > > ```go > package main > > import ( > "net/http" > > "github.com/gorilla/mux" > ) > > func main() { > // We can pass GorillaRouter as Router, because it implement required > methods > _ = ServerHandler{ > router: NewGorillaRouter(), > } > > // We can not pass FailingRouter as Router, because of: > // cannot use FailingRouter{} (value of type FailingRouter) as type > Router in struct literal: > // FailingRouter does not implement Router (wrong type for HandleFunc > method) > // have HandleFunc(path string, handler func(http.ResponseWriter, > *http.Request)) *FailingRoute > // want HandleFunc(path string, handler func(http.ResponseWriter, > *http.Request)) Route > _ = ServerHandler{ > router: FailingRouter{}, > } > } > > type ServerHandler struct { > router Router > } > > type Router interface { > HandleFunc(path string, handler func(http.ResponseWriter, > *http.Request)) Route > } > > type Route interface { > Methods(methods ...string) Route > } > > func NewGorillaRouter() *GorillaRouter { > return &GorillaRouter{ > router: mux.NewRouter(), > } > } > > type GorillaRouter struct { > router *mux.Router > } > > func (gr *GorillaRouter) HandleFunc(path string, handler > func(http.ResponseWriter, *http.Request)) Route { > return &GorillaRoute{ > route: gr.router.HandleFunc(path, handler), > } > } > > type GorillaRoute struct { > route *mux.Route > } > > func (r *GorillaRoute) Methods(methods ...string) Route { > r.route = r.route.Methods(methods...) > return r > } > > type FailingRouter struct{} > > func (fr *FailingRouter) HandleFunc(path string, handler > func(http.ResponseWriter, *http.Request)) *FailingRoute { > return &FailingRoute{} > } > > type FailingRoute struct{} > > func (r *FailingRoute) Methods(methods ...string) *FailingRoute { > return r > } > ``` > > For convienence you can find soure code from above and run it here: > https://go.dev/play/p/M6N48FeegND > Now when code and context is clear question is following: why in > `FailingRouter` assignment compiler is not happy while in `GorillaRouter` > it is happy? > > Or to rephrase, why assigning concrete implementation to a parameter of > interface type is accepted: > > ```go > type ServerHandler struct { > router Router // assigning GorillaRouter to router is accepted > } > ``` > > but vice versa is not and throws an error: > > ```go > HandleFunc(path string, handler func(http.ResponseWriter, *http.Request)) > *FailingRoute // returning concrete that implements Router is not allowed > ``` > Is my approach ( `GorillaRouter` ) correct solution for this problem? > > P.S. Sorry about the title, I am still not sure is it right for this > problem description. > > -- > 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/fdc03ca3-f899-455a-8b7c-319c646f483an%40googlegroups.com > <https://groups.google.com/d/msgid/golang-nuts/fdc03ca3-f899-455a-8b7c-319c646f483an%40googlegroups.com?utm_medium=email&utm_source=footer> > . > -- 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/CAEkBMfFQ8%3D1TK5xXr1M573dj%2B3%2Bhujr%2BizBo3U%3Dr2K9J0PLD4A%40mail.gmail.com.