英文:
Anonymous structs return empty field value
问题
类型(
Id 结构体 {
// 我之前忘记在我的问题中添加 `ID` 字段,它在我的代码中存在,但在这个问题中没有,正如 @icza 指出的那样
ID bson.ObjectId `json:"id" bson:"_id"`
}
User 结构体 {
// 使用匿名结构体时,在返回集合时,每个文档的 `id` 字段都将是空字符串 `""`
Id
Email string `json:"email" bson:"email"`
...
}
// 这个是可以工作的
User2 结构体 {
ID bson.ObjectId `json:"id" bson:"_id"`
Email string `json:"email" bson:"email"`
}
)
我可能还没有完全理解匿名结构体的概念。在上面的示例中,当从集合中查询所有用户时,id
字段将是一个空字符串 ""
。然而,如果我直接在 User
结构体中定义 ID 字段,id
就会正常显示。这不是匿名结构体的用途吗?基本上是扩展结构体,这样你就不必一遍又一遍地输入它们了。
更多示例:
类型 SoftDelete 结构体 {
CreatedAt time.Time json:"created_at" bson:"created_at"
UpdatedAt time.Time json:"updated_at" bson:"updated_at"
DeletedAt time.Time json:"deleted_at" bson:"deleted_at"
}
类型 UserModel 结构体 {
SoftDelete
}
类型 BlogPost 结构体 {
SoftDelete
}
英文:
type (
Id struct {
// I previously forgot to add the `ID` field in my question, it is present in my code but not on this question as @icza pointed it out to me
ID bson.ObjectId `json:"id" bson:"_id"`
}
User struct {
// When using anonymous struct, upon returning the collection, each of the document will have an empty `id` field, `id: ""`
Id
Email string `json:"email" bson:"email"`
...
}
// This works
User2 struct {
ID bson.ObjectId `json:"id" bson:"_id"`
Email string `json:"email" bson:"email"`
}
)
I might not have fully understood the concept of anonymous structs yet. In the example above, when querying all users from a collection, the id
field is going to be an empty string ""
. However, if I directly define the ID field in the User
struct, the id
shows up fine. Is this not what anonymous structs are for? Basically extending struct so you won't have to type them again and again?
More example:
type SoftDelete struct {
CreatedAt time.Time `json:"created_at" bson:"created_at"`
UpdatedAt time.Time `json:"updated_at" bson:"updated_at"`
DeletedAt time.Time `json:"deleted_at" bson:"deleted_at"`
}
type UserModel struct {
SoftDelete
}
type BlogPost struct {
SoftDelete
}
答案1
得分: 5
这里的问题是,具有struct
类型(包括嵌入的结构体)的字段在MongoDB中作为嵌入文档出现。如果你不想这样,你需要在嵌入结构体时指定"inline"
bson标志:
User struct {
Id `bson:",inline"`
Email string `json:"email" bson:"email"`
}
"inline"
标签的作用是在MongoDB中将嵌入结构体的字段“展开”,就好像它们是嵌入结构体的一部分一样。
类似地:
type UserModel struct {
SoftDelete `bson:",inline"`
}
type BlogPost struct {
SoftDelete `bson:",inline"`
}
编辑:下面的部分适用于原始的Id
类型,它嵌入了bson.ObjectId
。提问者后来澄清这只是一个拼写错误(并且编辑了问题),它是一个命名的非匿名字段。但我仍然认为下面的信息是有用的。
关于你的Id
类型,有一点需要注意:你的Id
类型也嵌入了bson.ObjectId
:
Id struct {
bson.ObjectId `json:"id" bson:"_id"`
}
Id
不仅有一个bson.ObjectId
类型的字段,而且它嵌入了它。这很重要,因为这样你的Id
类型将从bson.ObjectId
继承一个String()
方法,而User
也会继承这个方法,因为它嵌入了Id
。话虽如此,尝试打印或调试User
类型的值会很困难,因为你总是只会看到它作为一个单独的ObjectId
打印出来。
相反,你可以将它作为Id
的普通字段,嵌入User
仍然会按预期工作:
Id struct {
ID bson.ObjectId `json:"id" bson:"_id"`
}
参考相关问题+答案:https://stackoverflow.com/questions/41595577/enforce-a-type-mapping-with-mgo/41596169#41596169
英文:
The problem here is that fields having struct
types (including embedded structs) appear as embedded documents in MongoDB. If you don't want this, you have to specify the "inline"
bson flag when embedding a struct:
User struct {
Id `bson:",inline"`
Email string `json:"email" bson:"email"`
}
What the "inline"
tag does is in MongoDB it "flattens" the fields of the embedded struct as if they were part of the embedder struct.
Similarly:
type UserModel struct {
SoftDelete `bson:",inline"`
}
type BlogPost struct {
SoftDelete `bson:",inline"`
}
<sup>Edit: the following section applies to the original Id
type which embedded bson.ObjectId
. The asker later clarified that this was just a typo (and edited the question since), and it is a named, non-anonymous field. Still think the info below is useful.</sup>
One thing to note about your Id
type: Your Id
type also embeds bson.ObjectId
:
Id struct {
bson.ObjectId `json:"id" bson:"_id"`
}
Id
not just has a field of bson.ObjectId
, but it embeds it. This matters because this way you Id
type will have a String()
method promoted from bson.ObjectId
, and so will User
which embeds Id
. Having said that, it will be hard trying to print or debug values of type User
, because you will always see it printed just as a single ObjectId
.
Instead you can make it a regular field in Id
, embedding Id
in User
will still work as expected:
Id struct {
ID bson.ObjectId `json:"id" bson:"_id"`
}
See related question+asnwer: https://stackoverflow.com/questions/41595577/enforce-a-type-mapping-with-mgo/41596169#41596169
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论