A Go Task Queue Example

This example creates an app that displays an HTML form. You enter a string into the dialog box and click Add . The app counts the number of times that you enter any string in this way.

The app does these things:

  • When you click Add , the form uses an HTTP POST request to send the string to the app which is running on App Engine. There the app bundles the string into a task and sends it to the default queue.
  • The queue forwards the task to an included task handler, mapped to the URL /worker , which asynchronously writes the string to a datastore.
  • Sending an HTTP GET request displays a list of the strings you have entered and the number of times you have Add ed each string, either by typing it or by clicking on it in the dropdown box.

To deploy this app to App Engine:

  1. Copy the following into a file named queue.yaml . This changes the rate at which tasks will be processed from the default 5 per second to 3 per second.

      queue 
     : 
     - 
      
     name 
     : 
      
     default 
      
     rate 
     : 
      
     3/s 
     
    
  2. In the same directory, copy the following into a file named as you like (ending in .go ). This is the application code, including the task handler.

      package 
      
     counter 
     import 
      
     ( 
      
     "html/template" 
      
     "net/http" 
      
     "google.golang.org/appengine" 
      
     "google.golang.org/appengine/datastore" 
      
     "google.golang.org/appengine/log" 
      
     "google.golang.org/appengine/taskqueue" 
     ) 
     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 
     ) 
      
     return 
      
     } 
      
     } 
      
     q 
      
     := 
      
     datastore 
     . 
     NewQuery 
     ( 
     "Counter" 
     ) 
      
     var 
      
     counters 
      
     [] 
     Counter 
      
     if 
      
     _ 
     , 
      
     err 
      
     := 
      
     q 
     . 
     GetAll 
     ( 
     ctx 
     , 
      
    & counters 
     ); 
      
     err 
      
     != 
      
     nil 
      
     { 
      
     http 
     . 
     Error 
     ( 
     w 
     , 
      
     err 
     . 
     Error 
     (), 
      
     http 
     . 
     StatusInternalServerError 
     ) 
      
     return 
      
     } 
      
     if 
      
     err 
      
     := 
      
     handlerTemplate 
     . 
     Execute 
     ( 
     w 
     , 
      
     counters 
     ); 
      
     err 
      
     != 
      
     nil 
      
     { 
      
     http 
     . 
     Error 
     ( 
     w 
     , 
      
     err 
     . 
     Error 
     (), 
      
     http 
     . 
     StatusInternalServerError 
     ) 
      
     return 
      
     } 
      
     // 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 
     ) 
      
     return 
      
     } 
      
     counter 
     . 
     Count 
     ++ 
      
     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 
      
     = 
      
     ` 
    {{range .} } 
    < p>{{.Name}}: {{.Count}}</p> 
    {{end} } 
    < p>Start a new counter:</p> 
    < form action="/" method="POST" 
    >
    < input type="text" name="name" 
    >
    < input type="submit" value="Add" 
    >
    < /form 
    > ` 
     
    
  3. In the same directory, copy the following into a file named app.yaml . This configures your application for App Engine:

      runtime 
     : 
      
     go 
     api_version 
     : 
      
     go1 
     handlers 
     : 
     - 
      
     url 
     : 
      
     /worker/.* 
      
     script 
     : 
      
     _go_app 
      
     login 
     : 
      
     admin 
     - 
      
     url 
     : 
      
     /.* 
      
     script 
     : 
      
     _go_app 
     
    
  4. Make sure you have a Google Cloud Platform project with an App Engine app prepared and that you have initialized and configured the gcloud command for that project.

  5. Use the gcloud app deploy command to deploy the app to App Engine.

  6. See the app in action by using the gcloud app browse command.

Create a Mobile Website
View Site in Mobile | Classic
Share by: