> 백엔드 개발 > Golang > Go 언어에서 제어 역전이란 무엇입니까?

Go 언어에서 제어 역전이란 무엇입니까?

青灯夜游
풀어 주다: 2023-01-28 11:12:00
원래의
2020명이 탐색했습니다.

Go 언어에서 IoC(Inversion of Control)는 객체 지향 프로그래밍의 설계 원칙으로, 컴퓨터 코드 간의 결합을 줄이는 데 사용할 수 있습니다. 이는 코드 제어가 비즈니스 코드에서 프레임워크 코드로 "역전"된다는 의미입니다. . 제어 역전의 일반적인 방법을 종속성 주입이라고 하고, 또 다른 방법을 "종속성 조회"라고 합니다. 제어 역전을 통해 개체가 생성되면 시스템의 모든 개체를 제어하는 ​​외부 엔터티가 해당 개체를 참조합니다. 통과하세요.

Go 언어에서 제어 역전이란 무엇입니까?

이 튜토리얼의 운영 환경: Windows 7 시스템, GO 버전 1.18, Dell G3 컴퓨터.

Inversion of Control이란 무엇입니까

Inversion of Control(IoC로 약칭)은 컴퓨터 코드 간의 결합을 줄이는 데 사용할 수 있는 객체 지향 프로그래밍의 설계 원칙입니다. 가장 일반적인 방법은 DI(종속성 주입)이고 다른 방법은 "종속성 조회"입니다. 제어 역전을 통해 객체가 생성되면 시스템의 모든 객체를 제어하는 ​​외부 엔터티가 자신이 의존하는 객체의 참조를 전달합니다. 의존성이 객체에 주입된다고도 말할 수 있습니다.

더 간단하게 말하면 UserController라는 컨트롤러가 있으면 코딩, 읽기, 식사가 가능합니다. 물론 암시적인 __construct 생성자와 __destruct 소멸자도 있습니다. 수명 주기가 끝날 때 리소스가 해제될 때 초기화하는 동안 자체적으로 트리거되지만 이러한 기능 자체가 스스로 트리거되지 않는다고 가정하면 작성자로서 어떻게 실행되도록 할 수 있습니까? 실제로 내 컨트롤러에는 ArticleController 및 YouBadBadController도 있습니다. 이를 어떻게 처리해야 합니까?

사용자는 각자 자신의 일을 해야 합니다. 기사, 또한 작업하기 전에 스스로 구축해야 합니다. 나중에 소개하겠지만 각 컨트롤러는 스스로 해야 합니다. thing.은 실제로 컨트롤러입니다. 공개 동작을 처리할 때 실제로 외부에서 구현하고 관리할 수 있습니다. 기본 매직 기능은 필요하지 않습니다. 이제 핸들 기능을 구현하고 호출하기 위해 각 컨트롤러가 필요하다고 가정해 보겠습니다. 지금 실행 메서드를 실행해야 하는 경우 각 컨트롤러에 실행 기능을 추가한 후에도 일정을 작성해야 합니까?

공개 제어 반전을 사용하여 관리할 수 있나요? 이 작업을 균일하게 처리하려면 ControllerService를 사용하세요. 지금은 상속을 고려하지 않습니다.

class ControllerService{

public functiondo(){

->handle();

 } //去吧比卡丘; }

}
로그인 후 복사

잠깐만요, 샤오지는 포켓볼을 던지지 않고 어떻게 갈 수 있나요? 컨트롤러를 가져와야 합니다

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();
로그인 후 복사

이런 방식으로 제어가 ControllerService로 역전되었습니다.

Go 언어의 인터페이스 리플렉션 메커니즘도 Ioc의 구현입니다

Golang IOC(Inversion of Control)는 엔지니어링에 적용됨

Design

사용된 타사 라이브러리: https://github.com/berkaroad/ioc

RegisterTo 및 Invoke 외에는 사용이 비교적 간단하지만, 모든 라이브러리는 프레임워크와 결합되어야 합니다.

느슨한 결합이라고 하면 GO에서는 인터페이스를 생각하기 쉽기 때문에 다양한 계층 간의 느슨한 결합을 구현하기 위해 인터페이스를 사용합니다.

기존 MVC 프레임워크에 따르면 일반적으로 서버 측에는 컨트롤러 레이어, 서비스 레이어, 모듈 레이어 등 여러 레이어가 있습니다. Ioc를 프레임워크에 통합하는 방법은 살펴볼 가치가 있습니다.

Directory

Go 언어에서 제어 역전이란 무엇입니까?

호출 구조: 서비스가 없으므로 주요 기능이 컨트롤러 역할을 하고, 서비스가 서비스 레이어, 모듈이 데이터 레이어, 리소스가 스토리지 레이어, 앱이 정의 역할을 합니다. 다양한 인터페이스의
main-- >Service-->Module-->Resource
서비스 간 호출을 보여주기 위해 service1과 service2

implementation

두 가지 서비스를 정의했습니다. 의 각 레이어

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 객체는 나중에 앱으로 처리됩니다. Resource 인터페이스의 구현은 map

data 레이어

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를 등록했기 때문입니다. 여기에서 호출하면 이 인터페이스를 구현하는 객체를 얻을 수 있습니다

service Layers

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
	})
}
로그인 후 복사

Main

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")
}
로그인 후 복사

Testing

Go 언어에서 제어 역전이란 무엇입니까?

Thinking

我们为什么要用到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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