Программа server

Программа server обрабатывает запросы, такие как /search?q=golang, обслуживая первые несколько результатов поиска Google для golang. Она регистрирует handleSearch для обработки endpoint /search. Обработчик создает начальный Context с именем ctx и организует его отмену при возврате обработчика. Если запрос включает в себя параметр timeout в URL-адресе, Context отменится автоматически по истечении таймаута:

func handleSearch(w http.ResponseWriter, req *http.Request) {
    // ctx - это Context для данного обработчика. 
    // Вызов cancel закрывает канал ctx.Done, 
    // который является сигналом отмены запросов, 
    // запущенных этим обработчиком.
    var (
        ctx    context.Context
        cancel context.CancelFunc
    )
    timeout, err := time.ParseDuration(req.FormValue("timeout"))
    if err == nil {
        // Запрос имеет timeout, поэтому создайте context, 
        // который автоматически отменяется по истечении времени ожидания.
        ctx, cancel = context.WithTimeout(context.Background(), timeout)
    } else {
        ctx, cancel = context.WithCancel(context.Background())
    }
    defer cancel() // Отмена ctx при возврате handleSearch.

Обработчик берет query из запроса и извлекает IP-адрес клиента, вызывая пакет userip. IP-адрес клиента необходим для серверных запросов, поэтому handleSearch прикрепляет его к ctx:

    // Проверка поискового запроса
    query := req.FormValue("q")
    if query == "" {
        http.Error(w, "no query", http.StatusBadRequest)
        return
    }

    // Сохранение IP пользователя в ctx для дальнейшего использования в других пакетах
    userIP, err := userip.FromRequest(req)
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }
    ctx = userip.NewContext(ctx, userIP)

Обработчик вызывает google.Search с ctx и query:

    // Запуск Google поиска и вывод результатов.
    start := time.Now()
    results, err := google.Search(ctx, query)
    elapsed := time.Since(start)

Если поиск прошел успешно, обработчик отобразит результаты:

    if err := resultsTemplate.Execute(w, struct {
        Results          google.Results
        Timeout, Elapsed time.Duration
    }{
        Results: results,
        Timeout: timeout,
        Elapsed: elapsed,
    }); err != nil {
        log.Print(err)
        return
    }

results matching ""

    No results matching ""