Reference:
Https://studygolang.com/articles/13783?fr=sidebar
https://studygolang.com/articles/7716
First, I'm mysteryof the principle.
I. IOC
The IOC idea is decoupling, relying only on the container and not on the specific class, and when your class has modifications, you need to change the container-related code at most, and the business code is not affected.
Golang's Dependency Injection principle
The steps are as follows: (Golang does not support dynamic creation of objects, so you need to manually create objects and inject them, and Java can create objects dynamically)
1. Read the dependency of the object by reflection (Golang is implemented by tag)
2. Find the object instance in the container
3. If you have the object instance or the factory method that created the object, inject the object or use the factory to create the object and inject
4. If there is no instance of the object, the error
Code implementation
Package Diimport ("Sync" "Reflect" "FMT" "Strings" "Errors") var (errfactorynotfound = errors. New ("Factory not Found")) Type factory = Func () (interface{}, error)//container type Container struct {sync. Mutex singletons map[string]interface{} Factories map[string]factory}//container instantiation func newcontainer () *container {RE Turn &container{singletons:make (map[string]interface{}), Factories:make (map[string]factory),}}// Register the Singleton object func (P *container) Setsingleton (name string, Singleton interface{}) {P.lock () p.singletons[name] = Singleto n P.unlock ()}//Gets the Singleton object func (P *container) Getsingleton (name string) interface{} {return p.singletons[name]}//get instance pair Like Func (P *container) getprototype (name string) (interface{}, error) {factory, OK: = P.factories[name] If!ok { return nil, Errfactorynotfound} return factory ()}//set Instance Object factory func (P *container) setprototype (name string, factor Y Factory) {P.lock () p.factories[name] = FACTory P.unlock ()}//injection dependent func (P *container) ensure (instance interface{}) error {elemtype: = reflect. TypeOf (instance). Elem () Ele: = reflect. ValueOf (instance). Elem () for I: = 0; I < Elemtype.numfield (); i++ {//traversal field FieldType: = Elemtype.field (i) Tag: = FieldType.Tag.Get ("Di")//Get tag diname: = P.inje Ctname (tag) if diname = = "" {continue} var (diinstance interface{} Err error) if P.issingleton (tag) {diinstance = P.getsingleton (diname)} If P.isprototype (tag) {diinstance, err = P.getprototype (diname)} if Err! = Nil {ret Urn Err} if diinstance = = Nil {return errors. New (Diname + "dependency not Found")} ele. Field (i). Set (reflect. ValueOf (diinstance)} return nil}//gets the dependency name that needs to be injected func (P *container) injectname (tag String) string {Tags: = Strin Gs. Split (Tag, ",") IF len (tags) = = 0 {return ""} return tags[0]}//detect if a singleton relies on func (P *container) Issingleton (tag string) bool { Tags: = strings. Split (Tag, ",") for _, Name: = Range Tags {if name = = "Prototype" {return false}} re Turn true}//detects if the instance relies on Func (P *container) isprototype (tag string) bool {Tags: = strings. Split (Tag, ",") for _, Name: = Range Tags {if name = = "Prototype" {return true}} RET Urn false}//print Container internal instance func (P *container) string () string {lines: = make ([]string, 0, Len (p.singletons) +len (p.factories ) +2) lines = append (lines, "singletons:") for name, item: = Range P.singletons {line: = FMT. Sprintf ("%s:%x%s", name, &item, reflect. TypeOf (item). String ()) lines = append (lines, line)} lines = Append (lines, "factories:") for name, item: = Range P.fact ories {line: = FMT. Sprintf ("%s:%x%s", name, &item, reflect. TypeOf (item). String ()) lines = aPpend (lines, line)} return strings. Join (lines, "\ n")}