简体   繁体   English

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

[英]Why use a pointer when using a custom http.Handler in Go?

When calling http.Handle() in the code snippet below, I'm using my own templateHandler type which implements the http.Handler 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)
    }
}

Now for some reason I have to pass a pointer to http.Handle() using &templateHandler{filename: "chat.html"} . 现在由于某种原因,我必须使用&templateHandler{filename: "chat.html"}传递指向http.Handle()的指针。 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. http.Handle()需要一个实现http.Handler的值(任何值),这意味着它必须具有ServeHTTP()方法。

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. 您为templateHandler.ServeHTTP()方法使用了指针接收器,这意味着仅指向templateHandler的指针值具有此方法,而没有非指针templateHandler类型的指针。

Spec: Method sets: 规格:方法组:

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 type T . 其他任何类型T的方法集都包含以接收者类型T声明的所有方法 The method set of the corresponding pointer type *T is the set of all methods declared with receiver *T or T (that is, it also contains the method set of T ). 对应的指针类型 *T的方法集是用接收者*TT声明的所有方法的集合(也就是说,它还包含T的方法集)。

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. 您的ServeHTTP()方法会修改接收方,因此它必须是一个指针。 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: 但是,如果不需要其他处理程序,则可以使用非指针接收器创建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{})
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM