Зачем использовать указатель при использовании пользовательского http.Handler в Go? - PullRequest
0 голосов
/ 18 июня 2019

При вызове http.Handle() во фрагменте кода ниже я использую свой собственный тип templateHandler, который реализует интерфейс http.Handler.

package main

import (
    "html/template"
    "log"
    "net/http"
    "path/filepath"
    "sync"
)

type templateHandler struct {
    once     sync.Once
    filename string
    templ    *template.Template
}

func (t *templateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    t.once.Do(func() {
        t.templ = template.Must(template.ParseFiles(filepath.Join("templates", t.filename)))
    })
    t.templ.Execute(w, nil)
}

func main() {
    http.Handle("/", &templateHandler{filename: "chat.html"})
    if err := http.ListenAndServe(":8080", nil); err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

Теперь по какой-то причине я должен передать указатель на http.Handle(), используя &templateHandler{filename: "chat.html"}. Без & я получаю следующую ошибку:

cannot use (templateHandler literal) (value of type templateHandler) 
as http.Handler value in argument to http.Handle: 
missing method ServeHTTP

Почему именно это происходит? Какая разница с использованием указателя в этом случае?

1 Ответ

4 голосов
/ 18 июня 2019

http.Handle() ожидает значение (любое значение), которое реализует http.Handler, что означает, что он должен иметь метод ServeHTTP().

Вы использовали приемник указателя для метода templateHandler.ServeHTTP(), что означает, что только метод указателя на templateHandler имеет этот метод, но не метод не указателя templateHandler.

Спецификация: Наборы методов:

Тип может иметь набор методов , связанный с ним. Набор методов типа интерфейса является его интерфейсом. Набор методов любого другого типа T состоит из всех методов , объявленных с типом получателя T. Набор методов соответствующего типа указателя *T - это набор всех методов, объявленных с помощью приемника *T или T (то есть он также содержит набор методов T).

Тип без указателя имеет методы только с получателями без указателя. Тип указателя имеет методы как с указателями, так и с получателями без указателей.

Ваш метод ServeHTTP() изменяет приемник, поэтому он должен быть указателем. Но если какой-то другой обработчик не требуется, метод ServeHTTP() может быть создан с использованием приемника без указателя, и в этом случае вы можете использовать значение без указателя в качестве http.Handler, как в этом примере:

type myhandler struct{}

func (m myhandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {}

func main() {
    // non-pointer struct value implements http.Handler:
    http.Handle("/", myhandler{})
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...