uber-go/fx

Supporting a type alias of "context", injects actual context not type alias

Closed this issue · 4 comments

Hi,

I have just started to use fx, its going great but I came upon an issue and would love how to tackle it.

I need to inject "Context" into some structs, my initial thought was to create a type alias and inject it and sure enough, it works i.e.

fx.Provide(tester.NewMyNewContext),

and

type MyNewContext = context.Context

func NewMyNewContext() *MyNewContext {
	ctx := context.Background()

	return &ctx
}

I am "never" providing Context only MyNewContext.

Now when I inject *MyNewContext it does inject but I noticed from the log output that it is injecting a Context, not my alias, initially, I thought OK but let's just check injecting a standard Context, I would expect it to fail, but it does inject it and they are the same memory address.

i.e.

func NewCollector(config *configuration.Config, myNewContext *tester.MyNewContext) (*Collector, error) {

and

func NewExporter(config *configuration.Config, collector *collector.Collector, ctx *context.Context) *Exporter {

There is no failure and both the myNewContext and also ctx get injected and these are the same memory address.

I am a little confused about how to tackle this, can anyone help?

Thanks in advance for any help.

I forgot to mention my reasoning behind it. I wanted to be able to inject a different context OR maybe more than 1 context inside my app but as I am not fully understanding it - my current form injects the same instance.

Maybe type alias isn't the right approach, if anybody could suggest what is the right approach for supporting that scenario that would be really helpful.

Thanks

Hey there! The reason it's injecting a *context.Context instead of *MyNewContext is because you're using a type alias:

type MyNewContext = context.Context

An alias declaration in Go is strictly a convenience and does not actually result in a new type. It's strictly a build-time convenience.

From Go's point of view, at build time, func NewMyNewContext() *MyNewContext turns into func NewMyNewContext() *context.Context, and that's what gets compiled into your binary.

If you wish to declare an actual new type, you can drop the =. This will result in an a new type that is distinct from context.Context, but can be cast to/from it.

type MyNewContext context.Context

Closing because answered. Feel free to re-open or create a new ticket if you need more help!

Hey there! The reason it's injecting a *context.Context instead of *MyNewContext is because you're using a type alias:

type MyNewContext = context.Context

An alias declaration in Go is strictly a convenience and does not actually result in a new type. It's strictly a build-time convenience.

From Go's point of view, at build time, func NewMyNewContext() *MyNewContext turns into func NewMyNewContext() *context.Context, and that's what gets compiled into your binary.

If you wish to declare an actual new type, you can drop the =. This will result in an a new type that is distinct from context.Context, but can be cast to/from it.

type MyNewContext context.Context

Damn - why did I miss that lol, lets blame it on Friday :-)

Thanks for your help. I will get it changed.