Golang 依赖注入库Wire应用案例

文章目录

  • 简介
  • Github
  • 指南
  • 安装
  • 案例
    • wire.NewSet
    • wire.Build
    • wire.Bind
    • wire.Struct
    • wire.Value
    • wire.InterfaceValue

简介

Go语言的依赖注入库Wire是由Google提供的一个代码生成工具,用于简化和自动化依赖注入过程。Wire主要通过生成代码来处理依赖关系,而不是在运行时动态地解决依赖,这使得它更高效且易于调试。

  • wire.NewSet: NewSet 函数用于创建一个新的依赖集合。你可以将需要被注入的类型和提供这些类型依赖的函数放入到这个集合中。

  • wire.Build: Build 函数用于生成依赖注入代码。你可以将之前创建的依赖集合传递给 Build 函数,然后它将生成相应的代码用于构建依赖。

  • wire.Bind: Bind 函数用于将一个接口类型与其实现类型进行绑定。这样在依赖注入时,当需要注入某个接口类型时,Wire会知道该使用哪个具体的实现类型。

  • wire.Struct: Struct 函数用于将结构体类型与其字段进行绑定。这样在依赖注入时,可以将结构体的字段通过依赖注入的方式进行初始化。

  • wire.Value: Value 函数用于声明一个特定的值作为依赖。在依赖注入时,这个值会被直接使用,而不需要再进行额外的初始化。

  • wire.InterfaceValue: InterfaceValue 函数用于声明一个接口类型的值作为依赖。在依赖注入时,这个值会被用作接口类型的实现。

  • Wire的应用场景:

    • 构建复杂依赖图:Wire特别适用于处理具有复杂依赖关系的应用程序,尤其是当依赖项数量庞大且层次深厚时。

    • 简化初始化逻辑:通过自动生成依赖注入代码,Wire简化了对象的初始化逻辑,使代码更加简洁和易于维护。

    • 提高代码可测试性:通过接口绑定和依赖注入,Wire可以帮助实现松耦合结构,从而提高代码的可测试性。

    • 提升性能:Wire在编译时解析和生成依赖注入代码,因此在运行时不需要额外的依赖解析步骤,这使得它比一些运行时依赖注入框架更高效。

Github

  • https://github.com/google/wire

指南

  • https://github.com/google/wire/blob/main/docs/guide.md

安装

go get github.com/google/wire/cmd/wire
# 安装
go install github.com/google/wire/cmd/wire@latest

案例

wire.NewSet

wire.NewSet 是 Wire 库中用于创建依赖集合的函数。在依赖注入的场景中,你可以使用 wire.NewSet 将多个提供者函数(即构造函数)或现有值组合到一起,形成一个提供依赖项的集合。这对于组织和管理依赖项非常有帮助。

  • 应用场景
    • 分组管理依赖项:你可以将相关的依赖项分组到一个集合中,方便在不同的构建上下文中复用这些依赖项。
    • 模块化设计:通过创建不同的依赖集合,可以更清晰地表达模块之间的依赖关系。
    • 测试:可以创建不同的依赖集合用于测试,以便轻松替换实际依赖项。

wire.Build

wire.Build 是 Wire 库中的核心函数,用于生成依赖注入代码。它通过构建依赖图,根据提供的依赖集合自动生成所需的初始化代码。

  • 应用场景
    • 复杂依赖关系管理:在大型应用程序中,管理复杂的依赖关系是很困难的,使用 wire.Build 可以自动处理这些依赖。
    • 模块化开发:在模块化开发中,每个模块可能有自己的依赖项,通过 wire.Build 可以轻松组合不同模块的依赖。
    • 测试和替换依赖:在测试中,使用 wire.Build 可以方便地替换实际依赖项以进行单元测试。

在这里插入图片描述

  1. 定义依赖项和构造函数:定义 Database, HTTPServer 和 App 结构体,以及它们的构造函数。
  2. 创建依赖集合:使用 wire.NewSet 将构造函数组合成集合 ProviderSet。
  3. 生成依赖注入代码:在 app/wire.go 中,使用 wire.Build 和 ProviderSet 生成依赖注入代码。
  4. 使用生成的代码:在 main.go 中,调用 app.InitApp 函数初始化应用程序。
