Golang中依赖容器结构体应该按值传递还是引用传递

Golang中依赖容器结构体应该按值传递还是引用传递 你好,

我正想了解以下哪种做法是正确的。顺便提一下,接收函数不会修改容器。

谢谢

type Container struct {
	Version  string
	Shutdown time.Duration

	SomeStructA StructA
	SomeStructB *StructB

	DB     *sql.DB
	SRV    *http.Server
	AWSS3  *s3.S3
	AWSSES *session.Session
}

func main() {
	con := Container{ /* 假设所有字段都已在此处填充 */ }

	a(con) // 按值传递
	// 或者
	b(&con) // 按引用传递
}

func a(Container)  {}
func b(*Container) {}

更多关于Golang中依赖容器结构体应该按值传递还是引用传递的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

更多关于Golang中依赖容器结构体应该按值传递还是引用传递的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


以下链接可能会对你有所帮助

主题: 初学者问题:结构体、方法、指针

我正在学习一门Udemy课程,遇到了一个关于指针的问题,但老师没有讨论到。

我理解指针、内存地址及其内容。我知道,如果你想就地修改结构体(在这种情况下),而不是修改副本,可能会使用指针。

参考以下代码…

type person struct {
	first string
	last  string
}

func (p *person) changeMeMethod() {
	(*p).first = "Jo"
}

func changeMeFunc(p *person) {
	(*p).first = "Flem"
}

func main…

https://dave.cheney.net/2017/04/29/there-is-no-pass-by-reference-in-go

在Golang中,对于包含大量依赖项的结构体,通常建议使用指针传递(引用传递),即使接收函数不会修改容器。主要原因如下:

  1. 性能考虑:当结构体较大时,按值传递会导致完整的内存拷贝,增加CPU和内存开销
  2. 一致性:容器中已经包含了多个指针字段(如*sql.DB*http.Server),使用指针传递保持了一致性
  3. 惯用法:在Go社区中,包含依赖注入的结构体通常通过指针传递

示例代码:

type Container struct {
    Version  string
    Shutdown time.Duration
    
    SomeStructA StructA
    SomeStructB *StructB
    
    DB     *sql.DB
    SRV    *http.Server
    AWSS3  *s3.S3
    AWSSES *session.Session
}

func main() {
    con := &Container{
        Version:  "1.0",
        Shutdown: 30 * time.Second,
        DB:       initializeDB(),
        SRV:      initializeServer(),
        // 其他字段初始化
    }
    
    // 推荐使用指针传递
    processContainer(con)
}

// 即使不修改容器,也使用指针接收
func processContainer(c *Container) {
    fmt.Printf("处理容器版本: %s\n", c.Version)
    // 使用依赖项
    _ = c.DB.Ping()
}

// 如果需要确保不修改,可以添加文档说明
// processContainer 使用容器但不修改其内容

如果确实需要防止修改,可以使用接口约束或复制必要字段:

// 定义只读接口
type ContainerReader interface {
    GetVersion() string
    GetDB() *sql.DB
    // 其他只读方法
}

// 或者传递所需的最小数据
func processNeededData(version string, db *sql.DB) {
    // 只传递实际需要的字段
}

在实际项目中,依赖容器通常作为指针传递,这是Go中的常见模式。

回到顶部