Go言語における制御の反転とは何ですか
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
#の具体化です。 ## Golang Inversion of Control (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 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)
}
ログイン後にコピー
実際、どのように実装しても、それは単なる単一インスタンス NewContainerpackage 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)
}
ログイン後にコピー
RegisterTo は登録プロセスです。mo オブジェクトは、後で app.Resource インターフェイスの実装として使用されます。その基礎となる実装は、mappackage 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) }
data です。 layerpackage 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 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 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")
}
ログイン後にコピー#テスト
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还不让我们改,所以需要一些控制器去处理这种情况。 以上がGo言語における制御の反転とは何ですかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。
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"

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











Go ではファイルを安全に読み書きすることが重要です。ガイドラインには以下が含まれます。 ファイル権限の確認 遅延を使用してファイルを閉じる ファイル パスの検証 コンテキスト タイムアウトの使用 これらのガイドラインに従うことで、データのセキュリティとアプリケーションの堅牢性が確保されます。

Go データベース接続の接続プーリングを構成するにはどうすればよいですか?データベース接続を作成するには、database/sql パッケージの DB タイプを使用します。同時接続の最大数を制御するには、MaxOpenConns を設定します。アイドル状態の接続の最大数を設定するには、ConnMaxLifetime を設定します。

Golang と C++ は、それぞれガベージ コレクションと手動メモリ管理のプログラミング言語であり、構文と型システムが異なります。 Golang は Goroutine を通じて同時プログラミングを実装し、C++ はスレッドを通じて同時プログラミングを実装します。 Golang のメモリ管理はシンプルで、C++ の方がパフォーマンスが優れています。実際の場合、Golang コードはより簡潔であり、C++ には明らかにパフォーマンス上の利点があります。

Go フレームワーク アーキテクチャの学習曲線は、Go 言語とバックエンド開発への慣れ、選択したフレームワークの複雑さ、つまり Go 言語の基本の十分な理解によって決まります。バックエンドの開発経験があると役立ちます。フレームワークの複雑さが異なると、学習曲線も異なります。

Golang でリストのランダムな要素を生成する方法: rand.Intn(len(list)) を使用して、リストの長さの範囲内でランダムな整数を生成し、その整数をインデックスとして使用して、リストから対応する要素を取得します。

Go フレームワークは、その高いパフォーマンスと同時実行性の利点で際立っていますが、比較的新しい、開発者エコシステムが小さい、一部の機能が欠けているなどの欠点もあります。さらに、急速な変化と学習曲線はフレームワークごとに異なる場合があります。 Gin フレームワークは、効率的なルーティング、組み込みの JSON サポート、強力なエラー処理機能により、RESTful API を構築するための一般的な選択肢です。

ベスト プラクティス: 明確に定義されたエラー タイプ (エラー パッケージ) を使用してカスタム エラーを作成する 詳細を提供する エラーを適切にログに記録する エラーを正しく伝播し、非表示または抑制しないようにする コンテキストを追加するために必要に応じてエラーをラップする

Golang フレームワークの利点 Golang は、マイクロサービスや分散システムに特に適した高性能の同時プログラミング言語です。 Golang フレームワークは、既製のコンポーネントとツールのセットを提供することで、これらのアプリケーションの開発を容易にします。 Golang フレームワークの主な利点の一部を次に示します。 1. 高いパフォーマンスと同時実行性: Golang 自体は、その高いパフォーマンスと同時実行性で知られています。コードの同時実行を可能にする軽量のスレッド メカニズムであるゴルーチンを使用することで、アプリケーションのスループットと応答性が向上します。 2. モジュール性と再利用性: Golang フレームワークは、モジュール性と再利用可能なコードを奨励します。アプリケーションを独立したモジュールに分割することで、コードを簡単に保守および更新できます。
