我正在使用Go编写一个简单的App Engine程序。我需要将一些数据写入Google DataStore。当我尝试将程序数据存入时,程序会一直挂起。这整整一周都困扰着我。
在某些时候,我设法将数据写入DataStore,只有在我发现如何在Cloud Console中查看上传的数据时才意识到这一点。从那以后我经常更改代码,现在我再也无法编写任何数据了。它每次都挂起。
日志显示没有任何帮助。只是注意到该过程已经超时。没有从程序写入的日志,仅来自系统。
由于超出了请求截止日期,流程终止。 (错误代码123)
我尝试使用this link更改import语句,但编译失败,所以我回到this link编译没有问题。
我认为我可能会以某种方式严重错误配置(可能是毁容?)我的开发环境,所以我去了一台干净的机器并仔细地进行了新的安装。它仍然挂起。
我的app.yaml文件:
runtime: go
api_version: go1
handlers:
- url: /.*
script: _go_app
我添加了一个index.yaml文件:
indexes:
- kind: Bacon
properties:
- name: YCode
direction: asc
- name: URL
- name: Owner
- name: Location
这是我的代码:
package main
import (
"fmt"
"log"
"net/http"
"google.golang.org/appengine/datastore"
"google.golang.org/appengine"
)
type Bacon struct {
YCode string
URL string
Owner string
Location string
}
func main() {
http.HandleFunc("/", indexHandler)
appengine.Main()
}
func indexHandler(w http.ResponseWriter, r *http.Request) {
ctx := appengine.NewContext(r)
projectID := "fake-for-discussion-thread-787987"
client, err := datastore.NewClient(ctx, projectID)
if err != nil {
log.Fatalf("Failed to create client: %v", err)
return
}
kind := "Bacon"
name := "3"
baconKey := datastore.NameKey(kind, name, nil)
//Make bacon
bacon := Bacon{
YCode: "1",
URL: "http://www.safeway.com",
Owner: "Bob",
Location: "Deli",
}
// I've confirmed that this is where it hangs every time.
// It doesn't even capture my silly fatal log entry.
// It just times out and finally sends a 500 Server Error.
if _, err := client.Put(ctx, baconKey, &bacon); err != nil {
log.Fatalf("Failed to save my Bacon: %v", err)
}
client.Close()
}
非常感谢您提供的任何帮助!
答案 0 :(得分:3)
好!所以这真的把我推到了墙上,但今天早上我设法破解了它。我在查找在线文档时遇到了很多困难,我想确保将其放入我的(现在正在工作的)代码中,以便其他人可以免除这些痛苦。
值得注意的是,如果您正在部署到App Engine,我已经开始怀疑Go文档/示例可能会让您走错路。 App Engine并不像某些核心Go库等。在部署到App Engine时,这可能会变得非常混乱。
另请注意,我从我最初的问题的评论中学到了很多我的经验教训。我正在制作此条目,以便我可以正确发布我的固定App Engine特定代码。
//Modified to work on App Engine. May not work right locally, etc.
package main
import (
"fmt"
"log"
"net/http"
"google.golang.org/appengine/datastore"
"google.golang.org/appengine"
)
type Bacon struct {
YCode string
URL string
Owner string
Location string
}
func main() {
http.HandleFunc("/", indexHandler)
appengine.Main()
}
func indexHandler(w http.ResponseWriter, r *http.Request) {
//This gives a context that makes App Engine happy
ctx := appengine.NewContext(r)
//NOT NEEDED (Apparently, App Engine knows who you are. Creepy.)
//projectID := "fake-for-discussion-thread-787987"
//NOT NEEDED (And may actually cause you great woe!)
//client, err := datastore.NewClient(ctx, projectID)
//if err != nil {
// log.Fatalf("Failed to create client: %v", err)
// return
//}
//Turns out that these aren't needed, either.
//kind := "Bacon"
//name := "3"
//Note the changes from my original code, including the
//change from NameKey to NewIncompleteKey and the
//hard-coding of Bacon in the arguments. Alternatively, you might
//use a variable, depending on your needs. I just need bacon.
//This causes the entity you create in Google DataStore
//to have a "Kind" of "Bacon"
baconKey := datastore.NewIncompleteKey(ctx, "Bacon", nil)
//Make bacon
bacon := Bacon{
YCode: "1",
URL: "http://www.safeway.com",
Owner: "Bob",
Location: "Deli",
}
// Note changes here. No more client, just a call to datastore.Put.
// Now it works! One caveat: I'm still trying to figure out why it writes
// my data twice. But, hey! At least it's writing!
if _, err := datastore.Put(ctx, baconKey, &bacon); err != nil {
log.Fatalf("Failed to save my Bacon: %v", err)
}
//No client, so no need to close.
//client.Close()
}
干杯!