How to write a simple custom HTTP server in Go?

huangapple go评论89阅读模式
英文:

How to write a simple custom HTTP server in Go?

问题

我是你的中文翻译助手,以下是你要翻译的内容:

我刚开始学习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() {
	// 自定义http服务器
	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("服务器启动失败:%s", 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)

请问我该如何解决这个问题?

英文:

I am new to Go and trying to write a custom HTTP server. I'm getting a compilation error. How can I implement the ServeHTTP method in my code?

My Code:

package main

import (
	&quot;net/http&quot;
	&quot;fmt&quot;
	&quot;io&quot;
	&quot;time&quot;
)


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


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

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

Error while compiling:

<!-- language: lang-none -->

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

答案1

得分: 24

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

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

You either use a struct and define ServeHTTP on it or simply wrap your function in a HandlerFunc

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

答案2

得分: 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")
	//自定义http服务器
	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中请求处理的回顾

英文:

in order to work properly, myHandler should be an object that satisfy the Handler Interface, in other words myHandler should have method called ServeHTTP.

For example, let's say that myHandler is custom handler for showing the current time. The code should be like this

package main

import (
	&quot;fmt&quot;
	&quot;net/http&quot;
	&quot;time&quot;
)

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(&quot;The time is: &quot; + tm))
}

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

func main() {

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

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

run this code and access http://localhost:8080/ in your browser. you should see formatted text like this

The time is: Sat, 30 Aug 2014 18:19:46 EST

(you should see different time.)

hope this help,

Further more reading

A Recap of Request Handling in Go

答案3

得分: 4

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

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

func main(){

   // 定义一个serveMux来处理路由
   mux := http.NewServeMux()
   // 将路由/todo分配给处理程序myHandler
   mux.HandleFunc("/todo", myHandler)

   // 将路由/todo/notes分配给匿名函数
   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())
   }
}
英文:

You could also define a mux and add handlers to it before assigning it to the server like below.

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

func main(){

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

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

   s := &amp;http.Server{
	  Addr:           &quot;:8080&quot;,
	  Handler:        mux,
	  ReadTimeout:    10 * time.Second,
	  WriteTimeout:   10 * time.Second,
	  MaxHeaderBytes: 1 &lt;&lt; 20,
   }

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

huangapple
  • 本文由 发表于 2014年8月30日 21:47:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/25583028.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定