英文:
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
函数来进行初始化操作。然后,通过 NewRepo
和 NewFooRepo
函数来创建 dbRepo
类型的实例,并在创建实例后调用 init
函数进行初始化。其中,NewRepo
函数接受 foo
和 bar
两个参数,而 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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论