cd demo
# 初始化
go mod init example.com/demo
# 下载依赖库
go mod tidy
  • app/app.go
package app

import (
	"github.com/google/wire"
	"example.com/demo/db"
	"example.com/demo/server"
)

// App 是我们的应用程序,依赖于 HTTPServer
type App struct {
	Server *server.HTTPServer
}

// NewApp 是 App 的构造函数
func NewApp(server *server.HTTPServer) *App {
	return &App{
		Server: server,
	}
}

// ProviderSet 是应用程序模块的依赖集合
var ProviderSet = wire.NewSet(NewApp, db.ProviderSet, server.ProviderSet)
  • app/wire.go
// +build wireinject

package app

import (
	"github.com/google/wire"
)

// InitApp 使用 Wire 生成依赖注入代码
func InitApp() *App {
	wire.Build(ProviderSet)
	return &App{}
}
  • app/wire_gen.go(生成的代码)
// Code generated by Wire. DO NOT EDIT.

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

package app

import (
	"example.com/demo/db"
	"example.com/demo/server"
)

// Injectors from wire.go:

// InitApp 使用 Wire 生成依赖注入代码
func InitApp() *App {
	database := db.NewDatabase()
	httpServer := server.NewHTTPServer(database)
	app := NewApp(httpServer)
	return app
}
  • db/db.go
package db

import "github.com/google/wire"

// Database 是一个简单的数据库连接模拟
type Database struct {
	DSN string
}

// NewDatabase 是 Database 的构造函数
func NewDatabase() *Database {
	return &Database{
		DSN: "user:password@/dbname",
	}
}

// ProviderSet 是数据库模块的依赖集合
var ProviderSet = wire.NewSet(NewDatabase)
  • server/server.go
package server

import (
	"example.com/demo/db"
	"github.com/google/wire"
)

// HTTPServer 是一个简单的 HTTP 服务器
type HTTPServer struct {
	DB *db.Database
}

// NewHTTPServer 是 HTTPServer 的构造函数
func NewHTTPServer(db *db.Database) *HTTPServer {
	return &HTTPServer{
		DB: db,
	}
}

// ProviderSet 是服务器模块的依赖集合
var ProviderSet = wire.NewSet(NewHTTPServer)
  • main.go
package main

import (
	"fmt"
	"example.com/demo/app"
)

func main() {
	// 调用 app 包中的 InitApp 函数初始化应用
	myApp := app.InitApp()
	fmt.Printf("App initialized with server: %+v\n", myApp.Server)
}
  • 生成wire_gen.go
cd demo && wire
# 或
cd demo/app && wire
cd demo
go run .

wire.Bind

wire.Bind 是 Wire 提供的一个功能,用于将接口类型与具体实现类型绑定。这在依赖注入的场景中特别有用,因为它允许你将接口注入到依赖树中,而不是具体实现,从而实现更灵活和可测试的代码结构。

  • 应用场景
    • 接口与实现的解耦:当你的代码依赖于接口而不是具体实现时,可以更容易地更换实现或者进行单元测试。
    • 依赖注入中的多态性:在构建依赖图时,可以选择不同的具体实现绑定到相同的接口上,以实现多态行为。

在这里插入图片描述

  1. 定义接口和实现:在 service 包中定义 Service 接口和 RealService 实现。
  2. 构造函数和 ProviderSet:定义 NewRealService 构造函数和 ProviderSet,并使用 wire.Bind 将 Service 接口绑定到 RealService 实现。
  3. 使用依赖注入:在 app 包中定义 App 结构体及其构造函数 NewApp,并在 ProviderSet 中包含 service.ProviderSet。
  4. 生成 Wire 代码:在 app/wire.go 中使用 wire.Build 和 ProviderSet 生成依赖注入代码。
  5. 初始化应用:在 main.go 中调用 app.InitApp 初始化应用,并调用服务的方法。
  • app/app.go
package app

import (
	"github.com/google/wire"
	"example.com/demo/service"
)

