Facebookgo/injectを使用してGolangのDIを行う



  • サンプル項目の内容は「金英漢講師のSpring講義」で使用した例を参考にして作成したもので分かりやすい.
    会員情報を登録し、会員がVIPであることを確認し、割引金額を印刷します.

  • 依存注入についてSpringを用いた経験があり,比較理解を行った.
  • 実際のプロジェクトでは、構成部分とテストコードを別々に実装する必要がありますが、ここでは、注入と論理実行を1つのソースファイルに設定して説明します.
    各オブジェクトの「注入設定」セクション
    注ぎ込みを受けたいところに「inject:""」を貼る
    type MemberServiceImpl struct {
    	Repo Repository `inject:""` // 주입 받기 위해 `inject:""` 붙임
    }
    ストレージユーザのリポジトリ
    ストレージ・ユーザーのRepositoryインタフェースは次のとおりです.
    type Repository interface {
    	Save(member Member)`
    	FindById(id int) Member
    }
    各インプリメンテーションの依存部分
    管理メンバーのMemberServiceインターフェースおよびMemberServiceImplインプリメンテーション.
    プレイヤーを格納する知識ベースインタフェースの注入を受ける.
    type MemberService interface {
    	Join(member Member)
    	FindMember(id int) Member
    }
    
    type MemberServiceImpl struct {
    	Repo Repository `inject:""`
    }
    注文を処理するOrderServiceインターフェースおよびOrderServiceImplインプリメンテーション.
    プレイヤーの知識ベースと割引ポリシーを決定するDiscountPolicyインタフェースを注入する
    type OrderService interface {
    	CreateOrder(id int, itemName string, itemPrice int) *Order
    }
    
    type OrderServiceImpl struct {
    	Repository Repository `inject:""`
    	DisPolicy  DiscountPolicy `inject:""`
    }
    init.goのRun()部分
    func (mini MiniProject) Run() {
    	member := Member{1,"kj",true}
    
    	// 그래프 생성 (스프링의 스프링 컨테이너 역할 인 듯 하다.)
    	var graph inject.Graph
    
    	// 그래프에 오브젝트 제공
    	err := graph.Provide(
    		&inject.Object{Value: NewMemoryRepository()},
         		&inject.Object{Value: NewMemberServiceImplWithNoArgs(), Name: "memberServiceImpl"},
                	&inject.Object{Value: NewFixDiscountPolicy(1000)}),
    		&inject.Object{Value: NewOrderServiceImpl(), Name: "orderServiceImpl"}
    	if err != nil {
    		fmt.Println(err)
    		return
    	}
    
    	// 의존성을 주입 실행 부분
    	err = graph.Populate()
    	if err != nil {
    		fmt.Println(err)
    		return
    	}
        
        
        
        	// ------------ 테스트 코드 작성 ---------------
    
    	var memberService MemberService
    	var orderService OrderService
        
    	// 의존성 자동 주입이 완료된 구조체 인터페이스에 대입 name을 이용해서 graph에서 싱글턴 객체를 꺼내서 사용
    	for _, obj := range graph.Objects() {
    		if obj.Name == "memberServiceImpl" {
    			memberService = obj.Value.(*MemberServiceImpl)
    		} else if obj.Name == "orderServiceImpl" {
    			orderService = obj.Value.(*OrderServiceImpl)
    		}
    	}
    	memberService.Join(member)
    	fmt.Println("멤버 찾기 결과: ",memberService.FindMember(1))
    
    	fmt.Println("주문 생성 결과: " ,orderService.CreateOrder(1, "Mac", 100000))
    
    	fmt.Println("의존성 그래프 존재하는 모든 객체 출력")
    	for _, obj := range graph.Objects() {
    		log.Printf("object known: %v\n", obj)
    	}
    実行結果
    運転結果は以下の通りで、正常に注入されていることを確認できます.
    멤버 찾기 결과:  {1 kj true}
    주문 생성 결과:  &{1 Mac 100000 1000}
    의존성 그래프 존재하는 모든 객체 출력
    2021/08/03 16:07:15 object known: *modules.OrderServiceImpl named orderServiceImpl
    2021/08/03 16:07:15 object known: *modules.MemberServiceImpl named memberServiceImpl
    2021/08/03 16:07:15 object known: *modules.MemoryRepository
    2021/08/03 16:07:15 object known: *modules.FixDiscountPolicy
    
    注意:https://pkg.go.dev/github.com/facebookgo/inject#section-readme