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.

Reply via email to