Hacker News new | past | comments | ask | show | jobs | submit login

I think you're a little off. The only boilerplate required for your example is the interface definition. After that you can define your own implementations of the "Do" interface as suggested by the parent.

  // boilerplate
  type Do interface {
    func Do(*http.Request) (*http.Response, error)
  }

  // Custom Implementation
  type MockClient struct {}
  func (mc *MockClient) Do(req *http.Request) (*http.Response, error) {
    // MockClient type now satisfies the Do interface
  }



You're not taking this issue in account:

> you can't make your own interfaces that unify standard library types and your types unless you make your types take exactly the same methods with exactly the same signatures (problematic if you want your types to support slightly different functionality, etc.)


The original comment mentioned being able to decouple Go code from specific implementations of functionality by relying on self defined interfaces instead of specific functions. pcwalton's example seemed to confuse this point, which I wanted to clarify.

As to that point, your interface types will only match standard library ones if you're trying to unify them. In which case you probably want them to have the same signature.


> The original comment mentioned being able to decouple Go code from specific implementations of functionality by relying on self defined interfaces instead of specific functions. pcwalton's example seemed to confuse this point, which I wanted to clarify.

The problem is that you're clarifying the wrong thing, the example is confusing because it trivially proxies a built-in method but the remark is what's important to the reply. Your reply is only confusing things further by considering the flawed example but ignoring the actual point.

> As to that point, your interface types will only match standard library ones if you're trying to unify them.

No, why would you think that? You may want to "compatibilise" multiple third-party types (that some of them are in the standard library is a complete red herring) as well as first-party ones (a mock or whatever) e.g. abstract over stdlib sockets, zmq sockets and sqlite.


You're right, I'm confusing the issue. I re-read pcwalton's comment and I think understand the point they're trying to make. Not sure the last part was correct though.

> So Go makes a tradeoff with its structural typing: it doesn't require the small amount of boilerplate code to achieve the pattern you describe, but it prevents you from providing new implementations for types you didn't define.

Shouldn't this be "So Go makes a tradeoff with its structural typing: it does require a small amount of boilerplate code to achieve the pattern you describe, but it allows you to provide new implementations for types you define."?


Well no because "the pattern you describe" in that context was only implementing stuff on types you own/control, which is basically a function declaration in Go, the problem is that doesn't extend to types you don't control, Go only lets you define methods on local types (types from the same package).

By comparison the code pcwalton shows has more upfront boilerplate, you need to explicitly `implement $Interface for $Type`, but it works for both local and non-local types.

That's what e.g. Rust does, you can implement a trait on a type if either the trait or the type is local (in theory you could also do so if neither is local but IIRC that's not allowed so conflicts don't have to be handled). Which means you can do this:

    trait Do {
        fn do(&self, req: &Request) -> Result<Response>
    }

    impl Do for hyper::http::Client {
        fn do(&self, req: &Request) -> Result<Response> {
            ...
        }
    }

    impl Do for MockClient {
        fn do(&self, req: &Request) -> Result<Response> {
            ...
        }
    }
There's a higher up-front syntactic cost (in that you have to declare the trait and you have to explicitly implement it even on the local MockClient type) but in return you also can implement it on the non-local "actual" http client.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: