If you're new to Go, beware of one thing when returning interface values 
which are implemented by pointers.  An interface value can be nil (i.e. the 
zero value of interface: no type and no value); or it can contain a 
concrete value a concrete pointer type - where the concrete value itself is 
nil.  These two cases are distinct.

https://go.dev/play/p/cYJralfkYf6

On Monday, 20 June 2022 at 19:44:01 UTC+1 axel.wa...@googlemail.com wrote:

> [+golang-nuts again. Please don't respond off-list, so anyone can benefit 
> from the discussion]
>
> On Mon, Jun 20, 2022 at 8:32 PM Deividas Petraitis <
> h...@deividaspetraitis.lt> wrote:
>
>> Thank you for reply, it was really helpful! I wish groups would allow to 
>> edit the title.
>> According to he FAQ it seems like there should be some other ways to 
>> achieve what I am trying to accomplish here:
>> > Programmers who want covariant result types are often trying to express 
>> a type hierarchy through interfaces. In Go it's more natural to have a 
>> clean separation between interface and implementation.
>> I tried to google based on this keyword and found few interesting 
>> articles why covariance return types would be difficult to achieve, but not 
>> how to solve this problem using Go constructs.
>> In your opinion is my solution is right one for this problem? If not 
>> could you please give me few more ideas/hints. :)
>>
>
> You have to change the return type from `*FailingRoute` to `mux.Route`, so 
> the types match.
>  
>
>>
>> On Friday, 17 June 2022 at 22:22:12 UTC+3 axel.wa...@googlemail.com 
>> wrote:
>>
>>> 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...@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/5855c6fb-5c6c-4f0c-b440-0955ce49e737n%40googlegroups.com.

Reply via email to