在Go中使用自定义http.Handler时为什么要使用指针?

时间:2019-06-18 15:51:50

标签: pointers go methods interface

在下面的代码段中调用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 个答案:

答案 0 :(得分:4)

http.Handle()期望实现http.Handler的值(任何值),这意味着它必须具有ServeHTTP()方法。

您为templateHandler.ServeHTTP()方法使用了指针接收器,这意味着只有指向templateHandler的指针值才具有此方法,但没有非指针templateHandler类型的指针值。

Spec: Method sets:

  

类型可能具有与之关联的方法集interface type的方法集是其接口。任何其他类型T的方法集都由声明为接收者类型T的所有methods组成。相应的pointer type *T的方法集是用接收者*TT声明的所有方法的集合(也就是说,它还包含{{1 }}。

非指针类型仅具有带有非指针接收器的方法。指针类型同时具有指针接收者和非指针接收者的方法。

您的T方法修改了接收者,因此它必须是一个指针。但是,如果不需要其他处理程序,则可以使用非指针接收器创建ServeHTTP()方法,在这种情况下,您可以将非指针值用作ServeHTTP(),就像这样例如:

http.Handler