In this section, we shall look at an existing demo program that we ran in the Installation and Setup tutorial. This will be a good place to start analysing and understanding Go programs for the Google AppEngine and will allow us to move on to larger programs of our own.
To give a few more details …
application: When you upload your locally developed code to the AppEngine for hosting, this is the unique identifier that is used, and you will be prompted for it each time you create a new application on the AppEngine Administration Console. While you are developing and testing programs locally, this does not matter much.
version: Your application versioning information can contain alphanumeric characters, and hyphens. You can have any number of versions uploaded to the AppEngine but only one of them can be set as default. This allows you to create versions for testing (say like 3-01-8202-test) before being publicly deployed as the default.
runtime: Since we are working with go, "go" is what we put here. As of this writing, the AppEngine also supports Java and Python.
api_version: As the
handlers: This section mainly contains regular expressions which are compared, in the order of appearance within the yaml file, with the URL that tries to access the application. This will interpret the part of the URL following the application id, and depending on which is matched the appropriate static files are served or the go program is run. You could imagine that this section is like a
static_files: Certain files like images or pdfs are usually non-changing. These are treated differently as they can be optimized for returning data to the browser. For example, since they are usually unchanging, these files could be copied across different AppEngine servers in different geographic locations, allowing them to be served faster to the user. In this example there is only the image file
upload: This value defines what files will be uploaded from your local development environmen to the AppEngine server when the application is deployed each time. In this particular case it is saying that only the local file
script: _go_app: This exact string is required when testing the application locally with
At this point, if your application has run properly, you can navigate to http://localhost:8080/ to check that it is working as we saw in Installation and Setup tutorial. Now let’s try some others.
Because of
Because of
http://localhost:8080/
http://localhost:8080/abcd
http://localhost:8080/something/somethingelse
http://localhost:8080/favicon.icoandmore
Directory Structure
The list of files undergoogle_appengine/demos/helloworld
is as shown below:
helloworld/favicon.ico
helloworld/app.yaml
helloworld/helloworld/
helloworld/helloworld/helloworld.go
A side note: When you write your own programs later, note that only the
app.yaml
has to be named exactly like that. All other files and folders can take whatever name you prefer and they do not have to match with each other in folder name, file name, or package name.The .yaml file
The .yaml file is a configuration file. The AppEngine that hosts and executes your programs reads and interprets this file when you upload your application to the AppEngine for it to be hosted, and also when it is executed as and when users access it. A comprehensive definition of the possible contents of the.yaml
file is available at appconfig. I shall only attempt to cover the relevant sections for a beginner’s understanding of the .yaml
file. The contents of the file for this program are as shown below. I have added comments in addition to the original file after the #.application: helloworld # A unique identifier that distinguishes this application among the various AppEngine applications version: 1 # The version of your application. runtime: go # The programming language used by this application. api_version: 3 # The version of the AppEngine that this application uses. handlers: # Routing of different urls to different types of handlers, e.g. maybe to a go program or directly to the static file. - url: /favicon\.ico # If there is a URL of the form ‘application_root’/favicon.ico, then ... static_files: favicon.ico # … serve this static file back to the browser. upload: favicon\.ico # When uploading from your local directory to AppEngine, these are the local files that have to be updated. - url: /.* # For all other URL patterns … script: _go_app # … run the main application.
To give a few more details …
application: When you upload your locally developed code to the AppEngine for hosting, this is the unique identifier that is used, and you will be prompted for it each time you create a new application on the AppEngine Administration Console. While you are developing and testing programs locally, this does not matter much.
version: Your application versioning information can contain alphanumeric characters, and hyphens. You can have any number of versions uploaded to the AppEngine but only one of them can be set as default. This allows you to create versions for testing (say like 3-01-8202-test) before being publicly deployed as the default.
runtime: Since we are working with go, "go" is what we put here. As of this writing, the AppEngine also supports Java and Python.
api_version: As the
go
language and the AppEngine continues to evolve, there are changes and incompatibilites between versions. Therefore you need to specify which of the api_versions you are using. As of this writing in October 2011, the Go language and the AppEngine for Go is still experimental and changes will be faster and previous versions will be deprecated fairly quickly. The supported versions of the AppEngine is usually announced and available in the appropriate Google Groups: google-appengine-go. handlers: This section mainly contains regular expressions which are compared, in the order of appearance within the yaml file, with the URL that tries to access the application. This will interpret the part of the URL following the application id, and depending on which is matched the appropriate static files are served or the go program is run. You could imagine that this section is like a
switch-case
satatement in Go where the incoming URL is switch
ed against the regular expressions in the case
/- url:
statement, and then the first matching block is executed.static_files: Certain files like images or pdfs are usually non-changing. These are treated differently as they can be optimized for returning data to the browser. For example, since they are usually unchanging, these files could be copied across different AppEngine servers in different geographic locations, allowing them to be served faster to the user. In this example there is only the image file
favicon.ico
that is static and it is also in the application root directory within the AppEngine. Typically though, you would want it in a separate directory which is by convention named static
.upload: This value defines what files will be uploaded from your local development environmen to the AppEngine server when the application is deployed each time. In this particular case it is saying that only the local file
favicon.ico
is to be uploaded. If instead you wrote images/(*.ico|*.gif|*.jpg)
, it will upload all these types of files within the local images
directory onto the AppEngine server.script: _go_app: This exact string is required when testing the application locally with
dev_appserver.py
but is not used by the AppEngine server.For the full
yaml
specification, you can refer to the site yaml.org.
Checking URLs and URL handlers
In case URL handlers are new to you, let’s just go over them once to see how they work. First run the AppEngine application locally as below from within thegoogle_appengine/demos
directory:At this point, if your application has run properly, you can navigate to http://localhost:8080/ to check that it is working as we saw in Installation and Setup tutorial. Now let’s try some others.
Because of
url: /favicon\.ico
and static_files: favicon.ico
you should be able to see that file being served to the browser by following the link http://localhost:8080/favicon.ico. It is served statically to the browser, but the user will not have a way of knowing that.Because of
- url: /.*
and script: _go_app
, which is a catch all for all URLs, provided that it is not already handled by a previous url
handler, all other URLs will be directed to the main application. So all of the below and all other valid URLs (except http://localhost:8080/favicon.ico) that you can think of running at this server and port will be redirected to the main application.http://localhost:8080/
http://localhost:8080/abcd
http://localhost:8080/something/somethingelse
http://localhost:8080/favicon.icoandmore
The Go code
The Go code itself in this case is a very simple web application. You can read through the other writeup on an introduction to web applications at: Web programming with Go - first web Hello World. I have reproduced the code here with some comments that might be helpful if you are fairly new to web programming with Go.Full program
package helloworld import ( "fmt" "http" // import standard http package ) func init() { http.HandleFunc("/", handle) // define the main initialization function. This one defines that all incoming requests are to be passed on to the "handle" function below. } func handle(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Hello, World! 세상아 안녕!") // send back a small html stream with a greeting }
An important side note. Go coding for the web and for the AppEngine is very simple to get started with. Even for absolute beginners. I would strongly encourage you to just go for it and try it out. Most of what I have gone into detail here is boilerplate code that one tends to reuse, and the long-ish explanation of the syntax within this particular write-up should be mostly seen for reference when you have a doubt.
Good topic, thanks !
ReplyDelete