// App 是我们的应用程序,依赖于 Service
type App struct {
	Service service.Service
}

// NewApp 是 App 的构造函数
func NewApp(service service.Service) *App {
	return &App{
		Service: service,
	}
}

// ProviderSet 是应用程序模块的依赖集合
var ProviderSet = wire.NewSet(NewApp, service.ProviderSet)
  • app/wire.go
// +build wireinject

package app

import (
	"github.com/google/wire"
)

// InitApp 使用 Wire 生成依赖注入代码
func InitApp() *App {
	wire.Build(ProviderSet)
	return &App{}
}
  • app/wire_gen.go(生成的代码)
// Code generated by Wire. DO NOT EDIT.

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

package app

import (
	"example.com/demo/service"
)

// Injectors from wire.go:

// InitApp 使用 Wire 生成依赖注入代码
func InitApp() *App {
	realService := service.NewRealService()
	app := NewApp(realService)
	return app
}
  • service/service.go
package service

import (
	"github.com/google/wire"
)

// Service 是一个接口,定义了服务的行为
type Service interface {
	Serve() string
}

// RealService 是 Service 接口的具体实现
type RealService struct{}

// Serve 是 RealService 的 Serve 方法实现
func (s *RealService) Serve() string {
	return "Real service serving"
}

// NewRealService 是 RealService 的构造函数
func NewRealService() *RealService {
	return &RealService{}
}

// ProviderSet 是服务模块的依赖集合
var ProviderSet = wire.NewSet(
	NewRealService,
	wire.Bind(new(Service), new(*RealService)),
)
  • main.go
package main

import (
	"fmt"
	"example.com/demo/app"
)

func main() {
	// 调用 app 包中的 InitApp 函数初始化应用
	myApp := app.InitApp()
	fmt.Println(myApp.Service.Serve())
}

wire.Struct

wire.Struct 是 Wire 提供的一个功能,用于简化结构体的构造。当一个结构体有多个字段需要注入时,wire.Struct 可以自动生成构造函数,注入所有字段。它特别适用于需要依赖注入的复杂结构体。

  • 应用场景
    • 简化构造函数:当一个结构体有很多字段时,手动编写构造函数可能会很繁琐,使用 wire.Struct 可以自动生成构造函数。
    • 减少样板代码:在大型项目中,减少手动编写的构造函数代码,提高开发效率。
    • 保证依赖注入的正确性:通过自动生成构造函数,减少人为错误。

在这里插入图片描述

  1. 定义结构体:在 app 包中定义 App 结构体,它依赖于 HTTPServer 和 Database。
  2. 使用 wire.Struct:在 ProviderSet 中使用 wire.Struct(new(App), “*”),表示将自动生成 App 的构造函数并注入所有字段。
  3. 生成依赖注入代码:在 app/wire.go 中使用 wire.Build 和 ProviderSet 生成依赖注入代码。
  4. 初始化应用:在 main.go 中调用 app.InitApp 函数初始化应用。
  • app/app.go
package app

import (
	"github.com/google/wire"
	"example.com/demo/db"
	"example.com/demo/server"
)

// App 是我们的应用程序,依赖于 HTTPServer 和 Database
type App struct {
	Server *server.HTTPServer
	Db     *db.Database
}

// ProviderSet 是应用程序模块的依赖集合
var ProviderSet = wire.NewSet(wire.Struct(new(App), "*"), db.ProviderSet, server.ProviderSet)
  • app/wire.go
// +build wireinject

package app

import (
	"github.com/google/wire"
)

// InitApp 使用 Wire 生成依赖注入代码
func InitApp() *App {
	wire.Build(ProviderSet)
	return &App{}
}
  • app/wire_gen.go(生成的代码)
// Code generated by Wire. DO NOT EDIT.

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

package app

import (
	"example.com/demo/db"
	"example.com/demo/server"
)

// Injectors from wire.go:

// InitApp 使用 Wire 生成依赖注入代码
func InitApp() *App {
	database := db.NewDatabase()
	httpServer := server.NewHTTPServer(database)
	app := &App{
		Server: httpServer,
		Db:     database,
	}
	return app
}
  • db/db.go
package db

