Golang结构体构造的普遍性

huangapple go评论76阅读模式
英文:

Golang struct construction generality

问题

我有一个结构体,有两个其他对象实现它。在这种情况下,是typeA和typeB的repo。这里表示为省略号的是一些初始化代码。初始化代码在两个构造函数之间完全重复,并且只有两个dbRepo时并不是什么大问题,但是当我创建更多时,我会更担心这种不良实践。有没有办法用接口来泛化这个问题?

type dbRepo struct {
    foo string
    bar string
}

type typeARepo dbRepo
type typeBRepo dbRepo

func newTypeARepo(foo, bar string) {
    ...
}

func newTypeBRepo(foo, bar string) {
    ...
}
英文:

I have a struct that two other objects implement. In this case, typeA and B repo's. There's some initialization code, which are represented as ellipses here. The initialization code is completely duplicated between both constructors, and isn't a big deal while I only have two dbRepo's, but as I create more I will worry a bit more about the bad practice. Is there any way to generalize this with an interface?

type dbRepo struct {
    foo string
    bar string
}

type typeARepo dbRepo
type typeBRepo dbRepo

func newTypeARepo(foo, bar string) {
    ...
}

func newTypeBRepo(foo, bar string) {
    ...
}

答案1

得分: 5

我个人观察到的Go语言实践(也是《effective Go》或《getting started with Go》教程中推荐的做法)是只需定义一个NewdbRepo函数,并将其用于所有实例化。其实现可能如下所示:

func NewdbRepo(f, b string) *dbRepo {
    return &dbRepo{foo: f, bar: b}
}

实际上,你不能像在大多数类似C的语言中那样定义一个构造函数,所以你只需提供一个包范围的方法来进行构造。此外,如果你不使用复合字面量(我在NewdbRepo实现中使用的初始化样式),那么你可能会发现这样已经足够简洁满足你的需求了。

英文:

The practice I've personally observed in Go (and it's also what's recommended in the effective Go or getting started with Go tutorials) is just to define a NewdbRepo function and use it for all instantation. It's implementation would look something like;

func NewdbRepo(f, b string) *dbRepo {
    return &dbRepo{ foo:f, bar:b}
}

You can't actually define a constructor as you do in most C like languages so you just gotta provide a package scoped method to do construction for you. Also, if you're not using composite literals (the initilization style I use in my NewdbRepo implementation) then you may find that alone concise enough for your needs.

答案2

得分: 2

你可以使用你的初始化代码编写一个函数:

func newDbRepo(foo, bar string) dbRepo {
    // ...
}

然后你可以使用类型转换来使用它:

a := typeARepo(newDbRepo("foo", "bar"))
b := typeBRepo(newDbRepo("foo", "bar"))
英文:

You can write one function with your initializing code:

func newDbRepo(foo, bar string) dbRepo {
        // ...
}

Then you can use it with type conversion:

a := typeARepo(newDbRepo("foo", "bar"))
b := typeBRepo(newDbRepo("foo", "bar"))

答案3

得分: 2

在类型上定义一个未导出的函数来进行初始化,然后可以创建几个构造函数来调用它,例如:

func (db *dbRepo) init(){
    if len(db.foo) > 0 {
        // 进行 foo 的初始化
    }
    if len(db.bar) > 0 {
        // 进行 bar 的初始化
    }
    // 进行通用的初始化
}

func NewRepo(foo, bar string) *dbRepo {
    repo := &dbRepo{foo: foo, bar: bar}
    repo.init()
    return repo
}

func NewFooRepo(foo string) *dbRepo {
    repo := &dbRepo{foo: foo}
    repo.init()
    return repo
}

这段代码定义了一个名为 dbRepo 的类型,并在其上定义了一个未导出的 init 函数来进行初始化操作。然后,通过 NewRepoNewFooRepo 函数来创建 dbRepo 类型的实例,并在创建实例后调用 init 函数进行初始化。其中,NewRepo 函数接受 foobar 两个参数,而 NewFooRepo 函数只接受 foo 参数。

英文:

Define an unexported func on the type that does the initialization then you can create few constructors that call it, for example:

func (db *dbRepo) init(){
	if len(db.foo) > 0 {
		//do foo init
	}
	if len(db.bar) > 0 {
		// do bar init
	}
	// do generic init
}

func NewRepo(foo, bar string) *dbRepo {
	repo := &dbRepo{foo: foo, bar: bar}
	repo.init()
	return repo
}

func NewFooRepo(foo string) *dbRepo {
	repo := &dbRepo{foo: foo}
	repo.init()
	return repo
}

huangapple
  • 本文由 发表于 2015年4月17日 04:54:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/29685755.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定