When calling http.Handle()
in the code snippet below, I'm using my own templateHandler
type which implements the http.Handler
interface.
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)
}
}
Now for some reason I have to pass a pointer to http.Handle()
using &templateHandler{filename: "chat.html"}
. Without the &
I get the following error:
cannot use (templateHandler literal) (value of type templateHandler)
as http.Handler value in argument to http.Handle:
missing method ServeHTTP
Why exactly is this happening? What difference does using a pointer make in this case?
http.Handle()
expects a value (any value) that implements http.Handler
, which means it must have a ServeHTTP()
method.
You used pointer receiver for the templateHandler.ServeHTTP()
method, which means only a pointer value to templateHandler
has this method, but not that of a non-pointer templateHandler
type.
A type may have a method set associated with it. The method set of an interface type is its interface. The method set of any other type
T
consists of all methods declared with receiver typeT
. The method set of the corresponding pointer type*T
is the set of all methods declared with receiver*T
orT
(that is, it also contains the method set ofT
).
A non-pointer type only has methods with non-pointer receivers. A pointer type has methods both with pointer and non-pointer receivers.
Your ServeHTTP()
method modifies the receiver, so it must be a pointer. But if some other handler does not need to, the ServeHTTP()
method may be created using a non-pointer receiver, and in that case you can use a non-pointer value as the http.Handler
, like in this example:
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{})
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.