import "github.com/google/wire"

// Database 是一个简单的数据库连接模拟
type Database struct {
	DSN string
}

// NewDatabase 是 Database 的构造函数
func NewDatabase() *Database {
	return &Database{
		DSN: "user:password@/dbname",
	}
}

// ProviderSet 是数据库模块的依赖集合
var ProviderSet = wire.NewSet(NewDatabase)
  • server/server.go
package server

import (
	"example.com/demo/db"
	"github.com/google/wire"
)

// HTTPServer 是一个简单的 HTTP 服务器
type HTTPServer struct {
	DB *db.Database
}

// NewHTTPServer 是 HTTPServer 的构造函数
func NewHTTPServer(db *db.Database) *HTTPServer {
	return &HTTPServer{
		DB: db,
	}
}

// ProviderSet 是服务器模块的依赖集合
var ProviderSet = wire.NewSet(NewHTTPServer)
  • main.go
package main

import (
	"fmt"
	"example.com/demo/app"
)

func main() {
	// 调用 app 包中的 InitApp 函数初始化应用
	myApp := app.InitApp()
	fmt.Printf("App initialized with server: %+v\n", myApp.Server)
}

wire.Value

wire.Value 是 Wire 提供的一个功能,用于注入一个特定的值。这在配置项或常量注入等场景中特别有用,能够为依赖注入过程提供静态的值。

  • 应用场景
    • 配置注入:将配置项(如数据库连接字符串、API 密钥等)注入到依赖树中。
    • 静态值注入:对于某些不会改变的常量值,使用 wire.Value 注入这些值。
    • 默认值注入:为某些依赖项提供默认值。

在这里插入图片描述

  1. 定义配置结构体:在 config 包中定义 Config 结构体和 NewConfig 构造函数。
  2. 使用 wire.Value:在 config.ProviderSet 中使用 wire.Value(Config{DSN: “user:password@/dbname”}) 注入静态配置值。
  3. 定义数据库结构体:在 db 包中定义 Database 结构体和 NewDatabase 构造函数。
  4. 构建依赖树:在 app 包中定义 App 结构体及其构造函数 NewApp,并在 ProviderSet 中包含 db.ProviderSet 和 config.ProviderSet。
  5. 生成依赖注入代码:在 app/wire.go 中使用 wire.Build 和 ProviderSet 生成依赖注入代码。
  6. 初始化应用:在 main.go 中调用 app.InitApp 函数初始化应用。
  • app/app.go
package app

import (
	"github.com/google/wire"
	"example.com/demo/db"
)

// App 是我们的应用程序,依赖于 Database
type App struct {
	Database *db.Database
}

// NewApp 是 App 的构造函数
func NewApp(database *db.Database) *App {
	return &App{
		Database: database,
	}
}

// ProviderSet 是应用程序模块的依赖集合
var ProviderSet = wire.NewSet(NewApp, db.ProviderSet)
  • app/wire.go
// +build wireinject

package app

import (
	"github.com/google/wire"
	"example.com/demo/config"
)

// InitApp 使用 Wire 生成依赖注入代码
func InitApp() *App {
	wire.Build(ProviderSet, config.ProviderSet)
	return &App{}
}
  • app/wire_gen.go(生成的代码)
// Code generated by Wire. DO NOT EDIT.

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

package app

import (
	"example.com/demo/config"
	"example.com/demo/db"
)

// Injectors from wire.go:

// InitApp 使用 Wire 生成依赖注入代码
func InitApp() *App {
	config := _wireConfigValue
	database := db.NewDatabase(config)
	app := NewApp(database)
	return app
}

var (
	_wireConfigValue = config.Config{DSN: "user:password@/dbname"}
)
  • config/config.go
package config

import "github.com/google/wire"

// Config 是一个简单的配置结构体
type Config struct {
	DSN string
}

// NewConfig 是 Config 的构造函数
func NewConfig(dsn string) *Config {
	return &Config{
		DSN: dsn,
	}
}

// ProviderSet 是配置模块的依赖集合
var ProviderSet = wire.NewSet(
	wire.Value(Config{DSN: "user:password@/dbname"}),
)
  • db/db.go
