251 lines
6.4 KiB
Markdown
251 lines
6.4 KiB
Markdown
|
||
😯: go里的wire模块, 安装后, 可以使用wire命令, 来生成依赖注入的代码, 具体怎么使用,能否结合一个使用场景的例子,演示一下
|
||
|
||
😐: Go 里的 wire 模块是一个用于依赖注入(DI,Dependency Injection)的工具,可以帮助我们自动生成依赖注入的代码,从而减少手动编写的样板代码。使用 wire 可以提高代码的模块化,减少手动配置的错误。
|
||
|
||
|
||
|
||
**安装 wire**
|
||
|
||
|
||
|
||
首先,你需要安装 wire 工具:
|
||
|
||
```
|
||
go install github.com/google/wire/cmd/wire@latest
|
||
```
|
||
|
||
**使用 wire 的基本步骤**
|
||
|
||
1. **定义接口和实现**:在你的项目中定义需要依赖注入的接口和结构体。
|
||
|
||
2. **创建 Wire Provider Function**:提供函数用来创建对象。
|
||
|
||
3. **创建 Wire Injector Function**:使用 wire 提供的功能来自动生成依赖注入代码。
|
||
|
||
4. **运行 wire 命令**:生成依赖注入代码。
|
||
|
||
|
||
|
||
**示例场景**
|
||
|
||
|
||
|
||
假设你有一个 web 服务,需要使用一个 UserService,而 UserService 又依赖于一个 UserRepository,我们希望通过 wire 来自动管理这些依赖关系。
|
||
|
||
|
||
|
||
**步骤 1:定义接口和实现**
|
||
|
||
|
||
|
||
首先,定义 UserRepository 和 UserService。
|
||
|
||
|
||
|
||
**user_repository.go**
|
||
|
||
```go
|
||
package main
|
||
|
||
import "fmt"
|
||
|
||
// UserRepository 定义了数据访问接口
|
||
type UserRepository interface {
|
||
GetUser(id int) string
|
||
}
|
||
|
||
// InMemoryUserRepository 是 UserRepository 的实现
|
||
type InMemoryUserRepository struct{}
|
||
|
||
// GetUser 实现了 UserRepository 接口
|
||
func (r *InMemoryUserRepository) GetUser(id int) string {
|
||
return fmt.Sprintf("User-%d", id)
|
||
}
|
||
|
||
// 😯: UserRepository 作为一个接口, 下连具体的数据库实现, 上连UserService,
|
||
// 😯: 然后 InMemoryUserRepository 作为一个struct 实现了这个Repository接口,
|
||
```
|
||
|
||
**user_service.go**
|
||
|
||
```go
|
||
package main
|
||
|
||
import "fmt"
|
||
|
||
// UserService 依赖 UserRepository
|
||
type UserService struct {
|
||
repo UserRepository
|
||
}
|
||
|
||
// NewUserService 创建一个新的 UserService 实例
|
||
func NewUserService(repo UserRepository) *UserService {
|
||
return &UserService{repo: repo}
|
||
}
|
||
// 😯: UserService作为一个Service struct 本质上是一个UserRepository 的 Wraapper,
|
||
// 其实, 可以理解为, UserService struct 是这个UserRepository抽象接口的实体插座,
|
||
// 然后按照惯例, 给出了这个 struct 的初始化程序 NewUserService()
|
||
|
||
// GetUserInfo 获取用户信息
|
||
func (s *UserService) GetUserInfo(id int) string {
|
||
return fmt.Sprintf("User Info: %s", s.repo.GetUser(id))
|
||
}
|
||
```
|
||
|
||
**步骤 2:创建 Wire Provider Function**
|
||
|
||
|
||
|
||
接下来,我们创建 Wire Provider Function 来生成依赖关系。
|
||
|
||
|
||
|
||
**provider.go**
|
||
|
||
```go
|
||
// +build wireinject
|
||
|
||
package main
|
||
|
||
import "github.com/google/wire"
|
||
|
||
// InitializeUserService 使用 wire 来自动注入依赖
|
||
func InitializeUserService() *UserService {
|
||
wire.Build(NewUserService, &InMemoryUserRepository{})
|
||
return nil // wire 会自动生成代码
|
||
}
|
||
```
|
||
|
||
在上面的代码中,我们用 wire.Build 来指定如何构建 UserService,NewUserService 用于创建 UserService,而 &InMemoryUserRepository{} 是提供 UserRepository 接口的实现。
|
||
|
||
|
||
|
||
**步骤 3:创建 main 函数**
|
||
|
||
|
||
|
||
然后,我们在 main.go 中使用自动生成的代码来初始化服务。
|
||
|
||
|
||
|
||
**main.go**
|
||
|
||
```go
|
||
package main
|
||
|
||
import "fmt"
|
||
|
||
func main() {
|
||
userService := InitializeUserService()
|
||
fmt.Println(userService.GetUserInfo(1))
|
||
}
|
||
```
|
||
|
||
**步骤 4:生成依赖注入代码**
|
||
|
||
|
||
|
||
接下来,运行 wire 命令来自动生成依赖注入的代码。
|
||
|
||
```
|
||
wire
|
||
```
|
||
|
||
执行后,会在项目中生成一个名为 wire_gen.go 的文件,其中包含了 InitializeUserService 函数的实现,负责自动生成 UserService 和 UserRepository 的依赖注入代码。
|
||
|
||
|
||
|
||
**步骤 5:运行程序**
|
||
|
||
|
||
|
||
最后,运行 main.go:
|
||
|
||
```
|
||
go run main.go
|
||
```
|
||
|
||
你将会看到输出:
|
||
|
||
```
|
||
User Info: User-1
|
||
```
|
||
|
||
**总结**
|
||
|
||
• wire 帮助我们通过自动生成代码来管理依赖注入,简化了代码的模块化管理。
|
||
|
||
• 通过 wire.Build 可以定义如何构建依赖关系,wire 会根据这些定义生成必要的代码。
|
||
|
||
• 通过 InitializeUserService 函数,我们可以自动注入 UserRepository 和 UserService。
|
||
|
||
|
||
|
||
这个例子展示了如何在 Go 项目中使用 wire 来简化依赖注入的过程。希望这个示例对你有帮助!
|
||
|
||
执行完 wire 命令之后,wire 会自动生成一个新的 Go 文件,通常命名为 wire_gen.go,并将依赖注入的代码写入其中。这个文件是自动生成的,不需要手动修改。
|
||
|
||
---
|
||
|
||
😯: 执行完 wire之后预期的结果是什么
|
||
|
||
**预期的结果**
|
||
|
||
1. **生成 wire_gen.go 文件**:
|
||
|
||
该文件包含 wire 自动生成的代码,用于实现依赖注入。这个文件中会有一个 InitializeUserService 函数的实现,负责构建 UserService 和它的依赖(比如 UserRepository)。
|
||
|
||
1. **文件内容**:
|
||
|
||
wire_gen.go 文件会根据你提供的 wire.Build 指令生成构造依赖的代码。对于我们的示例来说,wire_gen.go 会看起来像这样:
|
||
|
||
```go
|
||
// Code generated by Wire. DO NOT EDIT.
|
||
// wire:build main.InitializeUserService
|
||
|
||
package main
|
||
|
||
import "github.com/google/wire"
|
||
|
||
// InitializeUserService 通过依赖注入创建 UserService 实例
|
||
func InitializeUserService() *UserService {
|
||
userRepository := &InMemoryUserRepository{}
|
||
userService := NewUserService(userRepository)
|
||
return userService
|
||
}
|
||
```
|
||
|
||
这段代码的意思是:
|
||
|
||
• wire 会自动创建一个 InMemoryUserRepository 的实例,并传递给 NewUserService 函数来创建 UserService 实例。
|
||
|
||
• InitializeUserService 函数返回的是 UserService 实例,这样你就可以直接在 main.go 中使用它。
|
||
|
||
|
||
|
||
1. **后续步骤**:
|
||
|
||
一旦生成了这个文件,你就可以在项目中使用 InitializeUserService 函数,它会自动创建并返回已注入依赖的 UserService 实例。
|
||
|
||
1. **编译和运行**:
|
||
|
||
• wire_gen.go 是自动生成的,因此你不需要手动编辑它。
|
||
|
||
• 你可以直接运行你的应用程序,Go 编译器会处理 wire_gen.go 中的代码,构建并启动你的应用。
|
||
|
||
|
||
|
||
**核心要点**
|
||
|
||
• wire 命令通过 wire.Build 定义的依赖关系自动生成代码。
|
||
|
||
• 生成的代码将自动实例化依赖并返回最终的对象,例如 UserService。
|
||
|
||
• 你只需运行生成的 main.go 或其他需要依赖注入的地方,所有的依赖注入将自动完成。
|
||
|
||
|
||
|
||
希望这个解释能帮你理解 wire 命令执行后的预期结果!
|
||
|