Go 言語では、制御の反転 (IoC) はオブジェクト指向プログラミングの設計原則であり、コンピューター コード間の結合を減らすために使用できます。つまり、コード制御がオブジェクト指向プログラミングから「逆転」されます。ビジネス コード。」をフレームワーク コードに追加します。制御の反転の一般的な方法は依存関係の注入と呼ばれ、別の方法は「依存関係のルックアップ」と呼ばれます。制御の反転により、オブジェクトの作成時に、システム内のすべてのオブジェクトを制御する外部エンティティが、依存するオブジェクトを参照します。渡してください。
このチュートリアルの動作環境: Windows 7 システム、GO バージョン 1.18、Dell G3 コンピューター。
制御の反転 (Inversion of Control、略して IoC) は、結合を減らすために使用できるオブジェクト指向プログラミングの設計原則です。コンピューターコードの間。最も一般的な方法は依存関係注入 (DI) と呼ばれ、もう 1 つの方法は依存関係ルックアップと呼ばれます。制御の反転により、オブジェクトが作成されると、システム内のすべてのオブジェクトを制御する外部エンティティが、依存するオブジェクトの参照をそれに渡します。依存関係がオブジェクトに注入されるとも言えます。
もっと簡単に言うと、コントローラー UserController があれば、コーディング、読み取り、食べることができます。もちろん、暗黙的な __construct コンストラクターと __destruct デストラクターもあります。これらのデフォルト関数はわかっています。ライフサイクルの終わりにリソースが解放されるとき、初期化などの特定の状況で自動的にトリガーされますが、これらの関数自体が自動的にトリガーされないと仮定すると、作成者としてどうすればそれらを実行できるでしょうか。実は、私のコントローラーにも ArticleController と YouBadBadController があるんですが、どうやって扱えばいいのでしょうか?
各ユーザーは作業する前に自分自身をビルドする必要があります。記事も作業する前に自分自身をビルドする必要があります。この状況の欠点は明らかです。後で紹介するように、各コントローラーをビルドする必要があります。誰もが自分のことを行いますが、彼らはパブリックな動作を扱うときは、実際にそれらを外部で実装および管理できます。デフォルトのマジック関数は必要ありません。具体的なシナリオを紹介します。各コントローラーがハンドル関数を実装して呼び出す必要があるとします。どうすれば合理的に完了できますか? 各コントローラーに run 関数を追加した後、今でも run メソッドを実行する必要がある場合でも、そのスケジュールを記述する必要がありますか?
制御の反転は、制御の統合管理ですか?この操作は? パブリックの ControllerService に処理を任せることができますが、現在は継承を考慮していません。
class ControllerService{ public functiondo(){ ->handle(); } //去吧比卡丘; } }
ちょっと待って、Xiaozhi はモンスターボールを投げずにどうやって行くことができますか? Xiaozhi はどこですか?コントロールがControllerServiceに反転されるように、コントローラを
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();
に渡す必要があります;
Go言語のインターフェース・リフレクション・メカニズムもIoc
設計
使用されるサードパーティ ライブラリ:https: //github.com/berkaroad/ioc
使い方は比較的簡単で、RegisterTo と Invoke だけですが、意味のあるライブラリを使用するにはフレームワークと組み合わせる必要があります。 疎結合というと、GO ではinterface(interface) を思い浮かべやすいため、インターフェイスを使用してさまざまなレイヤー間の疎結合を実現します。
従来の MVC フレームワークによると、通常、サーバー側にはコントローラー層、サービス層、モジュール層のいくつかの層があり、フレームワーク内で Ioc をどのように組み合わせるかが検討の価値があります。main-->Service-->Module-->Resource
呼び出しをデモンストレーションするためにサービス間には、service1 と service2 を定義しました。 2 つのサービス
実装
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) }
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) }
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 }) }
package service import ( "fmt" "github.com/berkaroad/ioc" "github.com/zhaoshoucheng/hodgepodge/IoC/app" ) var ( module app.Module service2 app.Service2 ) type Service1 struct { } func (s1 *Service1) AddData(str string) { service2.AddData(str) fmt.Println("Service1 AddData ", str) module.DataToSave(str) } func (s1 *Service1) DelData(str string) { service2.DelData(str) fmt.Println("Service1 DelData ", str) module.DataToRemove(str) } func init() { s1 := &Service1{} s2 := &Service2{} service2 = s2 //static assert 静态断言做类型检查 func(t app.Service1) {}(s1) func(t app.Service2) {}(s2) app.GetOrCreateRootContainer().RegisterTo(s1, (*app.Service1)(nil), ioc.Singleton) app.GetOrCreateRootContainer().RegisterTo(s2, (*app.Service2)(nil), ioc.Singleton) app.GetOrCreateRootContainer().Invoke(func(mod app.Module) { module = mod }) }
package main import ( "github.com/zhaoshoucheng/hodgepodge/IoC/app" _ "github.com/zhaoshoucheng/hodgepodge/IoC/resource" _ "github.com/zhaoshoucheng/hodgepodge/IoC/module" _ "github.com/zhaoshoucheng/hodgepodge/IoC/service" ) func main() { var s1 app.Service1 app.GetOrCreateRootContainer().Invoke(func(service app.Service1) { s1 = service }) s1.AddData("IOC Test") }#テスト
感想
我们为什么要用到Ioc呢?个人感觉有几点好处 问题 难道就没有问题吗? 第一种写法就会崩溃,第二种正确 原因第一种module 的init 先执行,app.Resource的对象还没有注册。所以init的先后顺序很重要 但这个是凭借字节码进行的排序,有时IDE还不让我们改,所以需要一些控制器去处理这种情况。
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"
以上がGo言語における制御の反転とは何ですかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。