Fragment Description:

The server program issues Google search requests and demonstrates the use of the Context API.
It serves on port 8080.
The /search endpoint accepts these query params:
q=the Google search query timeout=a timeout for the request, in time.Duration format For example, http://localhost:8080/search?q=golang&timeout=1s serves the first few Google search results for 'golang' or a 'deadline exceeded' error if the timeout expires.
see article here:


Last update, on 2015, Fri 9 Oct, 16:15:40

/* ... <== see fragment description ... */

package main

import (

func main() {
    http.HandleFunc("/search", handleSearch)
    log.Fatal(http.ListenAndServe(":8080", nil))

// handleSearch handles URLs like /search?q=golang&timeout=1s by forwarding
// the
// query to google.Search. If the query param includes timeout, the search is
// canceled after that duration elapses.
func handleSearch(w http.ResponseWriter, req *http.Request) {
    // ctx is the Context for this handler. Calling cancel closes the
    // ctx.Done channel, which is the cancellation signal for requests
    // started by this handler.
    var (
        ctx    context.Context
        cancel context.CancelFunc
    timeout, err := time.ParseDuration(req.FormValue("timeout"))
    if err == nil {
        // The request has a timeout, so create a context that is
        // canceled automatically when the timeout expires.
        ctx, cancel = context.WithTimeout(context.Background(), timeout)
    } else {
        ctx, cancel = context.WithCancel(context.Background())
    defer cancel() // Cancel ctx as soon as handleSearch returns.
    // Check the search query.
    query := req.FormValue("q")
    if query == "" {
        http.Error(w, "no query", http.StatusBadRequest)
    // Store the user IP in ctx for use by code in other packages.
    userIP, err := userip.FromRequest(req)
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
    ctx = userip.NewContext(ctx, userIP)
    // Run the Google search and print the results.
    start := time.Now()
    results, err := google.Search(ctx, query)
    elapsed := time.Since(start)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    if err := resultsTemplate.Execute(w, struct {
        Results          google.Results
        Timeout, Elapsed time.Duration
        Results: results,
        Timeout: timeout,
        Elapsed: elapsed,
    }); err != nil {

var resultsTemplate = template.Must(template.New("results").Parse(`
  {{range .Results}}
    <li>{{.Title}} - <a href="{{.URL}}">{{.URL}}</a></li>
  <p>{{len .Results}}  results in {{.Elapsed}}; timeout {{.Timeout}}</p>

/* More about Context:
 import ""
 Package context defines the Context type, which carries deadlines, cancellation signals, and other request-scoped values across API boundaries and between processes.
Incoming requests to a server should create a Context, and outgoing calls to servers should accept a Context. The chain of function calls between must propagate the Context, optionally replacing it with a modified copy created using WithDeadline, WithTimeout, WithCancel, or WithValue.
see details here: