Go依赖注入组件wire最佳实践(一)

Go依赖注入组件wire最佳实践(一)

什么是依赖注入?

贴一段维基百科中关于依赖注入的解释:

在软件工程中,依赖注入(dependency injection,缩写为 DI)是一种软件设计模式,也是实现控制反转的其中一种技术。这种模式能让一个对象接收它所依赖的其他对象。“依赖”是指接收方所需的对象。“注入”是指将“依赖”传递给接收方的过程。在“注入”之后,接收方才会调用该“依赖”[1]。此模式确保了任何想要使用给定服务的对象不需要知道如何建立这些服务。取而代之的是,连接收方对象(像是 client)也不知道它存在的外部代码(注入器)提供接收方所需的服务。

一个依赖注入的最简单示例

package tutorial

import "fmt"

type Message string

func NewMessage() Message {
	return Message("Hello Message")
}

type Greeter struct {
	message Message
}

func NewGreeter(msg Message) Greeter {
	return Greeter{message: msg}
}

func (g Greeter) Greet() Message {
	return g.message
}

type Event struct {
	greeter Greeter
}

func NewEvent(greeter Greeter) Event {
	return Event{greeter: greeter}
}

func (e Event) Start() {
	msg := e.greeter.Greet()
	fmt.Println(msg)
}

定义了几个类型和函数来模拟一个简单的问候事件。接下来看下如何使用Event来创建一个事件

package tutorial

import "testing"

func TestEvent_Start(t *testing.T) {
	msg := NewMessage()
	greeter := NewGreeter(msg)
	event := NewEvent(greeter)
	event.Start()
}

从上面的代码看出如果要New一个Event对象出来,我们先New一个Greeter,在NewGreeter的时候它依赖了Message对象,New一个Message。

我们正在使用依赖注入的设计原则。在实践中,这意味着我们传递每个组件所需的内容。这种设计风格适合编写易于测试的代码,并且很容易用另一个依赖项替换。

使用wire来生成代码

依赖注入的一个缺点是需要很多初始化步骤。让我们看看如何使用Wire来使我们组件的初始化过程更加顺畅。

安装wire
go install github.com/google/wire/cmd/wire@latest
编写wire注入函数
// wire.go
//go:build wireinject
// +build wireinject

package tutorial

import "github.com/google/wire"

func InitializeEvent() Event {
	wire.Build(NewEvent, NewGreeter, NewMessage)
	return Event{}
}

相对于逐个初始化每个组件并将其传递到下一个组件中,我们可以通过单个调用wire.Build来传入我们想要使用的初始化器。
在Wire中,初始化器被称为“提供者”,即提供特定类型的函数。我们添加了一个Event的零值作为返回值,以满足编译器。
请注意,即使我们向Event添加值,Wire也会忽略它们。实际上,注入器的目的是提供有关使用哪些提供者来构建事件的信息,因此我们将在文件顶部使用构建约束将其从最终二进制文件中排除。

//+build wireinject
生成wire_gen.go代码

在wire.go所在的目录,执行命令:

wire .
# 控制台会告诉你生成结果以及目录,类似下面的输出:
# wire: github.com/NanmiCoder/PracticeGoprojects/wirecase/tutorial: wrote /Users/nanmi/workspace/myself_code/PracticeGoprojects/wirecase/tutorial/wire_gen.go

查看生成的wire_gen.go代码,是不是放下跟上面我们自己构造的一样呢?

// wire_gen.go
// Code generated by Wire. DO NOT EDIT.

//go:generate go run github.com/google/wire/cmd/wire
//go:build !wireinject
// +build !wireinject

package tutorial

// Injectors from wire.go:

func InitializeEvent() Event {
	message := NewMessage()
	greeter := NewGreeter(message)
	event := NewEvent(greeter)
	return event
}

现在这是一个简单的例子,只有三个组件,所以手动编写初始化器并不太痛苦。想象一下在一些大型的项目中,组件会很多很多,使用wire组件用处就提现出来了 。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员阿江Relakkes

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值