> 백엔드 개발 > Golang > Go 언어 의존성 주입이란 무엇입니까?

Go 언어 의존성 주입이란 무엇입니까?

青灯夜游
풀어 주다: 2023-01-28 09:04:39
원래의
1857명이 탐색했습니다.

Go 언어에서 DI(종속성 주입)는 필요할 때 구성 요소 간의 종속성을 분리하는 디자인 패턴입니다. 서로 다른 구성 요소는 통합 인터페이스를 통해 다른 구성 요소의 객체와 상태를 얻을 수 있습니다. 종속성 주입의 이점은 분리이며, 분리는 향상된 코드 확장성, 향상된 코드 유지 관리, 보다 쉬운 단위 테스트 등 더 많은 이점을 가져올 수 있습니다.

Go 언어 의존성 주입이란 무엇입니까?

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

의존성 주입이란 무엇인가요?

이 단어를 처음 들었을 때 발음하기가 어려웠습니다. 아마도 봄철을 공부한 많은 학생들이 이것이 매우 기본적이고 이해하기 쉬운 지식이라고 생각하지만, 저는 이 단어를 한번도 배운 적이 없기 때문입니다. Java와 Spring이라 처음 이 단어를 접했을 때 매우 혼란스러웠습니다.

Dependency Injection, 영어 이름은 의존성 주입, 줄여서 DI입니다. 종속성이라는 단어는 이해하기 쉽습니다. 소프트웨어 설계에는 아키텍처 모듈에서 기능적 방법에 이르기까지 크고 작은 종속성이 있습니다.

예를 들어, 새로운 A보다 새로운 B가 생성되어야 하고, A는 B에 종속됩니다. 이때 B는 A의 종속성이고, A는 B를 제어하며, AB와 B 사이에는 결합 관계가 있다고 말할 수 있습니다. 코드 디자인 아이디어는 최고의 느슨한 결합을 달성할 수 있습니다. 어느 날 B를 변환해야 한다면 A도 변환해야 합니다. 이것이 종속성이라면 문제가 없을 수 있지만 A->B->C->D->E->F 사이에 일련의 종속성이 있는 경우 변환하는 것이 매우 번거로울 것입니다.

이때, 그들 사이의 강력한 결합을 분리할 무언가가 필요합니다. 어떻게 분리할 수 있을까요? 우리는 A에서 B까지의 통제권을 제3자에게 넘겨줄 수 밖에 없습니다. 이런 아이디어를 Inversion of Control(IOC Inversion Of Control)이라고 하며, 이 제3자를 IOC 컨테이너라고 합니다. IOC 컨테이너가 해야 할 일은 새로운 B를 생성한 다음 이 B의 인스턴스를 A에 주입하는 것입니다. 그러면 A는 일반적으로 B 기반 메서드를 사용할 수 있습니다. 이 프로세스를 종속성 주입이라고 하며 IOC 기반 이 메서드를 호출합니다. 의존성 주입.

간단히 말하면 DI(종속성 주입)는 구성 요소 간의 종속성을 분리하는 디자인 패턴입니다. 필요한 경우 다양한 구성 요소가 통합 인터페이스를 통해 다른 구성 요소의 개체와 상태를 얻을 수 있습니다. Go 언어의 인터페이스 디자인은 타사 종속성 주입 프레임워크(예: Java 등)를 사용해야 하는 많은 상황을 방지합니다. 우리의 주입 솔루션은 Dager 또는 Guice와 유사한 주입 솔루션을 거의 제공하지 않으며 개체와 구성 요소 간의 종속성을 수동으로 구성하지 않는 데 중점을 둡니다.

의존성 주입의 이점

의존성 주입의 개념을 이해하려면 이것이 가져오는 가장 큰 이점인 디커플링도 이해해야 합니다.

그리고 분리는 향상된 코드 확장성, 향상된 코드 유지 관리, 보다 쉬운 단위 테스트 등 더 많은 이점을 가져올 수 있습니다.

그럼 종속성 주입을 구현하는 방법은 무엇입니까?

