英文:
Go has-many relationship in Google App Engine Datastore
问题
我对Go语言非常陌生,但我会尽力帮你翻译。以下是你要翻译的内容:
我对Go语言非常陌生,到目前为止我非常喜欢它。然而,我无论如何都无法弄清楚这个问题。
我有一个简单的包,名为invoice。
type Invoice struct {
key datastore.Key
Name string
Created time.Time
Updated time.Time
lineItems []LineItem
}
一个Invoice有几个LineItem。
type LineItem struct {
key datastore.Key
InvoiceKey *datastore.Key
Name string
Description string
}
我的包中有几个函数。
func New(c appengine.Context) (i Invoice)
func (i *Invoice) Update()
func (i *Invoice) Save(c appengine.Context)
func (i *Invoice) AddLineItem(c appengine.Context, name string)
New()函数返回一个新的Invoice,并将由datastore.NewIncompleteKey()生成的键保存在Invoice中作为一个未导出的变量,以便稍后保存它。
所有这些都运行得很好,是否是正确的方法是另一个问题。我也愿意听取对此的评论。我似乎无法弄清楚的是最后一个函数。
func (i *Invoice) AddLineItem(c appengine.Context, name string) {
key := datastore.NewIncompleteKey(c, "LineItem", &i.key)
lineItem := LineItem{key: *key, InvoiceKey: &i.key, Name: name}
i.lineItems = append(i.lineItems, lineItem)
}
在Save()函数中:
for _, lineItem := range i.lineItems {
_, err := datastore.Put(c, &lineItem.key, &lineItem)
if err != nil {
panic(err)
}
}
我一直在这里遇到一个无效的键错误。我基本上只是想让一个Invoice能够拥有多个LineItem。能够将它们全部保存到数据存储中,然后在需要时提取出整个Invoice和所有的LineItem。
我走在正确的轨道上吗?有更好的方法吗?
英文:
I am very new to Go and so far I am loving it. However, I can't figure this out for the life of me.
I have a simple package, invoice.
type Invoice struct {
key datastore.Key
Name string
Created time.Time
Updated time.Time
lineItems []LineItem
}
An Invoice has several LineItems.
type LineItem struct {
key datastore.Key
InvoiceKey *datastore.Key
Name string
Description string
}
My package has a couple functions.
func New(c appengine.Context) (i Invoice)
func (i *Invoice) Update()
func (i *Invoice) Save(c appengine.Context)
func (i *Invoice) AddLineItem(c appengine.Context, name string)
New() returns a new Invoice, and saves the key generated by datastore.NewIncompleteKey() inside the Invoice as an unexported variable so that I can save it later.
All of that runs fine, whether it is the proper way to do this or not is another question. I'm open to comments on that too. What I can't seem to figure out is that last function.
func (i *Invoice) AddLineItem(c appengine.Context, name string) {
key := datastore.NewIncompleteKey(c, "LineItem", &i.key)
lineItem := LineItem{key: *key, InvoiceKey: &i.key, Name: name}
i.lineItems = append(i.lineItems, lineItem)
}
And in Save()
for _, lineItem := range i.lineItems {
_, err := datastore.Put(c, &lineItem.key, &lineItem)
if err != nil {
panic(err)
}
}
I keep getting an invalid key error here. I'm basically just trying to make an Invoice have the ability to have many LineItems. Be able to save them all to the datastore, and then pull out the entire Invoice with all the LineItems as needed.
Am I on the right track? Is there a better way to do this?
答案1
得分: 0
你的 lineItems []LineItem
和 key datastore.Key
是未导出的,它们需要以大写字母开头,否则 GAE 将无法使用它们。
根据规范:
> 为了允许从另一个包中访问,标识符必须被导出。如果满足以下两个条件,则标识符被导出:
>
> 1. 标识符名称的第一个字符是一个 Unicode 大写字母(Unicode 类别 "Lu");
> 2. 标识符在包块中声明,或者它是字段名或方法名。
>
> 所有其他标识符都不会被导出。
英文:
Your lineItems []LineItem
and key datastore.Key
are unexported, they need to start with a capital letter otherwise the GAE won't be able to use it.
From the specs:
> An identifier may be exported to permit access to it from another package. An identifier is exported if both:
>
> 1. the first character of the identifier's name is a Unicode upper case letter (Unicode class "Lu"); and
> 2. the identifier is declared in the package block or it is a field name or method name.
>
> All other identifiers are not exported.
答案2
得分: 0
不要使用datastore.Key
,而是使用*datastore.Key
。任何时候你认为它可能没有设置都是一个错误的源头,可能会将你的无效键错误转换为恐慌。
你给LineItem
键设置了一个父键(即Invoice
),这是可以的,但是为什么还要存储Invoice
键和LineItem
键呢?你可以通过调用后者的Parent方法来获取前者。
英文:
Don't use datastore.Key
, use *datastore.Key
instead. Any time you think it might not be set is a source of a bug, and will probably turn your invalid key errors into panics.
You are giving LineItem
keys a parent (the Invoice
), which is fine, but why then do you store the Invoice
key in addition to the LineItem
key? You can get the former by calling the latter's Parent method.
答案3
得分: 0
我遇到的问题是尝试使用不完整的发票键生成不完整的LineItem键。
key, err := datastore.Put(c, &i.key, i)
请使用put返回的完整键。
for _, lineItem := range i.lineItems {
key := datastore.NewIncompleteKey(c, "LineItem", key)
lineItem.InvoiceKey = k
_, err := datastore.Put(c, key, &lineItem)
if err != nil {
panic(err)
}
}
这样存储它们。现在要解决的任务是如何从数据存储中读取它们!祝我好运。
英文:
The issue I was having was trying to use an incomplete invoice key to generate an incomplete LineItem key.
key, err := datastore.Put(c, &i.key, i)
Use the complete key returned from the put.
for _, lineItem := range i.lineItems {
key := datastore.NewIncompleteKey(c, "LineItem", key)
lineItem.InvoiceKey = k
_, err := datastore.Put(c, key, &lineItem)
if err != nil {
panic(err)
}
}
That stores them. Now to the task of figuring out how to read them all out of the datastore! Wish me luck.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论