package db

import (
	"example.com/demo/config"
	"github.com/google/wire"
)

// Database 是一个简单的数据库连接模拟
type Database struct {
	DSN string
}

// NewDatabase 是 Database 的构造函数
func NewDatabase(config config.Config) *Database {
	return &Database{
		DSN: config.DSN,
	}
}

// ProviderSet 是数据库模块的依赖集合
var ProviderSet = wire.NewSet(NewDatabase)
  • main.go
package main

import (
	"fmt"
	"example.com/demo/app"
)

func main() {
	// 调用 app 包中的 InitApp 函数初始化应用
	myApp := app.InitApp()
	fmt.Printf("App initialized with database DSN: %+v\n", myApp.Database.DSN)
}

wire.InterfaceValue

wire.InterfaceValue 是 Wire 提供的一个功能,用于将一个特定的实现绑定到一个接口。这在依赖注入中非常有用,特别是在你有多个实现并且希望在运行时或编译时决定使用哪个实现的情况下。

  • 应用场景
    • 接口实现的动态选择:当你的代码依赖于接口而不是具体实现时,可以使用 wire.InterfaceValue 动态选择不同的实现。
    • 配置驱动的实现选择:根据配置或环境变量选择不同的实现。
    • 测试替身的注入:在测试中,可以用 wire.InterfaceValue 注入模拟或替身实现。

在这里插入图片描述

  1. 定义接口和实现:在 service 包中定义 Service 接口和 RealService, MockService 实现。
  2. 配置选择实现:在 config 包中定义 SelectedService 函数,用于选择具体的服务实现。
  3. 使用 wire.InterfaceValue:在 app/wire.go 中使用 wire.InterfaceValue 将 config.SelectedService() 的返回值绑定到 Service 接口。
  4. 构建依赖树:在 app 包中定义 App 结构体及其构造函数 NewApp,并在 ProviderSet 中包含 service.ProviderSet。
  5. 生成依赖注入代码:在 app/wire.go 中使用 wire.Build 和 ProviderSet 生成依赖注入代码。
  6. 初始化应用:在 main.go 中调用 app.InitApp 函数初始化应用,并调用服务的方法。
  • app/app.go
package app

import (
	"github.com/google/wire"
	"example.com/demo/service"
)

// App 是我们的应用程序,依赖于 Service
type App struct {
	Service service.Service
}

// NewApp 是 App 的构造函数
func NewApp(service service.Service) *App {
	return &App{
		Service: service,
	}
}

// ProviderSet 是应用程序模块的依赖集合
var ProviderSet = wire.NewSet(NewApp, service.ProviderSet)
  • app/wire.go
// +build wireinject

package app

import (
	"github.com/google/wire"
	"example.com/demo/config"
	"example.com/demo/service"
)

// InitApp 使用 Wire 生成依赖注入代码
func InitApp() *App {
	wire.Build(
		ProviderSet,
		wire.InterfaceValue(new(service.Service), config.SelectedService()),
	)
	return &App{}
}
  • app/wire_gen.go(生成的代码)
// Code generated by Wire. DO NOT EDIT.

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

package app

import (
	"example.com/demo/config"
)

// Injectors from wire.go:

// InitApp 使用 Wire 生成依赖注入代码
func InitApp() *App {
	service := _wireServiceValue
	app := NewApp(service)
	return app
}

var (
	_wireServiceValue = config.SelectedService()
)
  • config/config.go
package config

import "example.com/demo/service"

// SelectedService 返回要使用的服务实现
func SelectedService() service.Service {
	// 根据需要选择实际的服务实现,这里可以是基于配置或环境变量的逻辑
	return &service.RealService{}
}
  • db/db.go
package db

import (
	"example.com/demo/config"
	"github.com/google/wire"
)

// Database 是一个简单的数据库连接模拟
type Database struct {
	DSN string
}

// NewDatabase 是 Database 的构造函数
func NewDatabase(config config.Config) *Database {
	return &Database{
		DSN: config.DSN,
	}
}

// ProviderSet 是数据库模块的依赖集合
var ProviderSet = wire.NewSet(NewDatabase)
  • service/service.go
