1

I've been developing with Google App Engine Go for awhile, but I haven't touched it in a year. I tried updating my application from "go1" (1.9?) to "go111", and I'm currently getting some weird errors without any explanation as to what's going on.

The errors include:

  • The request failed because the instance could not start successfully
  • Container called exit(1).
  • 500 Internal server error
  • etc.

None of these point me to any specific line in my code where something would go wrong, nor explain anything more meaningful...

I'm guessing the error is stemming from me upgrading between the golang versions. I had to change the app package into main, add a main function to the application, update the appengine package to a newer version, update the gsuite app, add a cloud compilation widget thingy, change app.yaml script from go to auto, etc.

All in all, I'm lost. A Similar SE question yielded no good answers. Someone else suggested app.yaml might be at fault, so here is mine:

runtime:     go111

handlers:
- url: /static
  static_dir: static
- url: /res
  static_dir: res
- url: /update
  script: auto
  secure: always
  login: admin
- url: /.*
  script: auto
  secure: always
  login: optional

Debug console log is very unhelpful:

And the main file looks essentially like:

package main

import (
    "fmt"
    "google.golang.org/appengine"
    "html/template"
    "log"
    "net/http"
)

var MainTemplate *template.Template

func main() {
    http.HandleFunc("/", hello)

    var err error
    MainTemplate, err = template.ParseFiles("html/main.html")
    if err != nil {
        log.Printf("ERROR! %v\n", err.Error())
        panic(err)
    }
    log.Printf("Hello world!\n")
}


func hello(w http.ResponseWriter, r *http.Request) {
    c := appengine.NewContext(r)
    //................................//
    MainTemplate.Execute(w, nil)
}

Anything else it could be?

ThePiachu
  • 8,695
  • 17
  • 65
  • 94
  • 1
    Most likely your code crashed. Add the error messages from Stackdriver plus your code. – John Hanley Oct 20 '19 at 05:38
  • @JohnHanley Added the log, plus the basic code. Main function doesn't appear to crash, no errors pointing to anything going wrong... – ThePiachu Oct 20 '19 at 07:40
  • 1
    @ThePiachu you appear to be missing a call to http.ListenAndServe. Take a look at the helloworld.go example in the [go111 getting started page](https://cloud.google.com/appengine/docs/standard/go111/building-app/). Without that, your app is going to exit without ever listening for any requests (alternatively, it appears you can call appengine.Main per the [migration guide](https://cloud.google.com/appengine/docs/standard/go111/go-differences#package-main)). – robsiemb Oct 20 '19 at 14:26
  • The code that you posted could not have worked before in App Engine. Your code starts, processes templates, and exits. No web server process is started. – John Hanley Oct 20 '19 at 15:39
  • @JohnHanley yeah, that function used to be `init()`, but then appengine nagged me about not having a `main` package and a `main()` function, so I just switched init to main. I guess my mind glossed over the ListenAndServe from the example, since it was nested inside of a log... https://github.com/GoogleCloudPlatform/golang-samples/blob/master/appengine/go11x/helloworld/helloworld.go – ThePiachu Oct 20 '19 at 19:29

2 Answers2

2

Okay, after some help from a few comments, here are a few issues that I had to fix to get my code to work:

  1. I converted my init() function into main() without adding a way to listen to requests. The code just ran through the main() function and exited without an error, hence the problems with debugging.
  2. appengine.NewContext(r) is deprecated apparently, so I had to switch those statements to r.Context(). MEANWHILE, Appengine Datastore is still using golang.org/x/net/context and not just context, so if you want to use things like RunInTransaction(), DON'T update your imports, context casts into golang.org/x/net/context just fine
  3. If you follow the official examples provided by Google, you will most likely run into errors like textPayload: "2019/10/20 22:32:46 http: panic serving 127.0.0.1:16051: not an App Engine context. Instead, your code needs to look like the below example.
  4. Since the former app package is now the main package, make sure that any files that are referenced in app.yaml (favicon.ico for example) are in a proper position in relation to the main package (I had to move mine to a different folder to avoid errors popping up every request...).
package main

import (
    "google.golang.org/appengine"
    "html/template"
    "net/http"
)

var MainTemplate *template.Template

func init() {
    http.HandleFunc("/", hello)
    MainTemplate, _= template.ParseFiles("html/main.html")
}

func main() {
    appengine.Main()
}

func hello(w http.ResponseWriter, r *http.Request) {
    c := r.Context()
    //................................//
    MainTemplate.Execute(w, nil)
}

This ought to work. appengine.Main() apparently connects you to all the appengine functionality needed to use the context for datastore / memcache / whatever operations.

Thank you to the commenters that helped me get over the first hump!

ThePiachu
  • 8,695
  • 17
  • 65
  • 94
0

Your code is missing the part to start a listener. Add this to your code:

    port := os.Getenv("PORT")
    if port == "" {
            port = "8080"
            log.Printf("Defaulting to port %s", port)
    }
    log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
John Hanley
  • 74,467
  • 6
  • 95
  • 159
  • Close, but that apparently doesn't let you use the `Context` properly for `datastore` and what have you. So it's good enough to display a web page, but not good enough for a full appengine app... – ThePiachu Oct 20 '19 at 23:28
  • @ThePiachu - Where is Datastore in your question? – John Hanley Oct 21 '19 at 00:57
  • It wasn't, I use it a few layers deeper, didn't know it was an issue until the first layer of issues was fixed. – ThePiachu Oct 21 '19 at 01:36