Compile-time Dependency Injection for Go

Overview

Wire: Automated Initialization in Go

Build Status godoc Coverage

Wire is a code generation tool that automates connecting components using dependency injection. Dependencies between components are represented in Wire as function parameters, encouraging explicit initialization instead of global variables. Because Wire operates without runtime state or reflection, code written to be used with Wire is useful even for hand-written initialization.

For an overview, see the introductory blog post.

Installing

Install Wire by running:

go get github.com/google/wire/cmd/wire

and ensuring that $GOPATH/bin is added to your $PATH.

Documentation

Project status

As of version v0.3.0, Wire is beta and is considered feature complete. It works well for the tasks it was designed to perform, and we prefer to keep it as simple as possible.

We'll not be accepting new features at this time, but will gladly accept bug reports and fixes.

Community

For questions, please use GitHub Discussions.

This project is covered by the Go Code of Conduct.

Issues
  • wire: test flakes on Travis with

    wire: test flakes on Travis with "failed to cache compiled Go files"

    Describe the bug

    The Wire tests fail intermittently on Travis with an error like:

            wire_test.go:96: go [list -e -json -compiled -test=false -export=false -deps=true -tags=wireinject -- example.com/foo]: exit status 1: go: finding github.com/google/go-cloud v0.2.0
                go build runtime/internal/atomic: failed to cache compiled Go files
    

    To Reproduce

    This is an intermittent failure, but I've only seen it on Travis. Uncertain what the triggers are.

    Expected behavior

    Wire tests should pass.

    /cc @vangent, who I believe hit this failure before, but I can't find evidence of it.

    bug 
    opened by zombiezen 19
  • Problem running wire from tutorial

    Problem running wire from tutorial

    Describe the bug

    I can not get the wire command to work. Started off with the tutorial, made a directory in ~/go/src/test and copied the main.go and wire.go files from the _tutorial directory. Ran go get github.com/google/wire/cmd/wire then proceeded to run wire, here is the output:

    16:53 $
    ✔ ~/go/src/test
    16:53 $ ls
    main.go	wire.go
    ✔ ~/go/src/test
    16:53 $ cat main.go
    // Copyright 2018 The Wire Authors
    //
    // Licensed under the Apache License, Version 2.0 (the "License");
    // you may not use this file except in compliance with the License.
    // You may obtain a copy of the License at
    //
    //     https://www.apache.org/licenses/LICENSE-2.0
    //
    // Unless required by applicable law or agreed to in writing, software
    // distributed under the License is distributed on an "AS IS" BASIS,
    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    // See the License for the specific language governing permissions and
    // limitations under the License.
    
    // The greeter binary simulates an event with greeters greeting guests.
    package main
    
    import (
    	"errors"
    	"fmt"
    	"os"
    	"time"
    )
    
    // Message is what greeters will use to greet guests.
    type Message string
    
    // NewMessage creates a default Message.
    func NewMessage(phrase string) Message {
    	return Message(phrase)
    }
    
    // NewGreeter initializes a Greeter. If the current epoch time is an even
    // number, NewGreeter will create a grumpy Greeter.
    func NewGreeter(m Message) Greeter {
    	var grumpy bool
    	if time.Now().Unix()%2 == 0 {
    		grumpy = true
    	}
    	return Greeter{Message: m, Grumpy: grumpy}
    }
    
    // Greeter is the type charged with greeting guests.
    type Greeter struct {
    	Grumpy  bool
    	Message Message
    }
    
    // Greet produces a greeting for guests.
    func (g Greeter) Greet() Message {
    	if g.Grumpy {
    		return Message("Go away!")
    	}
    	return g.Message
    }
    
    // NewEvent creates an event with the specified greeter.
    func NewEvent(g Greeter) (Event, error) {
    	if g.Grumpy {
    		return Event{}, errors.New("could not create event: event greeter is grumpy")
    	}
    	return Event{Greeter: g}, nil
    }
    
    // Event is a gathering with greeters.
    type Event struct {
    	Greeter Greeter
    }
    
    // Start ensures the event starts with greeting all guests.
    func (e Event) Start() {
    	msg := e.Greeter.Greet()
    	fmt.Println(msg)
    }
    
    func main() {
    	e, err := InitializeEvent("hi there!")
    	if err != nil {
    		fmt.Printf("failed to create event: %s\n", err)
    		os.Exit(2)
    	}
    	e.Start()
    }
    ✔ ~/go/src/test
    16:53 $ cat wire.go
    //+build wireinject
    
    // The build tag makes sure the stub is not built in the final build.
    package main
    
    import "github.com/google/wire"
    
    // InitializeEvent creates an Event. It will error if the Event is staffed with
    // a grumpy greeter.
    func InitializeEvent(phrase string) (Event, error) {
    	wire.Build(NewEvent, NewGreeter, NewMessage)
    	return Event{}, nil
    }
    ✔ ~/go/src/test
    16:53 $ wire
    packages not found
    wire: generate failed
    ✘-1 ~/go/src/test
    16:53 $
    

    I then tried to run wire from the downloaded repo:

    16:51 $
    ✔ ~/go/src/github.com/google/wire/_tutorial [v0.2.1|✚ 1…1]
    16:54 $ ls
    README.md	main.go		wire.go
    ✔ ~/go/src/github.com/google/wire/_tutorial [v0.2.1|✚ 1…1]
    16:54 $ wire
    packages not found
    wire: generate failed
    ✘-1 ~/go/src/github.com/google/wire/_tutorial [v0.2.1|✚ 1…1]
    16:54 $
    

    To Reproduce

    go get -u github.com/google/wire
    cd ~/go/src/github.com/google/wire
    git co v0.2.1
    cd _tutorial
    rm wire_gen.go
    wire
    

    16:51 $ ✔ ~/go/src/github.com/google/wire/_tutorial [v0.2.1|✚ 1…1] 16:54 $ ls README.md main.go wire.go ✔ ~/go/src/github.com/google/wire/_tutorial [v0.2.1|✚ 1…1] 16:54 $ wire packages not found wire: generate failed ✘-1 ~/go/src/github.com/google/wire/_tutorial [v0.2.1|✚ 1…1] 16:54 $

    
    ## Expected behavior
    
    wire_gen.go will be generated.
    
    ### Version
    
    v0.2.1
    
    ### Additional context
    
    I tried this with master before resorting to v0.2.1 and I got the same error both times. I really want to try this out in my project. Any help would be awesome.
    
    GOPATH=/Users/kortm/go
    go version: `version go1.11.1 darwin/amd64`
    
    
    bug needs info 
    opened by yairgo 12
  • `go:generate wire` in generated files should be optional

    `go:generate wire` in generated files should be optional

    Is your feature request related to a problem? Please describe.

    We generate a lot of files with wire and we would like to use a single execution of wire to do that. When wire writes out go:generate instructions into files it generates, it makes it hard for us remove those commands and generate the wire files on our own.

    Describe the solution you'd like

    I propose adding a flag such as --no-go-generate to the cli, which, when set omits the go:generate line from https://github.com/google/wire/blob/f285c073b52078f165ca19f3ceb192f0f50f3934/internal/wire/wire.go#L253.

    Describe alternatives you've considered

    For now we can work around this issue by removing the line after running wire.

    Additional context

    opened by gracenoah 12
  • wire: wire.FieldsOf() to inject the values from fields of a struct

    wire: wire.FieldsOf() to inject the values from fields of a struct

    Pretty new to wire, so forgive me if I am asking the wrong questions.

    As far as I understand, wire.Value() allows to specify a value to be injected. If I have a struct, the fields of which must be injected rather than the value of the struct itself, would I have to use wire.Value() for each field of the struct?

    Would it make sense to add something like wire.FieldValues(), which injects the fields of the struct that is specified rather than the struct itself?

    enhancement 
    opened by e-nikolov 11
  • wire: don't work with go modules [go v.1.11.1]

    wire: don't work with go modules [go v.1.11.1]

    When I run the wire command, I get the following:

    ...
    /home/terminator/.gvm/pkgsets/go1.11.1/global/pkg/mod/github.com/ory/[email protected]+incompatible/dockertest.go:13:2: could not import github.com/cenkalti/backoff (cannot find package "github.com/cenkalti/backoff" in any of:
                    /home/terminator/.gvm/gos/go1.11.1/src/github.com/cenkalti/backoff (from $GOROOT)
                    /home/terminator/.gvm/pkgsets/go1.11.1/global/src/github.com/cenkalti/backoff (from $GOPATH))
    ...
    and many many other dependencies...
    

    wire looks at GOPATH and GOROOT instead of modules dir, what am I doing wrong?

    opened by Terminator637 9
  • Inject slice of interfaces

    Inject slice of interfaces

    Assume that i have this code

    type Counter interface {
    	GetCount() int
    }
    
    type A struct{}
    type B struct{}
    
    func (*A) GetCount() int {
    	return 1
    }
    
    func (*B) GetCount() int {
    	return 2
    }
    
    type ChainCounter struct {
    	counters []Counter
    }
    
    // Providers
    
    func ProvideA() *A {
    	return &A{}
    }
    
    func ProvideB() *A {
    	return &A{}
    }
    
    func ProvideChainCounter(counters ...Counter) *ChainCounter {
    	return &ChainCounter{counters: counters}
    }
    

    How can i inject A and B (which implementing Counter) to chain counter with wire ?

    opened by alexmatsak 8
  • wire: improve error message when a provider set includes a binding but not the corresponding concrete type

    wire: improve error message when a provider set includes a binding but not the corresponding concrete type

    Describe the bug

    A wire set containing subsets (one or more wire sets), should be just the same as a wire set with items from that subsets added directly.

    To Reproduce

    Given this code:

    master.go

    package wirebug
    
    type ISomeInterface interface {
    	DoStuff(thing string) int
    }
    
    type SomeStuff struct{}
    
    func (si *SomeStuff) DoStuff(thing string) int {
    	return len(thing)
    }
    
    func NewStuff() *SomeStuff {
    	return &SomeStuff{}
    }
    

    wiring.go

    package wirebug
    
    import "github.com/google/wire"
    
    var WiringProviders = wire.NewSet(
    	NewStuff,
    )
    
    var WiringBindings = wire.NewSet(
    	wire.Bind(new(ISomeInterface), new(SomeStuff)),
    )
    
    var WiringSet = wire.NewSet(
    	WiringProviders,
    	WiringBindings,
    )
    

    injectors.go

    //+build wireinject
    
    package wirebug
    
    import "github.com/google/wire"
    
    func InjectStuff() ISomeInterface {
    	wire.Build(WiringSet)
    	return nil
    }
    

    Running wire ./... results in an error:

    $$$/wirebug/wiring.go:10:2: no binding for *$$$/wirebug.SomeStuff
    wire: at least one generate failure
    

    It's as if items from WiringProviders can't be seen by WiringBindings although they're inside WiringSet. Inside the documentation of wire.NewSet, there's this statement, "Passing a ProviderSet to NewSet is the same as if the set's contents were passed as arguments to NewSet directly.", but it turns out that it's not so.

    Expected behavior

    The file wire_gen.go should be generated without problem.

    Both of these WiringSet

    var WiringProviders = wire.NewSet(
    	NewStuff,
    )
    
    var WiringBindings = wire.NewSet(
    	wire.Bind(new(ISomeInterface), new(SomeStuff)),
    )
    
    var WiringSet = wire.NewSet(
    	WiringProviders,
    	WiringBindings,
    )
    

    and

    var WiringSet = wire.NewSet(
    	NewStuff,
    	wire.Bind(new(ISomeInterface), new(SomeStuff)),
    )
    

    should behave the same. But only the below version works.

    Version

    Version 0.2.1

    Additional context

    None.

    opened by jarollz 8
  • Idea: use `go run` in generate line

    Idea: use `go run` in generate line

    An idea suggested by @steebchen is to use //go:generate go run github.com/google/wire/cmd/wire as the automatically inserted generate line for Wire output. This would have the advantage of always using a version of the code generator that's the same as the library being used, at the cost of perhaps some running time.

    EDIT (Hit send too early) I don't think we want to make this change until Go Modules is the default, thus I'm marking this issue blocked.

    enhancement 
    opened by zombiezen 8
  • Add goreportcard.com badge

    Add goreportcard.com badge

    It is one requirement of the pull request to add wire library to list https://github.com/avelino/awesome-go

    https://github.com/avelino/awesome-go/pull/2965

    https://github.com/avelino/awesome-go/blob/master/CONTRIBUTING.md

    https://github.com/avelino/awesome-go/blob/master/.github/PULL_REQUEST_TEMPLATE.md

    cla: yes 
    opened by dsxack 8
  • wire: replace wire.Value with wire.Zero

    wire: replace wire.Value with wire.Zero

    In reviewing the Wire documentation, I think that the variable reference semantics in wire.Value expressions are too subtle, and are impossible to precisely reproduce if a runtime-based approach is ever used. Out of the 9 current non-test usages of the wire.Value, only 2 use a non-zero value. The first is for http.DefaultClient and the second is for a statically known list of health checks. It's simpler to understand both of these as providers at the expense of some typing.

    For the common (and originally intended) use-case, I propose replacing wire.Value with wire.Zero, defined as:

    // Zero binds a type to its zero value. ptr must be a pointer to the desired type.
    //
    // Example:
    //
    //     var MySet = wire.NewSet(wire.Zero(new(*MyStruct)))
    func Zero(ptr interface{}) ZeroValue {
      // ...
    }
    
    // A ZeroValue is a binding to a zero value.
    type ZeroValue struct{}
    
    opened by zombiezen 7
  • Provide a way to add to wired providers - init skipped fields, or add cleanup/error

    Provide a way to add to wired providers - init skipped fields, or add cleanup/error

    Is your feature request related to a problem? Please describe.

    Sometimes there are fields that may need construction but not injection - typical examples are making a map for caching, or channel for whatever.

    The only trick I've found so far is to make a secondary type, such as

    
    struct InjectedBase {
      Config *config.Config
      HttpClient *http.Client
    }
    
    struct Injected {
      InjectedBase
    
      tokenForHost map[string]string `wire:"-"`
    }
    
    func NewInjectedFromBase(base *InjectedBase) (*Injected, func()) {
      ret := &Injected{
        InjectedBase: *base,
        tokenForHost: make(map[string]string),
      }
      return ret, ret.Close
    }
    
    var DefaultSet = wire.NewSet(
      wire.Struct(new(InjectedBase), "*"),
      NewInjectedFromBase,
    )
    var buildSet = DefaultSet
    
    func NewInjected() *Injected {
      panic(wire.Build(buildSet))
    }
    

    Describe the solution you'd like

    It would be great if a provider modifier could be somehow specified… Something like

    func WrapInjected(i *Injected) (*Injected, func()) {
      i.tokenForHost = make(map[string]string)
      return i, i.Close
    }
    
    var DefaultSet = wire.NewSet(
      wire.Struct(new(Injected), "*"),
      WrapInjected,
    )
    

    or maybe pass the wrapping to the wire.Struct call…

    var DefaultSet = wire.NewSet(
      wire.Struct(new(Injected), WrapInjected, "*"),
    )
    

    Describe alternatives you've considered

    We could always just do the two-class solution with "base" and "real" but it creates extra tedium to something that wire could make really pleasing.

    Additional context

    The two cases that could be solved with this wrapping style would be for:

    1. construction
    2. destruction ("cleanup")

    It would be really great to be able to have the cleanup as part of wire so that in the above example, if there's a "Close" method, each struct that has the Injected thing doesn't also need to (manually) add a Close method that closes the injected thing - but only the place where the injection starts (main(), e.g.) would have to defer cleanup() and that would do all the great wired composition of cleanups of all the things in the right reverse-order sequence.

    opened by scr-oath 0
  • "multiple binding" error throws, When generating wire_gen.go.

    Describe the bug

    scene one, there are three rules given:

    1. A depends on B and C
    2. B depends on D
    3. C depends on D

    in scene one, we can know that there are only one D rather than two. but i got an "multiple bindings" error

    scene two, there are also two rules given:

    1. A depends on B and C
    2. B and C depends on D

    actually scene two can be resolved to the same dependencies. but only the rules in scene two work when generating wire_gen.go

    To Reproduce

    1. provider.go
    type GrandParent struct {
    	pta *ParentA
    	ptb *ParentB
    }
    type ParentA struct {
    	son *Son
    }
    type ParentB struct {
    	son *Son
    }
    type Son struct {
    	name string
    }
    
    var (
    	son                = Son{"singleton"}
    	pta                 = ParentA{}
    	ptb                 = ParentB{}
    	ProvideParentASet  = wire.NewSet(pta, son)
    	ProvideParentBSet  = wire.NewSet(ptb, son)
    	ProvideGrandParent = wire.NewSet(ProvideParentASet, ProvideParentBSet)
    )
    
    1. wire.go
    func InjectGrandParent() *GrandParent {
    	panic(wire.Build(ProvideGrandParent))
    }
    

    when run wire, error throws

    
    wire: /Users/duncan/gitRepo/yet-another/provider.go:62:23: ProvideGrandParent has multiple bindings for e.coding.net/codingcorp/coding-ci/yet-another.Son
            current:
            <- struct provider "Son" (/Users/duncan/gitRepo/yet-another/provider.go:52:6)
            <- provider set "ProvideParentBSet" (/Users/duncan/gitRepo/yet-another/provider.go:61:23)
            previous:
            <- struct provider "Son" (/Users/duncan/gitRepo/yet-another/provider.go:52:6)
            <- provider set "ProvideParentASet" (/Users/duncan/gitRepo/yet-another/provider.go:60:23)
    wire: /Users/duncan/gitRepo/yet-another/provider.go:62:23: ProvideGrandParent has multiple bindings for *e.coding.net/codingcorp/coding-ci/yet-another.Son
            current:
            <- struct provider "Son" (/Users/duncan/gitRepo/yet-another/provider.go:52:6)
            <- provider set "ProvideParentBSet" (/Users/duncan/gitRepo/yet-another/provider.go:61:23)
            previous:
            <- struct provider "Son" (/Users/duncan/gitRepo/yet-another/provider.go:52:6)
            <- provider set "ProvideParentASet" (/Users/duncan/gitRepo/yet-another/provider.go:60:23)
    
    

    Expected behavior

    I think rules in scene one are supposed to be work.

    Version

    Which version of Wire are you seeing the bug with?

    v0.5.0

    Additional context

    Add any other context about the problem here.

    opened by Duncan-tree-zhou 0
  • missing go.sum entry after ran go mod tidy

    missing go.sum entry after ran go mod tidy

    You can use go bug to have a cool, automatically filled out bug template, or fill out the template below.

    Describe the bug

    Following docs, after initial command wire, then after go mod tidy, subsequent go generate ./... reports:

    /go/pkg/mod/github.com/google/[email protected]/cmd/wire/main.go:34:2: missing go.sum entry for module providing package github.com/google/subcommands (imported by github.com/google/wire/cmd/wire); to add:
            go get github.com/google/wire/cmd/[email protected]
    /go/pkg/mod/github.com/google/[email protected]/cmd/wire/main.go:36:2: missing go.sum entry for module providing package github.com/pmezard/go-difflib/difflib (imported by github.com/google/wire/cmd/wire); to add:
            go get github.com/google/wire/cmd/[email protected]
    /go/pkg/mod/github.com/google/[email protected]/internal/wire/copyast.go:21:2: missing go.sum entry for module providing package golang.org/x/tools/go/ast/astutil (imported by github.com/google/wire/internal/wire); to add:
            go get github.com/google/wire/internal/[email protected]
    /go/pkg/mod/github.com/google/[email protected]/internal/wire/parse.go:30:2: missing go.sum entry for module providing package golang.org/x/tools/go/packages (imported by github.com/google/wire/internal/wire); to add:
            go get github.com/google/wire/internal/[email protected]
    /go/pkg/mod/github.com/google/[email protected]/internal/wire/analyze.go:26:2: missing go.sum entry for module providing package golang.org/x/tools/go/types/typeutil (imported by github.com/google/wire/cmd/wire); to add:
            go get github.com/google/wire/cmd/[email protected]
    wire_gen.go:3: running "go": exit status 1
    

    To Reproduce

    I use this command to reproduce the problem:

    docker build - <<EOF
    FROM golang
    WORKDIR /myproject
    RUN go mod init myproject
    
    RUN echo '// +build wireinject' >> wire.go
    RUN echo 'package main' >> wire.go
    RUN echo 'import ("strings"; "github.com/google/wire")' >> wire.go
    RUN echo 'func initReader(s string) *strings.Reader {' >> wire.go
    RUN echo '	panic(wire.Build(strings.NewReader))' >> wire.go
    RUN echo '}' >> wire.go
    
    RUN go get github.com/google/wire/cmd/wire
    RUN wire
    RUN cat wire_gen.go
    RUN go mod tidy
    RUN cat go.mod
    RUN go generate ./...
    EOF
    

    Expected behavior

    go generate ./... should run without error

    Version

    go 1.16
    
    github.com/google/wire v0.5.0
    

    Additional context

    Following the error message and run the suggest go get commands fixes the problem. But as soon as I run go mod tidy, go generate ./... reports error

    opened by jackieli-tes 2
  • report wire build version

    report wire build version

    implements #169

    Below is the command to report wire build version info wire version

    cla: yes 
    opened by muyizixiu 3
  • Enable runtime choice of implementation similar to hard-coded wire.Bind

    Enable runtime choice of implementation similar to hard-coded wire.Bind

    Is your feature request related to a problem? Please describe.

    During development, oftentimes one doesn't want to connect to all the real things (such as a Redis for running a lock server) and a local implementation using Semaphore helps do the locking without the runtime dependency.

    We've got a common leaf "config" module with a DefaultSet we can pull in everywhere that has wire.Value to all of the various config source merged values (defaults, file, env, CLI switches, e.g.) I tried to make a provider something like

    func NewLockServerFromConfig(cfg *config.Config) LockServer {
      switch cfg.LockServerType {
        case "semaphore":
          return NewSemaphoreLockServer()
        case "redlock":
          return NewRedlockLockServer()
    }
    

    But… as both of the NewSemaphoreLockServer() and NewRedlockLockServer() were generated from a wire.Build directive, the end result was a cycle detected between the provider -> NewSemaphoreLockServer -> DefaultSet -> provider

    Describe the solution you'd like

    I solved it by having the provider receive all possible implementations, but this seems a bit cumbersome to instantiate things that will never be used… I'd much rather some mechanism similar to how Guice can inject either LockServer or Provider<LockServer> - if the provider above could take for instance func() *SemaphoreLockServer and func() *RedlockLockServer as injected args, and not be a cycle when used as a provider, then, LockServer were needed to be injected or built, then it could invoke that provider to make the determination from any runtime signals.

    Describe alternatives you've considered

    The alternative that worked was to inject all of the implementations to the provider and return the right one, but then that requires instantiation of all things.

    The idea of doing the guice-like provider func could work too, but there could be other alternatives, such as maybe some sort of wire.Bind function… if a function could be called (and have parameters injected into it such as the *Config) then it could return JUST the type of the object, which could then be injected as usual - obviously this would be slightly different than the current mechanism, where the Bind's type is just used to do generation, but in this condition where a function is used, it could still possibly generate some runtime code that switched on the type in some way to take alternative actions… might be cleaner/more idiomatic to return the concrete type and have wire take care of the rest; just throwing it out there as an idea…

    Additional context

    Add any other context or screenshots about the feature request here.

    opened by scr-oath 0
  • support method provider

    support method provider

    Is your feature request related to a problem? Please describe.

    I used to write type method instead of a single NewXxx. eg:

    // declare NewDog method, which belong to type Animals
    
    type Animals struct{}
    
    func NewAnimals() *Animals {
    	return &Animals{}
    }
    
    type Dog struct{}
    
    func (f *Animals) NewDog() *Dog {
    	return &Dog{}
    }
    
    
    

    frustrated when I want to use it as wire provider, I got unknown pattern error. eg:

    // wire.go
    
    //+build wireinject
    //go:generate wire
    
    func InitDog() *animals.Dog {
    	panic(wire.Build(
    		animals.NewAnimals,
    		(*animals.Animals).NewDog, // this line will trigger error
    	))
    }
    

    Describe the solution you'd like

    I want the above usage could be work. Generated code should looks like:

    // wire_gen.go
    
    func InitDog() *animals.Dog {
    	animalsAnimals := animals.NewAnimals()
    	dog := (*animals.Animals).NewDog(animalsAnimals)
    	return dog
    }
    
    opened by sin5th 0
  • Panic in case of nil cleanup function

    Panic in case of nil cleanup function

    Describe the bug

    It is possible to pass provider function with nil value cleanup function (cleanup == nil) in case of provider with 3 values signature: init, cleanup, error. It would lead to panic in case of abnormal start of application.

    panic: runtime error: invalid memory address or nil pointer dereference
    [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0xbd7492]
    
    goroutine 1 [running]:
    main.NewServiceContainer.func1()
    	/home/user/go/some-project-api/cmd/some-project-api/wire_gen.go:129 +0x32
    main.serve(0xc000256580, 0x13256b8, 0x0, 0x0, 0xe66940, 0xc000548eb0)
    	/home/user/go/some-project-api/cmd/some-project-api/main.go:96 +0x11a
    github.com/spf13/cobra.(*Command).execute(0xc000256580, 0xc000118190, 0x0, 0x0, 0xc000256580, 0xc000118190)
    	/home/user/go/pkg/mod/github.com/spf13/[email protected]/command.go:850 +0x47c
    github.com/spf13/cobra.(*Command).ExecuteC(0xc000256580, 0xc0004edf70, 0x1, 0x1)
    	/home/user/go/pkg/mod/github.com/spf13/[email protected]/command.go:958 +0x375
    github.com/spf13/cobra.(*Command).Execute(...)
    	/home/user/go/pkg/mod/github.com/spf13/[email protected]/command.go:895
    main.main()
    	/home/user/go/some-project-api/cmd/some-project-api/main.go:84 +0x193
    

    To Reproduce

    Define some providers with 3 return values signature, where cleanup function value is nil, like

    init.go

    func initWireExample() (*bytes.Buffer, func(), error) {
    	return &bytes.Buffer{}, nil, nil
    }
    
    func initWireExampleSecond(b *bytes.Buffer) (io.Reader, func(), error) {
    	return b, nil, nil
    }
    

    Use them in wire.Build. Generate wire gen. Run application with some error on initialization step. There is only panic in console, but no original error.

    Expected behavior

    There is an error on generation if case of nil value cleanup function. or Original error is printed to console. or Message describing what is wrong with cleanup is printed (cleanup == nil).

    Version

    github.com/google/wire v0.4.0
    

    Does this issue reproduce with the latest release of Wire?

    Yes, I've tried on github.com/google/wire v0.5.0 too.

    Additional context

    I understand that it is possible to use 2 return value function signature for providers, so it's really minor, but it can be really hard to understand what is going wrong in case described above.

    Proposed solution

    Set some guard code in wire_gen.go: check cleanup function to nil equality before calling cleanup code.

    What version of Go are you using (go version)?

    $ go version
    go version go1.15.7 linux/amd64
    

    What operating system and processor architecture are you using (go env)?

    go env Output
    $ go env
    GO111MODULE=""
    GOARCH="amd64"
    GOBIN=""
    GOCACHE="/home/user/.cache/go-build"
    GOENV="/home/user/.config/go/env"
    GOEXE=""
    GOFLAGS=""
    GOHOSTARCH="amd64"
    GOHOSTOS="linux"
    GOINSECURE=""
    GOMODCACHE="/home/user/go/pkg/mod"
    GONOPROXY=""
    GONOSUMDB=""
    GOOS="linux"
    GOPATH="/home/user/go"
    GOPRIVATE=""
    GOPROXY="https://proxy.golang.org,direct"
    GOROOT="/usr/local/go/go1.15.7"
    GOSUMDB="sum.golang.org"
    GOTMPDIR=""
    GOTOOLDIR="/usr/local/go/go1.15.7/pkg/tool/linux_amd64"
    GCCGO="gccgo"
    AR="ar"
    CC="gcc"
    CXX="g++"
    CGO_ENABLED="1"
    GOMOD="/home/user/go/project-api/go.mod"
    CGO_CFLAGS="-g -O2"
    CGO_CPPFLAGS=""
    CGO_CXXFLAGS="-g -O2"
    CGO_FFLAGS="-g -O2"
    CGO_LDFLAGS="-g -O2"
    PKG_CONFIG="pkg-config"
    GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build124353218=/tmp/go-build -gno-record-gcc-switches"
    uname -sr: Linux 5.4.0-72-generic
    Distributor ID:	Ubuntu
    Description:	Ubuntu 20.04.2 LTS
    Release:	20.04
    Codename:	focal
    /lib/x86_64-linux-gnu/libc.so.6: GNU C Library (Ubuntu GLIBC 2.31-0ubuntu9.3) stable release version 2.31.
    gdb --version: GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
    
    opened by rpromyshlennikov 0
  • Adding capability to auto-bind a type to interfaces it implements

    Adding capability to auto-bind a type to interfaces it implements

    Implements #242.

    I think motivation for this was covered well by @bradleypeabody in the linked issue, so I won't go into detail here, but I'll copy over a statement I liked:

    The Go language itself resolves interfaces based solely on method signatures, not an explicit implements mechanism - I don't see why wire wouldn't follow the same behavior. wire.Bind can still be used to resolve ambiguous cases.

    Summary

    Public API

    • Addition of wire.AutoBind() and corresponding AutoBinding type.

    Internals

    • Addition of a new AutoBinding type to the internal/wire package that records a concrete type and position of its token.
    • AutoBinding fields added to the ProviderSet, providerSetSrc, and ProviderType structs.
    • Check for fully unused AutoBindings.
    • processAutoBind() to handle the parsing
    • The code to actually implement the auto-binding behavior was added to (*ProviderSet).For(). This makes it easy to give explicit wire.Bind()s precedence. If a type is not found in the providerMap, and it is an interface, the []AutoBindings list is checked for a type that implements the interface. If one is found, it is added to the providerMap and srcMap to avoid future searches for the same type. If no such type is found, behavior is as before.

    Tests

    • A simpler InterfaceAutoBinding showing automated binding of Bar -> Fooer.
    • A more complex InterfaceExplicitBindingPreferredOverAutoBinding, which is fairly self-descriptive.

    I've tried out my fork on a project that was already using wire, and so far it is working rather nicely. It has made the wire.Build()s a bit nicer I think - especially for cases where one concrete type implements 2 or more interfaces. Coupling is reduced too, since the implementation and the interface don't need to directly know about each other. Usage seems more "Go-ish" from my (obviously a bit biased) point of view.

    Any feedback/comments/concerns is appreciated! This was my first time reading through wire's code (though I've used it a lot), so I'll be happy to make any changes necessary if there are concerns around the structure of the implementation.

    cla: yes 
    opened by dabbertorres 1
  • Please attach platform binaries to Wire release

    Please attach platform binaries to Wire release

    Is your feature request related to a problem? Please describe.

    I'd like to be able to use Wire without compiling my own binary

    Describe the solution you'd like

    Please just attach binary files to the releases page

    Describe alternatives you've considered

    I'm currently hosting binaries on my own fork

    Additional context

    I'm mainly opening this issue because I created a set of release bazel rules for Wire and wanted to share. I'm already hosting the binaries on my own fork, so it would be nice to have an official release, but I'm working around it for now.

    enhancement 
    opened by dmayle 0
  • Wire should not put a go:generate line into wire_gen.go

    Wire should not put a go:generate line into wire_gen.go

    Is your feature request related to a problem? Please describe.

    Wire puts the following line into the generated file:

    //go:generate wire
    

    We have a lot of generated files (many megabytes of total size), which is why we don't commit files to git and just require a simple go generate ./... to be run by users or before tests are run. We define all commands in //go:generate ... comments which are needed to compile the program, so that step is already required in order to compile the program.

    Since wire is the only one generating a new //go:generate line into the already generated file, when you run go generate ./... again, the wire code generation gets triggered twice. While this is not the worst thing in the world, I think it would be great if this could be at least configured.

    Describe the solution you'd like

    Either don't generate this line at all, or add a CLI configuration option --no-go-generate could be introduced, which if present skips this line:

    https://github.com/google/wire/blob/f285c073b52078f165ca19f3ceb192f0f50f3934/internal/wire/wire.go#L253

    Describe alternatives you've considered

    1. removing the line with sed

    This is unacceptable, since sed has different implementations on different operating systems. It's not worth the trouble and just results in bugs and weird behaviour.

    1. run go generate -tags wireinject ./...

    This will ignore the generated code because the generated wire_gen.go has a !wireinject flag. However, everyone working on a project needs to run this command.

    1. ignore

    Ignore this, and just let the wire codeine run twice. It's not too slow so it's ok, but it doesn't feel good.

    Additional context

    https://github.com/google/wire/issues/106 requested a similar feature but for different reasons.

    opened by steebchen 1
