Go依赖注入库Wire入门实战

651 阅读1分钟

概述

Java Spring最重要的特性之一就是强大的依赖注入能力。依赖注入,简单理解就是不写构造器或NewXXX,由框架负责创建出实例。Go崇尚简单清晰,官方并没有很好的依赖注入能力,Google开源的wire是为CDK(Cloud Development Kit)服务的,它基于代码生成而不是常见的运行时注入。

实战

一键安装

go get github.com/google/wire/cmd/wire

只要懂2个基础概念

Provider

“提供者”,顾名思义就是提供给依赖注入的“原料”,可以是NewXXX函数,也可以是wire提供的一些工具函数,例如wire.Bind, wire.Struct, wire.Value, wire.InterfaceValue。

Injector

“注入者”,是我们想要创建出实例的函数,在wire中就是我们指示wire,希望生成的构造函数。

案例代码

基于公开的资料,整理了wire的demo: github.com/luxiaofengl…

只需要在wire.go,所在的路径下运行 wire gen . 即可生成wire_gen.go

wire.go的编写如下:

//go:build wireinject

package demo

import (
	"github.com/google/wire"
	"gorm.io/gorm"
	"io"
	"os"
	"wire_demo/demo/common"
	"wire_demo/demo/dal"
	"wire_demo/demo/handler"
	"wire_demo/demo/service"
)

func InitializeBroadCast() BroadCast {
	wire.Build(NewBroadCast, NewChannel, NewMessage)
	return BroadCast{}
}

func BuildInjector() (*Injector, error) {
	wire.Build(
		NewInjector,
		handler.NewProjectHandler,
		service.NewProjectService,
		wire.Bind(new(dal.IProjectDal), new(*dal.ProjectDal)),
		dal.NewProjectDal,
		dal.NewQuestionDal,
		dal.NewQuestionModelDal,
		common.InitGormDB,
	)
	return new(Injector), nil
}

func BuildInjectorBySet() (*Injector, error) {
	wire.Build(
		NewInjector,
		ProjectSet,
		common.InitGormDB,
	)
	return new(Injector), nil
}

var ProjectSet = wire.NewSet(
	handler.NewProjectHandler,
	service.NewProjectService,
	wire.Bind(new(dal.IProjectDal), new(*dal.ProjectDal)),
	dal.NewProjectDal,
	dal.NewQuestionDal,
	dal.NewQuestionModelDal,
)

func BuildInjectorByStructProvider() (*Injector, error) {
	wire.Build(
		NewInjector,
		handler.NewProjectHandler,
		wire.Struct(new(service.ProjectService), "*"),
		// interface bind
		wire.Bind(new(dal.IProjectDal), new(*dal.ProjectDal)),
		dal.NewProjectDal,
		dal.NewQuestionDal,
		dal.NewQuestionModelDal,
		common.InitGormDB,
	)
	return new(Injector), nil
}

func BuildInjectorClean() (*Injector, func(), error) {
	wire.Build(
		NewInjector,
		handler.NewProjectHandler,
		service.NewProjectServiceClean,
		wire.Bind(new(dal.IProjectDal), new(*dal.ProjectDal)),
		dal.NewProjectDal,
		dal.NewQuestionDal,
		dal.NewQuestionModelDal,
		common.InitGormDB,
	)
	return new(Injector), nil, nil
}

var ISet = wire.NewSet(wire.InterfaceValue(new(io.Reader), os.Stdin))

func BuildByInterfaceValueProvider() *common.MyReader {
	wire.Build(common.NewMyReader, ISet)
	return new(common.MyReader)
}

func BuildByValueProvider() *dal.QuestionDal {
	wire.Build(
		dal.NewQuestionDal,
		wire.Value(&gorm.DB{}),
	)
	return new(dal.QuestionDal)
}

参考

mp.weixin.qq.com/s/yHB9BzEGI…

itnext.io/mastering-w…

github.com/luxiaofengl…