Heim > Artikel > Backend-Entwicklung > Was ist die Umkehrung der Kontrolle in der Go-Sprache?
In der Go-Sprache ist Inversion of Control (IoC) ein Entwurfsprinzip in der objektorientierten Programmierung, das verwendet werden kann, um die Kopplung zwischen Computercodes zu reduzieren. Es bedeutet, dass die Codesteuerung vom Geschäftscode zum Framework-Code „umgekehrt“ wird. . Eine übliche Methode zur Umkehrung der Kontrolle wird als Abhängigkeitsinjektion bezeichnet, und eine andere Methode wird als „Abhängigkeitssuche“ durch Umkehrung der Kontrolle bezeichnet. Wenn ein Objekt erstellt wird, verweist eine externe Entität, die alle Objekte im System steuert, auf die Objekte, von denen es abhängt. übergebe es.
Die Betriebsumgebung dieses Tutorials: Windows 7-System, GO Version 1.18, Dell G3-Computer.
Inversion of Control (Inversion of Control, abgekürzt als IoC) ist ein Entwurfsprinzip in der objektorientierten Programmierung, das verwendet werden kann, um die Kopplung zwischen Computercodes zu reduzieren. Die gebräuchlichste Methode heißt Dependency Injection (DI), die andere Methode heißt Dependency Lookup. Durch die Umkehrung der Kontrolle übergibt eine externe Entität, die alle Objekte im System steuert, bei der Erstellung eines Objekts die Referenz des Objekts, von dem sie abhängt, an dieses. Man kann auch sagen, dass Abhängigkeiten in das Objekt eingefügt werden.
Um es einfacher auszudrücken: Wenn ich einen Controller, UserController, habe, kann er programmieren, lesen und essen. Natürlich verfügt er auch über einen impliziten __construct-Konstruktor und einen __destruct-Destruktor. Es wird von selbst ausgelöst, beispielsweise während der Initialisierung, wenn die Ressource am Ende des Lebenszyklus freigegeben wird. Wenn wir jedoch davon ausgehen, dass diese Funktionen selbst nicht von selbst ausgelöst werden, wie können wir als Autoren sie dann ausführen lassen? Tatsächlich verfügt mein Controller auch über ArticleController und YouBadBadController. Wie soll ich damit umgehen?
Bevor Sie arbeiten, sollten Sie sich selbst erstellen. Die Mängel dieser Situation sind offensichtlich Wenn wir mit öffentlichen Verhaltensweisen umgehen, können wir sie tatsächlich von außen umsetzen und verwalten. Wir benötigen nicht die standardmäßige magische Funktion. Lassen Sie uns ein bestimmtes Szenario vorstellen. Angenommen, ich benötige jetzt, dass jeder Controller eine Handle-Funktion implementiert und aufruft. Wie können wir es sinnvoll vervollständigen? Wenn wir jetzt noch eine Ausführungsmethode ausführen müssen, müssen wir nach dem Hinzufügen der Ausführungsfunktion zu jedem Controller noch deren Zeitplan schreiben.
Ist es möglich, eine öffentliche Umkehrung der Steuerung zu verwenden? Diese Operation einheitlich durchführen? Verwenden Sie einfach den ControllerService, um beim Handle zu helfen. Wir ziehen derzeit keine Vererbung in Betracht.
class ControllerService{ public functiondo(){ ->handle(); } //去吧比卡丘; } }
Moment mal, wie kann Xiaozhi gehen, ohne den Pokéball zu werfen? Wo ist Xiaozhi? Wir müssen den Controller überbringen
class ControllerService{ public $handler; public function __construct($handler){ $this->handler=$handler ; } //通过构造函数带入; } // public function setHandler($handler){ $this->handler->handle(); } //通过setter带入; } public function do(){ $this->handler->handle(); } //去吧比卡丘; } } new ControllerService()->setHandler(new UserController())->do();
Auf diese Weise wurde die Steuerung auf den ControllerService umgedreht;
Der Schnittstellenreflexionsmechanismus in der Go-Sprache ist auch die Verkörperung von Ioc
Design
Die verwendete Bibliothek eines Drittanbieters: https://github.com/berkaroad/ioc
Es ist relativ einfach zu verwenden, nichts weiter als RegisterTo und Invoke, aber Jede Bibliothek muss mit dem Framework kombiniert werden. Das macht Sinn.
Wenn es um lose Kopplung geht, denkt man in GO leicht an Schnittstelle, daher verwenden wir Schnittstellen, um eine lose Kopplung zwischen verschiedenen Schichten zu erreichen.
Nach dem traditionellen MVC-Framework gibt es im Allgemeinen mehrere Schichten auf der Serverseite, z. B. die Controller-Schicht, die Service-Schicht und die Modul-Schicht. Von oben nach unten ist es eine Überlegung wert, wie man Ioc in das Framework integriert.
Aufrufstruktur: Da es keinen Dienst gibt, fungiert die Hauptfunktion als Controller, Dienst ist die Dienstschicht, Modul ist die Datenschicht, Ressource ist die Speicherschicht und App ist die Definition verschiedener Schnittstellen
main-- >Service-->Module-->Ressource
Um die Aufrufe zwischen Diensten zu demonstrieren, haben wir zwei Dienste definiert, service1 und service2
Implementierung
package app type Service1 interface { AddData(string) DelData(string) } type Service2 interface { AddData(string) DelData(string) } type Module interface { DataToSave(string) DataToRemove(string) } type Resource interface { Save(string) Remove(string) }
package app import ( "github.com/berkaroad/ioc" "github.com/spf13/viper" ) func GetOrCreateRootContainer() ioc.Container { v := viper.Get("runtime.container") if v == nil { v = ioc.NewContainer() viper.Set("runtime.container", v) } return v.(ioc.Container) }
Egal, wie Sie es hier implementieren, reicht nur eine einzige Instanz von NewContainer aus
package resource import ( "fmt" "github.com/berkaroad/ioc" "github.com/zhaoshoucheng/hodgepodge/IoC/app" ) type ResourceObj struct { name string } func (r *ResourceObj) Save(str string) { fmt.Println(r.name, " Save ", str) } func (r *ResourceObj) Remove(str string) { fmt.Println(r.name, " Remove ", str) } func init() { mo := &ResourceObj{name: "mongo"} // static assert 静态断言类型检测 func(t app.Resource) {}(mo) app.GetOrCreateRootContainer().RegisterTo(mo, (*app.Resource)(nil), ioc.Singleton) //rd := &ResourceObj{name: "redis"} 实现是用的map,所以mong会被覆盖 //app.GetOrCreateRootContainer().RegisterTo(rd, (*app.Resource)(nil), ioc.Singleton) }
RegisterTo ist die Registrierung Prozess, und das MO-Objekt wird später als App behandelt. Die zugrunde liegende Implementierung ist eine Map
package module import ( "fmt" "github.com/berkaroad/ioc" "github.com/zhaoshoucheng/hodgepodge/IoC/app" ) var ( rs app.Resource ) type ModuleObj struct { } func (mo *ModuleObj) DataToSave(str string) { fmt.Println("ModuleObj DataToSave ", str) rs.Save(str) } func (mo *ModuleObj) DataToRemove(str string) { fmt.Println("ModuleObj DataToRemove ", str) rs.Remove(str) } func init() { mo := &ModuleObj{} // static assert 静态断言类型检测 func(t app.Module) {}(mo) app.GetOrCreateRootContainer().RegisterTo(mo, (*app.Module)(nil), ioc.Singleton) app.GetOrCreateRootContainer().Invoke(func(r app.Resource) { rs = r }) }
我们为什么要用到Ioc呢?个人感觉有几点好处
1.解决各种依赖问题,写GO可能都遇到过循环引用问题,越是复杂的系统就越有可能出现这种混乱的调用现象。
2.实现了很好的扩展性,如果存储层想从redis切换到mongo,定义一个相同的对象,替换注册对象就可以轻松实现。
3.易使用,随时随地可以通过Invoke获取相应的接口对象。
问题
难道就没有问题吗?
当然有,就是引用顺序的问题,也就是先register 还是先invoke 这个在例子中感觉很简单,但是在工程中很容易出错
_ "github.com/zhaoshoucheng/hodgepodge/IoC/module" _ "github.com/zhaoshoucheng/hodgepodge/IoC/resource" _ "github.com/zhaoshoucheng/hodgepodge/IoC/service"
_ "github.com/zhaoshoucheng/hodgepodge/IoC/resource" _ "github.com/zhaoshoucheng/hodgepodge/IoC/module" _ "github.com/zhaoshoucheng/hodgepodge/IoC/service"
第一种写法就会崩溃,第二种正确
原因第一种module 的init 先执行,app.Resource的对象还没有注册。所以init的先后顺序很重要
但这个是凭借字节码进行的排序,有时IDE还不让我们改,所以需要一些控制器去处理这种情况。
Das obige ist der detaillierte Inhalt vonWas ist die Umkehrung der Kontrolle in der Go-Sprache?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!