Golang中结构体构造函数的使用与实践
Golang中结构体构造函数的使用与实践
我使用了以下方式为结构体实现构造函数 Make 模式:
package main
import (
"fmt"
)
type Etc struct {
Foo string
Bar int
}
func (Etc) Make(foo string, bar int) Etc {
return Etc{
Foo: foo,
Bar: bar,
}
}
func main() {
fmt.Printf("%#+v\n", Etc.Make(Etc{}, "foo_string", 0xbeef))
}
使用这种带有额外参数(据我理解是实际的"接收器")的构造函数是否正确?
更多关于Golang中结构体构造函数的使用与实践的实战教程也可以访问 https://www.itying.com/category-94-b0.html
6 回复
谢谢,
顺便问一下,根据我对 Golang 命名规则的理解,New 函数应该返回指针,而 Make 函数应该返回值。这样对吗?
我喜欢遵循社区的代码示例。
我从未见过那种代码。我通常看到的是:
func MakeEtc(foo string, bar int) Etc {
...
}
//或者类似这样的
func MakeEtc(foo string, bar int, etc *Etc) {
...
}
不,这是不正确的。你创建了一个结构体函数,然后通过结构体本身引用调用它,并向其传递一个Etc对象来满足接收器参数!!为什么要传递一个Etc对象来生成一个却不使用它呢? 正确的方式应该是:
package main
import (
"fmt"
)
type Etc struct {
Foo string
Bar int
}
func Make(foo string, bar int) Etc {
return Etc{
Foo: foo,
Bar: bar,
}
}
func main() {
fmt.Printf("%#+v\n", Make("foo_string", 0xbeef))
}
祝您有美好的一天。
以下是我编写构造函数的一个示例。这是一个微服务应用程序的示例。我在构造函数前加上"New"前缀。
//每个微服务应用程序中的聚合体都有
//自己的存储库。
package main
import "fmt"
type CustomerRepository interface {
Add()
}
type CustomersRepository struct {
DatabaseName string
CollectionName string
}
func main(){
n := NewCustomersRepository("testDB", "testCollection")
fmt.Printf("创建了新的 CustomersRepository 实例 %T\n %s %s \n", n,
n.DatabaseName, n.CollectionName)
}
func NewCustomersRepository(database string, collection string) *CustomersRepository {
return &CustomersRepository {
DatabaseName: database,
CollectionName: collection,
}
}
在Go语言中,你展示的构造函数用法并不符合惯用方式。Go中的构造函数通常定义为包级函数,而不是结构体方法。以下是正确的实现方式:
package main
import (
"fmt"
)
type Etc struct {
Foo string
Bar int
}
// 正确的构造函数实现
func NewEtc(foo string, bar int) Etc {
return Etc{
Foo: foo,
Bar: bar,
}
}
// 另一种常见的命名约定 - 使用Make前缀
func MakeEtc(foo string, bar int) Etc {
return Etc{
Foo: foo,
Bar: bar,
}
}
func main() {
// 正确的调用方式
etc1 := NewEtc("foo_string", 0xbeef)
fmt.Printf("%#+v\n", etc1)
etc2 := MakeEtc("bar_string", 0xdead)
fmt.Printf("%#+v\n", etc2)
}
你原来的方法存在几个问题:
- 方法接收器
Etc{}在构造函数中完全未被使用,这是冗余的 - 调用时需要传递不必要的接收器实例:
Etc.Make(Etc{}, "foo_string", 0xbeef) - 不符合Go语言的惯用约定
Go中构造函数的常见命名模式:
NewTypeName()- 最常用New()- 当包中只有一个主要类型时MakeTypeName()- 较少使用,但也可接受
对于需要错误处理的构造函数:
func NewEtcWithValidation(foo string, bar int) (Etc, error) {
if foo == "" {
return Etc{}, fmt.Errorf("foo cannot be empty")
}
return Etc{Foo: foo, Bar: bar}, nil
}
输出结果:
main.Etc{Foo:"foo_string", Bar:48879}
main.Etc{Foo:"bar_string", Bar:57005}

