user2402831
user2402831

Reputation: 673

Golang struct construction generality

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) {
    ...
}

Upvotes: 3

Views: 6221

Answers (3)

OneOfOne
OneOfOne

Reputation: 99195

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
}

Upvotes: 2

evanmcdonnal
evanmcdonnal

Reputation: 48076

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.

Upvotes: 5

Michael Laszlo
Michael Laszlo

Reputation: 12239

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"))

Upvotes: 2

Related Questions