Rumah >pembangunan bahagian belakang >Golang >Apakah penyongsangan kawalan dalam bahasa go

Apakah penyongsangan kawalan dalam bahasa go

青灯夜游
青灯夜游asal
2023-01-28 11:12:002026semak imbas

Dalam bahasa Go, Inversion of Control (IoC) ialah prinsip reka bentuk dalam pengaturcaraan berorientasikan objek Ia boleh digunakan untuk mengurangkan gandingan antara kod komputer, yang bermaksud kawalan kod "terbalik" daripada perniagaan kod. ” kepada kod rangka kerja. Kaedah penyongsangan kawalan biasa dipanggil suntikan pergantungan, dan kaedah lain dipanggil "pencarian pergantungan" melalui penyongsangan kawalan, apabila objek dicipta, entiti luaran yang mengawal semua objek dalam sistem merujuk kepada objek yang bergantung padanya. luluskannya.

Apakah penyongsangan kawalan dalam bahasa go

Persekitaran pengendalian tutorial ini: sistem Windows 7, GO versi 1.18, komputer Dell G3.

Apakah itu Penyongsangan Kawalan

Penyongsangan Kawalan (disingkat IoC) ialah prinsip reka bentuk dalam pengaturcaraan berorientasikan objek yang boleh digunakan Kurangkan gandingan antara kod komputer. Kaedah yang paling biasa dipanggil Dependency Injection (DI), dan kaedah lain dipanggil Dependency Lookup. Melalui penyongsangan kawalan, apabila objek dicipta, entiti luaran yang mengawal semua objek dalam sistem menghantar rujukan objek yang bergantung kepadanya. Ia juga boleh dikatakan bahawa kebergantungan disuntik ke dalam objek.

Secara lebih ringkas, jika saya mempunyai pengawal, UserController, ia boleh Code, Read dan Eat Sudah tentu, ia juga mempunyai __construct constructor dan __destruct destructor mencetuskan dirinya sendiri dalam situasi tertentu, seperti permulaan dan apabila sumber dikeluarkan pada penghujung kitaran hayat Tetapi jika kita menganggap bahawa fungsi ini sendiri tidak akan mencetuskan dirinya sendiri, maka bagaimana kita, sebagai pengarang, membiarkannya dilaksanakan. Malah, pengawal saya juga mempunyai ArticleController dan YouBadBadController Bagaimana saya harus mengendalikannya?

Setiap pengguna harus membina dirinya sendiri sebelum bekerja. Kelemahan situasi ini adalah jelas sebenarnya semua Pengawal Apabila berurusan dengan tingkah laku awam, kita sebenarnya boleh melaksanakan dan mengurusnya secara luaran. Kita tidak memerlukan fungsi ajaib lalai Mari kita perkenalkan senario tertentu Katakan saya kini memerlukan setiap pengawal untuk melaksanakan dan memanggil fungsi pemegang. Bagaimanakah kita boleh menyelesaikannya secara munasabah? Jika kita masih perlu melaksanakan kaedah larian sekarang, selepas menambah fungsi larian pada setiap pengawal, adakah kita masih perlu menulis jadual mereka? operasi? Anda boleh membiarkan Perkhidmatan Pengawal awam membantu mengendalikannya. Kami tidak mempertimbangkan warisan sekarang.

Tunggu sebentar, bagaimana Xiaozhi boleh pergi tanpa membaling Bola Poké Di manakah Xiaozhi? Kita perlu membawa pengawal ke atas
class ControllerService{

public functiondo(){

->handle();

 } //去吧比卡丘; }

}

supaya kawalan telah diterbalikkan kepada 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();

Mekanisme pantulan antara muka dalam bahasa Go juga merupakan pantulan Ioc

Aplikasi Golang Inversion of Control (IOC) dalam kejuruteraan

Reka BentukPerpustakaan pihak ketiga yang digunakan:

https://github.com/berkaroad/ioc

Ia agak mudah digunakan, tidak lebih daripada RegisterTo dan Invoke, tetapi mana-mana perpustakaan perlu digabungkan dengan rangka kerja untuk menjadi bermakna.

Apabila bercakap tentang gandingan longgar, mudah untuk memikirkan

antara muka (antara muka)

dalam GO, jadi kami menggunakan antara muka untuk mencapai gandingan longgar antara pelbagai lapisan. Menurut rangka kerja MVC tradisional, secara amnya terdapat beberapa lapisan pada bahagian pelayan, lapisan Pengawal, lapisan Perkhidmatan dan lapisan Modul Dari atas ke bawah, cara mengintegrasikan Ioc ke dalam rangka kerja adalah sesuatu yang patut diterokai.

Direktori

Apakah penyongsangan kawalan dalam bahasa goStruktur panggilan: Memandangkan tiada perkhidmatan, fungsi utama bertindak sebagai Pengawal, Perkhidmatan ialah lapisan perkhidmatan , dan Modul ialah Lapisan data, Sumber ialah lapisan storan dan apl ialah definisi pelbagai antara muka

utama-->Perkhidmatan-->Modul-->Sumber

Untuk menunjukkan panggilan antara perkhidmatan, kami mentakrifkan perkhidmatan1 dan perkhidmatan2 Dua perkhidmatan

melaksanakan

takrifan antara muka setiap lapisan

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)
}
Inisialisasi IOC

Malah, tidak kira bagaimana anda melaksanakannya, ia hanyalah satu contoh NewContainer
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)
}

Lapisan storan (bawah ke atas)

RegisterTo ialah proses pendaftaran Objek mo akan digunakan sebagai pelaksanaan apl. Antara muka sumbernya ialah peta
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)
}

lapisan data

Oleh kerana kami telah mendaftarkan aplikasi.Sumber sebelum ini, kami boleh mendapatkan objek yang melaksanakan antara muka ini apabila Invoke di sini
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
	})
}

Lapisan perkhidmatan

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
	})
}
Utama

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")
}
Ujian

Apakah penyongsangan kawalan dalam bahasa go

Berfikir

我们为什么要用到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视频教程编程教学

Atas ialah kandungan terperinci Apakah penyongsangan kawalan dalam bahasa go. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn