myNotes/worksAndStudy/core/go_wire 循环依赖.md
zhangkun9038@dingtalk.com cceeb4d554 worksAndStudy
2025-03-21 23:52:19 +08:00

6.4 KiB
Raw Blame History

😯: go里的wire模块, 安装后, 可以使用wire命令, 来生成依赖注入的代码, 具体怎么使用,能否结合一个使用场景的例子,演示一下

😐: Go 里的 wire 模块是一个用于依赖注入DIDependency 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

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

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

// +build wireinject

package main

import "github.com/google/wire"

// InitializeUserService 使用 wire 来自动注入依赖
func InitializeUserService() *UserService {
    wire.Build(NewUserService, &InMemoryUserRepository{})
    return nil // wire 会自动生成代码
}

在上面的代码中,我们用 wire.Build 来指定如何构建 UserServiceNewUserService 用于创建 UserService而 &InMemoryUserRepository{} 是提供 UserRepository 接口的实现。

步骤 3创建 main 函数

然后,我们在 main.go 中使用自动生成的代码来初始化服务。

main.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 会看起来像这样:

// 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 命令执行后的预期结果!