Releases(v0.5.0)
  • v0.5.0(Jan 25, 2021)

    New Features

    • Permit specifying build tags for analysis (#252)

    Changed

    • Use full go run command in go:generate comment (#268)

    Bug Fixes

    • internal/wire: fix panic in objectCache.processExpr (#236)
    • internal/wire: copy doc comment for generated injectors (#254)
    • docs: fix syntax error (#255)
    • docs: fix incorrect generated code in example (#277)
    Source code(tar.gz)
    Source code(zip)
  • v0.4.0(Dec 11, 2019)

    New Features

    • FieldsOf provides a pointer type to the field as well as the actual field type for pointers to structs (#208)
    • A new --output_file_prefix flag permits changing the name of the outputted file (#192)

    Bug Fixes

    • Use go/token to determine whether names are keywords (#203)
    • Wire no longer panics when wire.Struct is given a non-struct first argument (#219)
    • Wire no longer emits invalid code for injectors that return their arguments (#222)
    • Wire's go.mod no longer includes unused dependencies (#228)
    Source code(tar.gz)
    Source code(zip)
  • v0.3.0(Jun 18, 2019)

    Wire version 0.3.0 is the first release we are marking as beta. With this release, we are committing to API stability: we do not intend to make backward-incompatible changes going forward. There are new features and breaking changes in this release, see below for details.

    To upgrade to v0.3.0, please upgrade both the Wire command and library.

    Breaking Changes

    • github.com/google/wire is now the single canonical import path. Any code still using github.com/google/go-cloud/wire will no longer be recognized. To upgrade: change github.com/google/go-cloud/wire to github.com/google/wire.
    • The second argument of Bind is now a pointer type to match argument types in other marker functions. If you have code like wire.Bind(new(Fooer), new(MyFoo))), the behavior will change. To upgrade: see the guide for how to migrate.

    New Features

    • A new marker function FieldsOf to inject fields of a struct directly. See the guide for how to use it.
    • A new marker function Struct for struct providers. This will replace the current struct provider syntax in 1.0, so please upgrade as soon as possible. To upgrade: see the guide.
    • The wire help command will be more useful. You can use wire help to list available commands and their descriptions; you can also use wire help [command] to get more detailed information.
    • A new --header_file flag to gen and diff commands for copying copyright headers. Support using a wire:”-” tag to prevent filling certain struct fields.
    • Misc stability and documentation improvements.
    Source code(tar.gz)
    Source code(zip)
  • v0.2.2(May 10, 2019)

  • v0.2.1(Jan 14, 2019)

    Bug Fixes

    • Fixed a bug when an interface is bound to a Value, wire would fail to record it as used.
    • Preserve anonymous imports in wire_gen.go (#94)
    Source code(tar.gz)
    Source code(zip)
  • v0.2.0(Dec 3, 2018)

    • Add support for variadic argument provider functions and injectors (#61, thanks @shantuo!)
    • diff now exits with status 1 for differences and 2 for errors (#90, thanks @vangent!)
    Source code(tar.gz)
    Source code(zip)
Owner
Google
Google ❤️ Open Source
Google
Simple and yet powerful Dependency Injection for Go

goioc/di: Dependency Injection Why DI in Go? Why IoC at all? I've been using Dependency Injection in Java for nearly 10 years via Spring Framework. I'

Go IoC 81 Jul 19, 2021
Dependency Injection and Inversion of Control package

Linker Linker is Dependency Injection and Inversion of Control package. It supports the following features: Components registry Automatic dependency i

Logrange 32 May 6, 2021
🛠 A full-featured dependency injection container for go programming language.

DI Dependency injection for Go programming language. Tutorial | Examples | Advanced features Dependency injection is one form of the broader technique

Goava 95 Jul 14, 2021
Compile-time dependency injection for Go

Dihedral Dihedral is a compile-time injection framework for Go. Getting started > go get -u github.com/dimes/dihedral Create a type you want injected

null 76 Sep 4, 2020
Generated dependency injection containers in go (golang)

Generation of dependency injection containers for go programs (golang). Dingo is a code generator. It generates dependency injection containers based

null 55 Jul 10, 2021
Strict Runtime Dependency Injection for Golang

wire Wire is runtime depedency injection/wiring for golang. It's designed to be strict to avoid your go application running without proper dependency

Muhammad Surya 33 Jul 20, 2021
A reflection based dependency injection toolkit for Go.

⚒️ dig A reflection based dependency injection toolkit for Go. Good for: Powering an application framework, e.g. Fx. Resolving the object graph during

Uber Go 2k Jul 24, 2021
A dependency injection based application framework for Go.

?? Fx An application framework for Go that: Makes dependency injection easy. Eliminates the need for global state and func init(). Installation We rec

Uber Go 2.1k Jul 23, 2021
Compile-time Dependency Injection for Go

Wire: Automated Initialization in Go Wire is a code generation tool that automates connecting components using dependency injection. Dependencies betw

Google 6.1k Jul 23, 2021
An additive dependency injection container for Golang.

Alice Alice is an additive dependency injection container for Golang. Philosophy Design philosophy behind Alice: The application components should not

Minjie Zha 44 Feb 1, 2021
Simple Dependency Injection Container

?? gocontainer gocontainer - Dependency Injection Container ?? ABOUT Contributors: Rafał Lorenz Want to contribute ? Feel free to send pull requests!

Rafał Lorenz 14 Dec 10, 2020
A lightweight yet powerful IoC container for Go projects

Container A lightweight yet powerful IoC container for Go projects. It provides a simple, fluent and easy-to-use interface to make dependency injectio

GoLobby 212 Jul 21, 2021
Serverless Container Workflows

direktiv event-based serverless container workflows Check out our online demo: wf.direktiv.io What is Direktiv? Direktiv is a specification for a serv

vorteil.io pty ltd 86 Jul 22, 2021