Override struct tags in go

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

Override struct tags in go

问题

我在项目中有一个实体,可以被公开和管理员查看。并非所有字段都应该对公众可见。

例如:

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 字段应该只对管理员可见。目前,当来自公众的请求到达时,我调用一个单独的方法,将每个需要的字段复制到新的结构体中:

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
}

但是,如果我需要在实体中添加新字段,我需要在三个地方添加它:在结构体本身中,FooPublic 中和 Public 方法中。这似乎违反了 DRY 原则。在这里,有什么正确的、惯用的解决方案吗?我可以定义 FooPublic 来覆盖所需字段的标签吗?或者可能有一种好的方法可以将一个结构体的相应字段复制到另一个结构体中,这样我就不需要在 Public 方法中手动执行此操作了吗?

英文:

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?

答案1

得分: 3

一般情况下,可以通过使用嵌入来避免这种重复。你的 Foo 类型应该嵌入 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
}

但是,如果有人能够调用 Foo.Public(),那么这个人已经拥有 Foo*Foo 值(因此可以访问导出的 AdminOnly 字段),那么这样做有什么意义呢?

一个更好的解决方案是使用接口,而不是暴露 Foo 结构体。

英文:

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.

huangapple
  • 本文由 发表于 2016年8月22日 18:21:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/39077015.html
匿名

发表评论

匿名网友

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

确定