Java에는 다음과 같은 메소드가 있습니다.

  • setter 메소드 주입: 외부 컨테이너가 종속 유형의 객체를 호출할 수 있도록 특정 속성의 공개 설정 메소드를 구현합니다.

  • 인터페이스 기반 주입: 종속 유형의 개체를 주입하기 위해 외부 컨테이너에 대한 특정 인터페이스를 구현합니다.

  • 생성자 기반 주입: 특정 매개변수로 생성자를 구현하고 새 객체를 생성할 때 종속 유형의 객체를 전달합니다.

  • 주석 기반 주입: 코드에 특정 키워드를 추가하여 주입을 수행합니다.

주석은 주석과 마찬가지로 코드로 실행되지 않고 특별히 다른 사람들이 읽을 수 있도록 하는 가장 일반적인 방법입니다. 그러나 주석을 읽는 사람은 전적으로 사람이고, 사람 이외의 주석을 읽는 주요 독자는 프레임워크나 프리컴파일러입니다.

Go 의존성 주입-와이어

wire는 주석 기반 의존성 주입 방법입니다. wire는 Google의 오픈 소스 종속성 주입 도구로, 특수 go 파일에서 유형 간의 종속성을 wire에 알려 주기만 ​​하면 됩니다. 자동으로 코드를 생성하고, 지정된 유형의 객체를 생성하고, 해당 종속성을 조합하는 데 도움을 줍니다. wire是 Google 开源的一个依赖注入工具,我们只需要在一个特殊的go文件中告诉wire类型之间的依赖关系,它会自动帮我们生成代码,帮助我们创建指定类型的对象,并组装它的依赖。

wire有两个基础概念,Provider(构造器)和Injector(注入器)。

通过提供provider函数,让wire知道如何产生这些依赖对象。wire根据我们定义的injector函数签名,生成完整的injector函数,injector函数是最终我们需要的函数,它将按依赖顺序调用provider

wire的要求很简单,新建一个wire.go文件(文件名可以随意),创建我们的初始化函数。比如,我们要创建并初始化一个Mission

wire에는 Provider(생성자)와 Injector(인젝터)라는 두 가지 기본 개념이 있습니다. 🎜🎜 provider 기능을 제공하여 wire에 이러한 종속 개체를 생성하는 방법을 알립니다. wire는 우리가 정의한 injector 함수 서명을 기반으로 완전한 injector 함수를 생성합니다. need. 의존성 순서에 따라 provider를 호출하는 함수입니다. 🎜🎜wire에 대한 요구 사항은 매우 간단합니다. 새 wire.go 파일(파일 이름은 임의적일 수 있음)을 만들고 초기화 기능을 만듭니다. 예를 들어 Mission 객체를 생성하고 초기화하려는 경우 다음과 같이 할 수 있습니다. 🎜
//+build wireinject

package main

import "github.com/google/wire"

func InitMission(name string) Mission {
  wire.Build(NewMonster, NewPlayer, NewMission)
  return Mission{}
}
로그인 후 복사

첫 번째 줄에서 +build wireinject라는 주석을 볼 수 있는데, 이는 이것이 인젝터임을 나타냅니다. +build는 실제로 Go 언어의 기능입니다. C/C++의 조건부 컴파일과 마찬가지로 go build 실행 시 일부 옵션을 전달할 수 있으며, 이러한 옵션에 따라 특정 파일의 컴파일 여부가 결정됩니다. wire 도구는 wireinject를 사용하는 파일만 처리하므로 wire.go 파일에 이를 추가해야 합니다. +build其实是 Go 语言的一个特性。类似 C/C++ 的条件编译,在执行go build时可传入一些选项,根据这个选项决定某些文件是否编译。wire工具只会处理有wireinject的文件,所以我们的wire.go文件要加上这个。

在函数中,我们调用wire.Build()将创建Mission所依赖的类型的构造器传进去。例如,需要调用NewMission()创建Mission类型,NewMission()接受两个参数一个Monster类型,一个Player类型。Monster类型对象需要调用NewMonster()创建,Player类型对象需要调用NewPlayer()创建。所以NewMonster()NewPlayer()我们也需要传给wire

