dotdx80642 2019-06-18 15:51
浏览 227
已采纳

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

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?

  • 写回答

1条回答 默认 最新

  • douyanguo7964 2019-06-18 15:59
    关注

    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.

    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. 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).

    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{})
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 求.net core 几款免费的pdf编辑器
  • ¥20 SQL server表计算问题
  • ¥15 C# P/Invoke的效率问题
  • ¥20 thinkphp适配人大金仓问题
  • ¥20 Oracle替换.dbf文件后无法连接,如何解决?(相关搜索:数据库|死循环)
  • ¥15 数据库数据成问号了,前台查询正常,数据库查询是?号
  • ¥15 算法使用了tf-idf,用手肘图确定k值确定不了,第四轮廓系数又太小才有0.006088746097507285,如何解决?(相关搜索:数据处理)
  • ¥15 彩灯控制电路,会的加我QQ1482956179
  • ¥200 相机拍直接转存到电脑上 立拍立穿无线局域网传
  • ¥15 (关键词-电路设计)