{"action":"reopened","issue":{"url":"https://api.github.com/repos/uber-go/fx/issues/126","repository_url":"https://api.github.com/repos/uber-go/fx","labels_url":"https://api.github.com/repos/uber-go/fx/issues/126/labels{/name}","comments_url":"https://api.github.com/repos/uber-go/fx/issues/126/comments","events_url":"https://api.github.com/repos/uber-go/fx/issues/126/events","html_url":"https://github.com/uber-go/fx/issues/126","id":195618785,"number":126,"title":"RFC: fx.Context as a struct","user":{"login":"abhinav","id":41730,"avatar_url":"https://avatars.githubusercontent.com/u/41730?v=3","gravatar_id":"","url":"https://api.github.com/users/abhinav","html_url":"https://github.com/abhinav","followers_url":"https://api.github.com/users/abhinav/followers","following_url":"https://api.github.com/users/abhinav/following{/other_user}","gists_url":"https://api.github.com/users/abhinav/gists{/gist_id}","starred_url":"https://api.github.com/users/abhinav/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/abhinav/subscriptions","organizations_url":"https://api.github.com/users/abhinav/orgs","repos_url":"https://api.github.com/users/abhinav/repos","events_url":"https://api.github.com/users/abhinav/events{/privacy}","received_events_url":"https://api.github.com/users/abhinav/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":11,"created_at":"2016-12-14T19:11:37Z","updated_at":"2016-12-16T22:32:08Z","closed_at":null,"body":"Following up our discussion yesterday: I would like to propose the following:\r\n\r\n-   `fx.Context` is a struct that embeds `context.Context` rather than an\r\n    interface.\r\n-   UberFx values stored on `fx.Context` actually just use\r\n    `context.WithValue` rather than wrapping a `context.Context` in a new\r\n    type.  Value accessors will be defined for all UberFx values.\r\n-   Corresponding methods will be declared on `fx.Context` which just call the\r\n    accessor on itself.\r\n    \r\nSpecifically,\r\n\r\n```go\r\npackage fx\r\n\r\ntype Context struct{ context.Context }\r\n\r\nfunc (ctx Context) Logger() Logger {\r\n    return GetLogger(ctx)\r\n}\r\n\r\nfunc GetLogger(ctx context.Context) Logger {\r\n    // ..\r\n}\r\n```\r\n\r\nThis has a few advantages:\r\n\r\n-   Discoverability by having methods on `fx.Context`.\r\n-   Full compatibility with `context.Context` and `WithValue`. You won't lose\r\n    UberFx information if you do,\r\n    \r\n    ```go\r\n    fxctx := fx.NewContext(ctx, host)\r\n    ctx := fxctx.WithValue(...)\r\n    ```\r\n-   Downgrading to `context.Context` and upgrading back to `fx.Context` just\r\n    works.\r\n    \r\n    ```go\r\n    fxctx := fx.NewContext(ctx, host)\r\n    var ctx2 context.Context = fxctx\r\n    fxctx2 := fx.Context{ctx2}\r\n    fmt.Println(fxctx.Logger() == fxctx2.Logger())  // true\r\n    ```\r\n\r\nThe only thing to keep in mind is that accessors have to have reasonable\r\nbehavior for the case where a `context.Context` does not have UberFx\r\ninformation on it.\r\n\r\nThoughts?\r\n\r\nCC @breerly @kriskowal @willhug @sectioneight "}}
{"actor":{"display_login":"anuptalwalkar"}}