Is there a better dependency injection pattern in golang?

后端 未结 6 1897
野趣味
野趣味 2021-02-07 09:07

Given this code:

package main

import (
    \"fmt\"
)

type datstr string

type Guy interface {
   SomeDumbGuy() string
}

func (d *datstr) SomeDumbGuy() string          


        
6条回答
  •  醉酒成梦
    2021-02-07 09:38

    You should also try Dargo, which is new but has some features that the facebook one doesn't have. The code is here.

    Here is an example:

    In this example a service called SimpleService will inject a logger. The logger itself is a dargo service that is bound with a creation method. That creation method looks like this:

    func newLogger(ioc.ServiceLocator, ioc.Descriptor) (interface{}, error) {
        return logrus.New(), nil
    }
    

    The binding of SimpleService will provide the struct that should be used to implement the interface. The struct has a field annotated with inject followed by the name of the service to inject. This is the interface and the struct used to implement it:

    type SimpleService interface {
        // CallMe logs a message to the logger!
        CallMe()
    }
    
    // SimpleServiceData is a struct implementing SimpleService
    type SimpleServiceData struct {
        Log *logrus.Logger `inject:"LoggerService_Name"`
    }
    
    // CallMe implements the SimpleService method
    func (ssd *SimpleServiceData) CallMe() {
        ssd.Log.Info("This logger was injected!")
    }
    

    Both the logger service and the SimpleService are bound into the ServiceLocator. This is normally done near the start of your program:

    locator, err := ioc.CreateAndBind("InjectionExampleLocator", func(binder ioc.Binder) error {
            // Binds SimpleService by providing the structure
            binder.Bind("SimpleService", SimpleServiceData{})
    
            // Binds the logger service by providing the creation function 
            binder.BindWithCreator("LoggerService_Name", newLogger).InScope(ioc.PerLookup)
    
            return nil
        })
    

    The returned locator can be used to lookup the SimpleService service. The SimpleService is bound into the Singleton scope (the default scope), which means that it will only be created the first time it is looked up or injected, and never again. The LoggerService, on the other hand is in the PerLookup scope, which means that every time it is injected or looked up a new one will be created.

    This is the code that uses the looked up service:

    raw, err := locator.GetDService("SimpleService")
    if err != nil {
        return err
    }
    
    ss, ok := raw.(SimpleService)
    if !ok {
        return fmt.Errorf("Invalid type for simple service %v", ss)
    }
    
    ss.CallMe()
    

    Any depth of injection is supported (ServiceA can depend on ServiceB which depends on ServiceC and so on). A service can also depend on as many services as it would like (ServiceA can depend on service D, E and F etc). Howerver, services cannot have circular dependencies.

提交回复
热议问题