A Go Task Queue Example

The following example defines a task handler (worker) that increments a counter in the datastore, mapped to the URL /worker. There is also a handler for an HTTP GET request that displays the current value of the counter, and a handler for an HTTP POST request that enqueues a task and returns. It's difficult to watch the counter increase if the queue is processing tasks quickly. Therefore, the push queue should customized using queue.yaml so its tasks are sent at the slow rate of one per second:

# Change the refresh rate of the default queue from 5/s to 1/s.
- name: default
  rate: 1/s

Here is the code for the application, including the task handler:

package counter

import (



func init() {
	http.HandleFunc("/", handler)
	http.HandleFunc("/worker", worker)

type Counter struct {
	Name  string
	Count int

func handler(w http.ResponseWriter, r *http.Request) {
	ctx := appengine.NewContext(r)
	if name := r.FormValue("name"); name != "" {
		t := taskqueue.NewPOSTTask("/worker", map[string][]string{"name": {name}})
		if _, err := taskqueue.Add(ctx, t, ""); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
	q := datastore.NewQuery("Counter")
	var counters []Counter
	if _, err := q.GetAll(ctx, &counters); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	if err := handlerTemplate.Execute(w, counters); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	// OK

func worker(w http.ResponseWriter, r *http.Request) {
	ctx := appengine.NewContext(r)
	name := r.FormValue("name")
	key := datastore.NewKey(ctx, "Counter", name, 0, nil)
	var counter Counter
	if err := datastore.Get(ctx, key, &counter); err == datastore.ErrNoSuchEntity {
		counter.Name = name
	} else if err != nil {
		log.Errorf(ctx, "%v", err)
	if _, err := datastore.Put(ctx, key, &counter); err != nil {
		log.Errorf(ctx, "%v", err)

var handlerTemplate = template.Must(template.New("handler").Parse(handlerHTML))

const handlerHTML = `
{{repeat .}}
<p>{{.Name}}: {{.Count}}</p>
<p>Start a new counter:</p>
<form action="/" method="POST">
<input type="text" name="name">
<input type="submit" value="Add">

Send feedback about...

App Engine standard environment for Go