{"action":"closed","issue":{"url":"https://api.github.com/repos/golang/go/issues/23886","repository_url":"https://api.github.com/repos/golang/go","labels_url":"https://api.github.com/repos/golang/go/issues/23886/labels{/name}","comments_url":"https://api.github.com/repos/golang/go/issues/23886/comments","events_url":"https://api.github.com/repos/golang/go/issues/23886/events","html_url":"https://github.com/golang/go/issues/23886","id":297976779,"number":23886,"title":"proposal: Derive interface type from a concrete type","user":{"login":"guangda-hu","id":751752,"avatar_url":"https://avatars2.githubusercontent.com/u/751752?v=4","gravatar_id":"","url":"https://api.github.com/users/guangda-hu","html_url":"https://github.com/guangda-hu","followers_url":"https://api.github.com/users/guangda-hu/followers","following_url":"https://api.github.com/users/guangda-hu/following{/other_user}","gists_url":"https://api.github.com/users/guangda-hu/gists{/gist_id}","starred_url":"https://api.github.com/users/guangda-hu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/guangda-hu/subscriptions","organizations_url":"https://api.github.com/users/guangda-hu/orgs","repos_url":"https://api.github.com/users/guangda-hu/repos","events_url":"https://api.github.com/users/guangda-hu/events{/privacy}","received_events_url":"https://api.github.com/users/guangda-hu/received_events","type":"User","site_admin":false},"labels":[{"id":150880249,"url":"https://api.github.com/repos/golang/go/labels/Go2","name":"Go2","color":"ffaaaa","default":false},{"id":150880200,"url":"https://api.github.com/repos/golang/go/labels/LanguageChange","name":"LanguageChange","color":"ffaaaa","default":false},{"id":236419512,"url":"https://api.github.com/repos/golang/go/labels/Proposal","name":"Proposal","color":"ededed","default":false}],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":{"url":"https://api.github.com/repos/golang/go/milestones/30","html_url":"https://github.com/golang/go/milestone/30","labels_url":"https://api.github.com/repos/golang/go/milestones/30/labels","id":1373555,"number":30,"title":"Proposal","description":"Proposals that are pending (not yet accepted/rejected).\r\n","creator":{"login":"rsc","id":104030,"avatar_url":"https://avatars1.githubusercontent.com/u/104030?v=4","gravatar_id":"","url":"https://api.github.com/users/rsc","html_url":"https://github.com/rsc","followers_url":"https://api.github.com/users/rsc/followers","following_url":"https://api.github.com/users/rsc/following{/other_user}","gists_url":"https://api.github.com/users/rsc/gists{/gist_id}","starred_url":"https://api.github.com/users/rsc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rsc/subscriptions","organizations_url":"https://api.github.com/users/rsc/orgs","repos_url":"https://api.github.com/users/rsc/repos","events_url":"https://api.github.com/users/rsc/events{/privacy}","received_events_url":"https://api.github.com/users/rsc/received_events","type":"User","site_admin":false},"open_issues":187,"closed_issues":475,"state":"open","created_at":"2015-10-24T01:40:49Z","updated_at":"2018-04-24T20:58:01Z","due_on":null,"closed_at":null},"comments":2,"created_at":"2018-02-17T04:01:03Z","updated_at":"2018-04-24T20:58:01Z","closed_at":"2018-04-24T20:58:01Z","author_association":"NONE","body":"I'm not sure if this is a good idea. But I have thought about it several times and would like to share it in case it has not been considered. This is for future versions of Go (probably Go 2.0).\r\n\r\n## Proposal\r\nIt would be nice if there is a way to define an interface type that is the method set of some arbitrary type `T`. My proposal is to simply generalize the existing interface embedding:\r\n```golang\r\ninterface {\r\n  T\r\n}\r\n```\r\nCurrently `T` can only be an interface. The proposal is to allow other types as well, and the interface contains the _method sets_ of all embedded types.\r\n* The same restrictions of struct embedding applies: `T` must not be a pointer type, and for non-interface type, `*T` can also be embeded.\r\n* The rules of interface embedding also applies: the method sets of embedded types must be disjoint.\r\n\r\n## Application\r\nSuppose I need to write the following function that uses a concrete type `someservice.Client`:\r\n```golang\r\nfunc MyFunc(*someservice.Client) {\r\n // ....\r\n}\r\n```\r\nTo write unit test for `MyFunc`, I want to fake `someservice.Client`. An easy way is to change the above code to\r\n```golang\r\ntype myInterface interface {\r\n  // all methods needed\r\n}\r\nvar _ myInterface = &someservice.Client{}\r\nfunc MyFunc(myInterface) {\r\n}\r\n```\r\nHere `myInterface` contains a subset of the method set of `*someservice.Client`. However, if the method set is large, and if I need to change code back and forth (so it's hard to determine which methods are used), it would be tedious to keep `myInterface` up to date. The proposal will solve the problem:\r\n```golang\r\ntype myInterface interface {\r\n  *someservice.Client\r\n}\r\n```\r\n\r\n## Note 1\r\nA google search shows that people have written tools to generate interface from struct: https://github.com/vburenin/ifacemaker (not necessarily to solve the same problem I mentioned though).\r\n\r\n## Note2\r\nAnother note is that I think this can somewhat make \"polymorphism\" easier in Go. Struct embedding is like \"inherence\" in many ways, but not always. Suppose we have\r\n```golang\r\ntype Derived struct {\r\n  Base\r\n}\r\n```\r\nWe still need an interface type that contains the methods of `Base` if we want something that can hold either a `Base` or a `Derived`. And the proposed `interface { Base }` is such an interface.\r\n"}}
{"actor":{"display_login":"ianlancetaylor"}}