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中结构体构造函数的使用与实践的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


谢谢,

顺便问一下,根据我对 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)
}

你原来的方法存在几个问题:

  1. 方法接收器 Etc{} 在构造函数中完全未被使用,这是冗余的
  2. 调用时需要传递不必要的接收器实例:Etc.Make(Etc{}, "foo_string", 0xbeef)
  3. 不符合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}
回到顶部