함수에서는 wire.Build()를 호출하여 Mission이 의존하는 유형의 생성자를 전달합니다. 예를 들어, Mission 유형을 생성하려면 NewMission()을 호출해야 합니다. NewMission()은 두 개의 매개변수와 Monster<를 허용합니다. /code> 유형입니다. <code>Monster 유형의 객체는 NewMonster()를 호출하여 생성해야 하고, Player 유형의 객체는 NewPlayer()를 호출하여 생성해야 합니다. . 따라서 NewMonster()NewPlayer()wire에 전달해야 합니다.

wire.go 파일을 작성하고 wire 명령어를 실행하면 wire_gen.go 파일이 자동으로 생성됩니다.

// Code generated by Wire. DO NOT EDIT.

//go:generate wire
//+build !wireinject

package main

// Injectors from wire.go:

func InitMission(name string) Mission {
  player := NewPlayer(name)
  monster := NewMonster()
  mission := NewMission(player, monster)
  return mission
}
로그인 후 복사

와이어가 자동으로 InitMission 메서드를 생성하는 것을 볼 수 있습니다. 이 메서드에서는 플레이어, 몬스터, 미션이 순차적으로 초기화됩니다. 그런 다음 주 함수에서 이 InitMission만 호출하면 됩니다.

func main() {
  mission := InitMission("dj")

  mission.Start()
}
로그인 후 복사

종속성 주입 이전의 코드는 다음과 같았습니다.

func main() {
  monster := NewMonster()
  player := NewPlayer("dj")
  mission := NewMission(player, monster)

  mission.Start()
}
로그인 후 복사

훨씬 더 간단하지 않나요? 여기에는 개체 초기화가 세 개만 있습니다. 그 이상이면 종속성 주입의 이점을 깨닫지 못할 수도 있습니다.

예:

wire.go文件:
// +build wireinject
// The build tag makes sure the stub is not built in the final build.

package di

import (
	"github.com/google/wire"
)

//go:generate kratos t wire
func InitApp() (*App, func(), error) {
	panic(wire.Build(dao.Provider, service.Provider, http.New, grpc.New, NewApp))
}

实现文件:
//dao
var Provider = wire.NewSet(New, NewDB, NewRedis)
//service
var Provider = wire.NewSet(New, wire.Bind(new(pb.Server), new(*Service)))


生成的wire_gen.go 文件:
func InitApp() (*App, func(), error) {
	redis, cleanup, err := dao.NewRedis()
	if err != nil {
		return nil, nil, err
	}
	db, cleanup2, err := dao.NewDB()
	if err != nil {
		cleanup()
		return nil, nil, err
	}
	daoDao, cleanup3, err := dao.New(redis, db)
	if err != nil {
		cleanup2()
		cleanup()
		return nil, nil, err
	}
	serviceService, cleanup4, err := service.New(daoDao)
	if err != nil {
		cleanup3()
		cleanup2()
		cleanup()
		return nil, nil, err
	}
	engine, err := http.New(serviceService)
	if err != nil {
		cleanup4()
		cleanup3()
		cleanup2()
		cleanup()
		return nil, nil, err
	}
	server, err := grpc.New(serviceService)
	if err != nil {
		cleanup4()
		cleanup3()
		cleanup2()
		cleanup()
		return nil, nil, err
	}
	app, cleanup5, err := NewApp(serviceService, engine, server)
	if err != nil {
		cleanup4()
		cleanup3()
		cleanup2()
		cleanup()
		return nil, nil, err
	}
	return app, func() {
		cleanup5()
		cleanup4()
		cleanup3()
		cleanup2()
		cleanup()
	}, nil
}
로그인 후 복사
그렇다면 종속성 주입이란 정확히 무엇입니까?

그냥 캡슐화와 디커플링일 뿐입니다.

【관련 추천: Go 비디오 튜토리얼, 프로그래밍 교육

】🎜

위 내용은 Go 언어 의존성 주입이란 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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