package service

import "github.com/google/wire"

// Service 是一个接口,定义了服务的行为
type Service interface {
	Serve() string
}

// RealService 是 Service 接口的一个具体实现
type RealService struct{}

func (s *RealService) Serve() string {
	return "Real service serving"
}

// MockService 是 Service 接口的另一个具体实现
type MockService struct{}

func (s *MockService) Serve() string {
	return "Mock service serving"
}

// ProviderSet 是服务模块的依赖集合
var ProviderSet = wire.NewSet()
  • main.go
package main

import (
	"fmt"
	"example.com/demo/app"
)

func main() {
	// 调用 app 包中的 InitApp 函数初始化应用
	myApp := app.InitApp()
	fmt.Println(myApp.Service.Serve())
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/722487.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

java-SpringBoot执行定时任务-任务调度-@EnableScheduling和@Scheduled

文章目录 java借助springBoot框架,执行定时任务0. 项目地址1. 需求分析2、新建springBoot项目3. 编写定时任务3.1 开启调度任务3.2 编写定时任务方法 java借助springBoot框架,执行定时任务 0. 项目地址 https://github.com/OrangeHza/JavaDemo 1. 需求…

揭示西周与汉唐时期的纺织工艺

在中国新疆这片充满神秘色彩的土地上,每一次的考古发掘都仿佛是对历史的一次深情回望,揭示出中华民族悠久而灿烂的文明史。其中,新疆出土的西周和汉唐时期的织物,更是以其精美绝伦的工艺和独特的审美风格,让我们对古代…

加速Python库安装:一键切换pip源,提升下载速度与成功率

pip换源 一、为什么要换源二、如何换源1. 临时换源2. 永久换源Windows系统Linux和macOS系统 3. 使用镜像站工具 三、常见的国内源四、注意事项五、总结 在Python开发中,我们经常需要使用pip来安装各种库。然而,由于网络环境的原因,直接使用pi…

《山西教育》教学版是什么级别的刊物?

《山西教育》教学版是什么级别的刊物? 《山西教育(教学版)》创刊于1956年,是由山西教育报刊社主办的教学刊物。山西省一级期刊,是“宣传教育政策,关注教育热点,传播先进经验,提供教改资讯”的权威性期刊&a…

C语言入门系列:判断和循环常踩的5个坑

文章目录 1. if代码块不带大括号问题描述示例与分析解决办法 2. if条件和大括号之间加了一个分号问题描述示例与分析解决办法 3. 使用号判断相等问题描述示例与分析解决办法 4. while循环的无限循环问题描述示例与分析解决办法 5. for循环中的off-by-one错误问题描述示例与分析…

Matlab只选取自己需要的数据画图

在Matlab作图的时候,经常会在同一个坐标系中作很多数据的图,如下图所示: 这就会导致不同数据所作的线会重叠在一起,不利于数据分析。如果只想对比几个数据的趋势,直接修改代码太过麻烦,可通过Matlab的绘图…

Python酷库之旅-比翼双飞情侣库(15)

目录 一、xlrd库的由来 二、xlrd库优缺点 1、优点 1-1、支持多种Excel文件格式 1-2、高效性 1-3、开源性 1-4、简单易用 1-5、良好的兼容性 2、缺点 2-1、对.xlsx格式支持有限 2-2、功能相对单一 2-3、更新和维护频率低 2-4、依赖外部资源 三、xlrd库的版本说明 …

开源新纪元:ChatTTS——引领对话式文本转语音的新潮流

✨作者主页: Mr.Zwq✔️个人简介:一个正在努力学技术的Python领域创作者,擅长爬虫,逆向,全栈方向,专注基础和实战分享,欢迎咨询! 您的点赞、关注、收藏、评论,是对我最大…

帕金森病患者应对腿部无力的方法

帕金森病是一种慢性神经系统退化性疾病,主要影响运动系统,导致运动功能障碍。患者常见的症状包括肌肉僵硬、运动迟缓、静止性震颤和姿势不稳。这些症状可能会导致患者在行走时感到腿软无力,尤其是在起步或转弯时更为明显。 帕金森病患者在日常…

Linux 图形化编程GTK3.0 快速入门之布局

GTK3.0 布局之水平布局 核心语法: 水平布局容器: 水平布局容器的创建: GtkWidget *gtk_hbox_new( gboolean homogeneous, gint spacing ); homogeneous:容器内控件是否大小一致( gboolean 取值为TRUE 或 FALSE ) spacing&#…

C++语法01 基本框架

目录 什么是 C ? 新建源程序 保存源程序 程序基本框架 #include using namespace std; int main() return 0; 编译 运行 什么是 C ? C语言,是基本的程序设计语言之一【程序设计语言,简单的来说就是编写代码来操控计…

【深度学习驱动流体力学】OpenFOAM框架剖析

目录 1. applications 目录solvers:存放各种求解器。mesh:网格生成相关工具。 2. src 目录3. tutorials 目录其他主要目录和文件参考 OpenFOAM 源码文件目录的框架如下,OpenFOAM 是一个开源的计算流体力学 (CFD) 软件包,其源码文件结构设计精…

Maven 插件列表详解

Maven 是一个强大的项目管理和构建工具,广泛应用于 Java 项目中。作为一款优秀的构建管理工具,Maven 不仅提供了标准化的项目结构和依赖管理,还通过其丰富的插件系统,极大地扩展了其功能和灵活性。无论是代码编译、测试、打包&…

小程序分页新写法

// pages/query/query.js import {request } from ../../utils/request; Page({/*** 页面的初始数据*/data: {tabClickIndex: ,page: 1,limit: 10,listData: []},/*** 生命周期函数--监听页面加载*/onLoad(options) {this.getList()},/*** 生命周期函数--监听页面初次渲染完成*…

uniapp运行到模拟器(联想模拟器)

记录一下uniapp项目运行到联想模拟器的流程 先配置一下模拟器端口 填写对应的adb路径,也就是模拟器安装路径下的adb.exe的路径 然后打开模拟器的设置,搜索版本找到版本号,多次点击打开开发者模式 进入开发者选项,打开USB调试 …

QT 中QcomboBox控件的详细用法

在Qt中,QComboBox 是一个用于选择下拉列表中的项目的控件。它继承自 QWidget 并提供了许多成员函数来操作和管理这个下拉列表。以下是一些常用的 QComboBox 成员函数及其基本用法: 构造函数 QComboBox(QWidget *parent nullptr): 创建一个新的 QCombo…

职业探索-性能测试01-性能工程师成长路径-性能测试的核心概念-性能测试的全周期概览

职业探索-性能测试01-性能工程师成长路径-性能测试的核心概念-性能测试的全周期概览 参考来源 极客时间专栏:高楼的性能测试实战30讲 课程链接:https://time.geekbang.org/column/intro/100042501 性能测试分析的能力阶梯视图 性能工程师 真正的性能…

FuTalk设计周刊-Vol.034

🔥AI漫谈 热点捕手 1、反转反转再反转!OpenAI“内斗”风波始末 故事还远远没有结束,一场“宫斗”解决不了商业世界影响下科技发展的路线之争,或许未来还将有很多“选择”将困扰这家年轻的企业,这是AI领域发展下必将经…

【论文阅读】-- 时间空间化:用于深度分类器训练的可扩展且可靠的时间旅行可视化

Temporality Spatialization: A Scalable and Faithful Time-Travelling Visualization for Deep Classifier Training 摘要1 引言2 动机3 问题定义4 方法论4.1 时空复合体4.2 复数约简 5 实验6 相关工作7 结论参考文献 摘要 时间旅行可视化回答了深度分类器的预测是如何在训练…

【单片机毕业设计选题24015】-基于物联网的家用智能充电桩计费系统设计

系统功能: 采用STM32最小系统板控制 1. 通过IM1281B电能计量模块读取系统电压电流功率电能等信息 2. 通过ESP8266WiFi模块连接阿里云 3. 使用RFID模块刷卡 4. 继电器模块控制充电 5. 12864OLED模块显示系统信息 6. 开启充电但检测不到系统电压时蜂鸣器模块报警。 主要功…