Golang中你更倾向于使用哪种init函数?

Golang中你更倾向于使用哪种init函数? 1:此初始化函数要求传入一个结构体指针,并返回一个同类型的指针(类似于 append 函数)。

func initMyStruct_1(p *myStruct) *myStruct {
        if p == nil {
		p = &myStruct{}
	}
	if p.a == nil {
		p.a = make(map[string]string)
	}
	return p
}

func main() {
	var b *myStruct
	b = initMyStruct_1(b)
}

2:此初始化函数要求传入一个双重指针。

func initMyStruct_2(p **myStruct) {
	if p == nil {
		// 错误处理
	}
	if *p == nil {
		*p = &myStruct{}
	}
	if (*p).a == nil {
		(*p).a = make(map[string]string)
	}
}

func main() {
	var b *myStruct
	initMyStruct_2(&b)
}

为了构建这两个函数,我想处理输入指针为 nil 的情况。如果像下面这样只传递值,那么主函数中的指针 b 仍然是 nil。你有更好的方法来解决这个问题吗?谢谢!

func initMyStruct_3(p *myStruct) {
	if p == nil {
		p = &myStruct{}
	}
	if p.a == nil {
		p.a = make(map[string]string)
	}
	return p
}

func main() {
	var b *myStruct
	initMyStruct_3(b)
}

更多关于Golang中你更倾向于使用哪种init函数?的实战教程也可以访问 https://www.itying.com/category-94-b0.html

4 回复

为什么不直接

func newMyStruct() *myStruct {
    return &myStruct{
        a: make(map[string]string),
    }
}

更多关于Golang中你更倾向于使用哪种init函数?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


这是个好方法! 当我提出这个问题时,我只是想确保变量的初始化,这个输入是针对这种情况的:在执行这段代码之前,变量已经被初始化了。 然而,我发现通过重构我的代码可以避免这种情况……

你好, 如果我没有机会在同一个代码块中检查和初始化指针p,我想使用双指针,如下例所示:

package main

import "fmt"

type myStruct struct {
	a map[string]string
}

func main() {
	var p *myStruct
    
    // 检查并初始化 p
	if p == nil {
		p = &myStruct{
			a: map[string]string{},
		}
	}

	if p == nil {
		fmt.Println("p is not initialized")
		return
	}
	if p.a == nil {
		fmt.Println("p.a is not initialized")
	}
	fmt.Println("p is initialized")
}

在Golang中,我倾向于使用第一种方式(返回指针),因为它更符合Go语言的惯用法,代码更清晰且易于理解。

第一种方式的优势:

  1. 函数签名明确表达了输入和输出
  2. 调用方式直观,类似标准库中的append函数
  3. 避免了双重指针带来的理解复杂度

示例代码:

type myStruct struct {
    a map[string]string
    b int
}

// 方式1:返回指针(推荐)
func initMyStruct_1(p *myStruct) *myStruct {
    if p == nil {
        p = &myStruct{}
    }
    if p.a == nil {
        p.a = make(map[string]string)
    }
    return p
}

// 使用示例
func main() {
    // 情况1:nil指针初始化
    var b *myStruct
    b = initMyStruct_1(b)
    
    // 情况2:非nil指针初始化
    s := &myStruct{b: 10}
    s = initMyStruct_1(s)
    
    // 情况3:链式调用
    result := initMyStruct_1(nil).a["key"] = "value"
}

第二种方式(双重指针)虽然也能工作,但增加了代码的复杂性,需要处理指针的指针,这在Go中并不常见。第三种方式的问题在于Go是值传递,函数内修改指针的副本不会影响原始指针。

对于需要处理nil指针并初始化内部字段的场景,第一种方式是最佳选择。如果结构体有多个字段需要初始化,可以考虑以下扩展:

func initMyStructWithDefaults(p *myStruct, defaults map[string]string) *myStruct {
    if p == nil {
        p = &myStruct{}
    }
    if p.a == nil {
        p.a = make(map[string]string)
    }
    for k, v := range defaults {
        if _, exists := p.a[k]; !exists {
            p.a[k] = v
        }
    }
    return p
}

这种返回指针的方式在Go标准库和流行开源项目中广泛使用,保持了代码的简洁性和可读性。

回到顶部