如何在Go语言中编写一个简单的自定义HTTP服务器?

24

我是Go语言的新手,正在尝试编写自定义的HTTP服务器。但我遇到了编译错误。如何在我的代码中实现ServeHTTP方法?

我的代码:

package main

import (
    "net/http"
    "fmt"
    "io"
    "time"
)


func myHandler(w http.ResponseWriter, req *http.Request) {
    io.WriteString(w, "hello, world!\n")
}


func main() {
    // Custom http server
    s := &http.Server{
        Addr:           ":8080",
        Handler:        myHandler,
        ReadTimeout:    10 * time.Second,
        WriteTimeout:   10 * time.Second,
        MaxHeaderBytes: 1 << 20,
    }

    err := s.ListenAndServe()
    if err != nil {
        fmt.Printf("Server failed: ", err.Error())
    }
}

编译时出错:

.\hello.go:21: cannot use myHandler (type func(http.ResponseWriter, *http.Request)) as type http.Handler in field value:
    func(http.ResponseWriter, *http.Request) does not implement http.Handler (missing ServeHTTP method)
3个回答

24

你可以使用一个结构体并在其上定义ServeHTTP,或者简单地将您的函数包装在HandlerFunc中。

s := &http.Server{
    Addr:           ":8080",
    Handler:        http.HandlerFunc(myHandler),
    ReadTimeout:    10 * time.Second,
    WriteTimeout:   10 * time.Second,
    MaxHeaderBytes: 1 << 20,
}

你是不是想在“您要使用结构体并定义”中写“and”而不是“an”? - kometen
我该如何添加多个处理程序函数? - user1642018

6
为了使myHandler正常工作,它应该是一个符合Handler接口的对象,换句话说,myHandler应该有一个名为ServeHTTP的方法。
例如,假设myHandler是用于显示当前时间的自定义处理程序。代码应该如下所示:
package main

import (
    "fmt"
    "net/http"
    "time"
)

type timeHandler struct {
    zone *time.Location
}

func (th *timeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    tm := time.Now().In(th.zone).Format(time.RFC1123)
    w.Write([]byte("The time is: " + tm))
}

func newTimeHandler(name string) *timeHandler {
    return &timeHandler{zone: time.FixedZone(name, 0)}
}

func main() {

    myHandler := newTimeHandler("EST")
    //Custom http server
    s := &http.Server{
        Addr:           ":8080",
        Handler:        myHandler,
        ReadTimeout:    10 * time.Second,
        WriteTimeout:   10 * time.Second,
        MaxHeaderBytes: 1 << 20,
    }

    err := s.ListenAndServe()
    if err != nil {
        fmt.Printf("Server failed: ", err.Error())
    }
}

运行此代码并在浏览器中访问http://localhost:8080/。您应该看到像这样格式化的文本。
The time is: Sat, 30 Aug 2014 18:19:46 EST

你应该看到不同的时间。

希望这有所帮助,

更多阅读

Go中请求处理的回顾


1
谢谢。您的答案是正确的。但是,http.HandlerFunc(myHandler) 通过自动将ServeHTTP方法添加到myHandler中,从而满足了Handler接口,并简化了它。 - AnkurS
@AnkurS 好的,我也喜欢OneOfOne的回答。它更简单 :) - pyk

4

你也可以在将mux分配给服务器之前定义它并添加处理程序,如下所示。

func myHandler(w http.ResponseWriter, req *http.Request) {
   io.WriteString(w, "hello, world!\n")
}

func main(){

   // define a serveMux to handle routes
   mux := http.NewServeMux()
   // assign a route/todo to a handler myHandler
   mux.HandleFunc("/todo", myHandler)

   // assign a route/todo/notes to an anonymous func
   mux.HandleFunc("/todo/notes", func(w http.ResponseWriter, req *http.Request) {
       w.Write([]byte("Hello again."))
   })

   s := &http.Server{
      Addr:           ":8080",
      Handler:        mux,
      ReadTimeout:    10 * time.Second,
      WriteTimeout:   10 * time.Second,
      MaxHeaderBytes: 1 << 20,
   }

   if err := s.ListenAndServe(); err != nil {
      log.Fatalf("server failed to start with error %v", err.Error())
   }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接