Go言語における制御の反転とは何ですか

青灯夜游
リリース: 2023-01-28 11:12:00
オリジナル
1981 人が閲覧しました

Go 言語では、制御の反転 (IoC) はオブジェクト指向プログラミングの設計原則であり、コンピューター コード間の結合を減らすために使用できます。つまり、コード制御がオブジェクト指向プログラミングから「逆転」されます。ビジネス コード。」をフレームワーク コードに追加します。制御の反転の一般的な方法は依存関係の注入と呼ばれ、別の方法は「依存関係のルックアップ」と呼ばれます。制御の反転により、オブジェクトの作成時に、システム内のすべてのオブジェクトを制御する外部エンティティが、依存するオブジェクトを参照します。渡してください。

Go言語における制御の反転とは何ですか

このチュートリアルの動作環境: 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

#の具体化です。 ## Golang Inversion of Control (IOC) がプロジェクトに適用されます

設計

使用されるサードパーティ ライブラリ:

https: //github.com/berkaroad/ioc

使い方は比較的簡単で、RegisterTo と Invoke だけですが、意味のあるライブラリを使用するにはフレームワークと組み合わせる必要があります。

疎結合というと、GO では

interface(interface) を思い浮かべやすいため、インターフェイスを使用してさまざまなレイヤー間の疎結合を実現します。

従来の MVC フレームワークによると、通常、サーバー側にはコントローラー層、サービス層、モジュール層のいくつかの層があり、フレームワーク内で Ioc をどのように組み合わせるかが検討の価値があります。

ディレクトリ

Go言語における制御の反転とは何ですか

呼び出し構造: サービスがないため、メイン関数はコントローラーとして機能し、サービスはサービス層になります。 、モジュールはデータ層、リソースはストレージ層、アプリはさまざまなインターフェイスの定義です

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)
}
ログイン後にコピー

IOC 初期化
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)
}
ログイン後にコピー

実際、どのように実装しても、それは単なる単一インスタンス NewContainer

ストレージ層 (ボトムアップ) )
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 は登録プロセスです。mo オブジェクトは、後で app.Resource インターフェイスの実装として使用されます。その基礎となる実装は、map

data です。 layer
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
	})
}
ログイン後にコピー

すでに app.Resource を登録しているため、ここで呼び出すとこのインターフェイスを実装するオブジェクトを取得できます

サービス レイヤー
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")
}
ログイン後にコピー
#テスト

Go言語における制御の反転とは何ですか感想

我们为什么要用到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还不让我们改,所以需要一些控制器去处理这种情况。

【相关推荐:Go视频教程编程教学

以上がGo言語における制御の反転とは何ですかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート