Reputation: 169
I have an entity in my project that is viewable by public and by admin. Not all fields should be accessible by public.
For example
type Foo struct {
Id bson.ObjectId `json:"id" bson:"_id"`
DateAdded time.Time `json:"date_added" bson:"date_added"`
Bar string `json:"bar" bson:"bar"`
AdminOnly string `json:"admin_only" bson:"admin_only"`
}
AdminOnly field should be only visible to admins. For now, when requests comes from public, I call separate method that copies every needed field to new struct
type FooPublic struct {
Id bson.ObjectId `json:"id" bson:"_id"`
DateAdded time.Time `json:"date_added" bson:"date_added"`
Bar string `json:"bar" bson:"bar"`
}
func (f *Foo) Public() (res FooPublic) {
res = FooPublic{
Id: f.Id,
DateAdded: f.DateAdded,
Bar:f.Bar,
}
return
}
But if I need to add new field to my entity, I need to add it in 3 places. In struct itself, in PublicFoo
and in Public
method.
This seems to be agains DRY principle. What is correct, idiomatic solution here? Can I define FooPublic
so it overrides tags of needed fields? Or probably there is at least good way to copy corresponding fields from one struct to another, so I don't need to do this manually in Public
method?
Upvotes: 4
Views: 2132
Reputation: 417412
In general this repetition can be avoided by using embedding. Your Foo
type should embed FooPublic
:
type FooPublic struct {
Id bson.ObjectId `json:"id" bson:"_id"`
DateAdded time.Time `json:"date_added" bson:"date_added"`
Bar string `json:"bar" bson:"bar"`
}
type Foo struct {
FooPublic
AdminOnly string `json:"admin_only" bson:"admin_only"`
}
func (f *Foo) Public() FooPublic {
return f.FooPublic
}
But if someone is able to call the Foo.Public()
, that someone already has the Foo
or *Foo
value (and so can access the exported AdminOnly
field), so what's the point?
A better solution would be to use an interface, and not expose the Foo
struct.
Upvotes: 4