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.

Reply via email to