当前位置:   article > 正文

day 1 HTTP基础

day 1 HTTP基础

https://geektutu.com/post/gee-day3.html

仅仅是一个笔记,在此对geektutu大神膜拜

package main
​
import (
    "fmt"
    "log"
    "net/http"
)
​
func main() {
    http.HandleFunc("/", indexHandler)
    http.HandleFunc("/hello", helloHandler)
    log.Fatal(http.ListenAndServe(":9999", nil))
    //log.Fatal用来检测错误,如果出现了错误,就会调用log.Fatal函数来记录错误并终止程序执行
    //第二个参数为nil,说明使用默认的路由器
}
​
// handler echoes r.URL.Path
func indexHandler(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintf(w, "URL.Path = %q\n", req.URL.Path)
}
​
// handler echoes r.URL.Header
func helloHandler(w http.ResponseWriter, req *http.Request) {
    for k, v := range req.Header {
        fmt.Fprintf(w, "Header[%q] = %q\n", k, v)
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

用curl这个工具测试

$ curl http://localhost:9999/
URL.Path = "/"
$ curl http://localhost:9999/hello
Header["Accept"] = ["*/*"]
Header["User-Agent"] = ["curl/7.54.0"]
  • 1
  • 2
  • 3
  • 4
  • 5

首先我们来解释一下curl

curl是一个命令行工具和库,用于在各种网络协议下传输数据,支持多种数据

curl可以通过URL从服务器下载或上传数据,具有许多功能

package main
​
import (
    "fmt"
    "log"
    "net/http"
)
​
// Engine is the uni handler for all requests
type Engine struct{}
​
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    switch req.URL.Path {
    case "/":
        fmt.Fprintf(w, "URL.Path = %q\n", req.URL.Path)
    case "/hello":
        for k, v := range req.Header {
            fmt.Fprintf(w, "Header[%q] = %q\n", k, v)
        }
    default:
        fmt.Fprintf(w, "404 NOT FOUND: %s\n", req.URL)
    }
}
​
func main() {
    engine := new(Engine)
    log.Fatal(http.ListenAndServe(":9999", engine))
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

注意,我们现在已经自己实现了ServeHTTP,有了自己的处理思维了,而不在需要按照之前系统默认的那样,还需要创建一个处理程序,但是我们也不可能将所有的处理函数都放在ServeHTTP中,这个时候,我们需要沿着如何更好的回应系统中的请求的方向继续设计

实现http.Handler接口

观察源码:

package http
​
type Handler interface {
    ServeHTTP(w ResponseWriter, r *Request)
}
​
func ListenAndServe(address string, h Handler) error
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

我们主要观察ListenAndServe的第二个参数,Handler是一个接口,也就是说只要实现了ServeHTTP就能传入Handler,所有的HTTP请求也就交给这个

我首先是实现了gee.go

没错,我们在是实现ServeHTTP函数的基础上,将这个函数变成了一个类型map[stirng]HandlerFunc ,并且将它命名为router进行封装

func main() {
    http.HandleFunc("/", indexHandler)
    http.HandleFunc("/hello", helloHandler)
    log.Fatal(http.ListenAndServe(":9999", nil))
    //log.Fatal用来检测错误,如果出现了错误,就会调用log.Fatal函数来记录错误并终止程序执行
    //第二个参数为nil,说明使用默认的路由器
}
​
// handler echoes r.URL.Path
func indexHandler(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintf(w, "URL.Path = %q\n", req.URL.Path)
}
​
// handler echoes r.URL.Header
func helloHandler(w http.ResponseWriter, req *http.Request) {
    for k, v := range req.Header {
        fmt.Fprintf(w, "Header[%q] = %q\n", k, v)
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

猜测原始代码中,我们使用http.HandleFunc是让默认的路由处理器增添方法,我们也需要用一个函数来增添我们的方法,与这个类似

package gee
​
import (
    "fmt"
    "net/http"
)
​
type HandlerFunc func(http.ResponseWriter, *http.Request)
​
// Engine implement the interface of ServeHTTP
type Engine struct {
    router map[string]HandlerFunc
}
​
// New is the constructor of gee.Engine
func New() *Engine {
    return &Engine{router: make(map[string]HandlerFunc)}
}
​
func (engine *Engine) addRoute(method string, pattern string, handler HandlerFunc) {
    key := method + "-" + pattern
    engine.router[key] = handler
}
​
// GET defines the method to add GET request
func (engine *Engine) GET(pattern string, handler HandlerFunc) {
    engine.addRoute("GET", pattern, handler)
}
​
// POST defines the method to add POST request
func (engine *Engine) POST(pattern string, handler HandlerFunc) {
    engine.addRoute("POST", pattern, handler)
}
​
// Run defines the method to start a http server
func (engine *Engine) Run(addr string) (err error) {
    return http.ListenAndServe(addr, engine)
}
​
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    key := req.Method + "-" + req.URL.Path
    if handler, ok := engine.router[key]; ok {
        /*
            注意router是一个map结构 map[key]HandlerFunc
            if的目的是找到对应路径的处理器
​
        */
        handler(w, req)
    } else {
        fmt.Fprintf(w, "404 NOT FOUND:%s\n", req.URL)
    }
}
​
​
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

知道我们为什么要设置请求方法吗,这个不是URL中的功能,

GET很容易在URL中看出,但是POST并不容易

这两者都是由服务器自动识别的,不是说我们在访问URL的时候,还去写一个POST和GET

然后发现引入包的时候引入不了,原来是要将go.mod和main.go在一起

原谅我前面学的太差了

package main
​
import (
    "example/gee"
    "fmt"
    "net/http"
)
​
func main() {
    r := gee.New()
    r.GET("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "URL.Path = %q\n", r.URL.Path)
    })
​
    r.GET("/hello", func(w http.ResponseWriter, r *http.Request) {
        for k, v := range r.Header {
            fmt.Fprintf(w, "Header[%q] = %q\n", k, v)
        }
    })
}
​
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

老老实实编写

package main
​
import (
    "example/gee"
    "fmt"
    "net/http"
)
​
func main() {
    r := gee.New()
    r.GET("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "URL.Path = %q\n", r.URL.Path)
    })
​
    r.GET("/hello", func(w http.ResponseWriter, r *http.Request) {
        for k, v := range r.Header {
            fmt.Fprintf(w, "Header[%q] = %q\n", k, v)
        }
    })
    /*
        GET方法是用添加路由的
    从源码中就能看到GET最终指向的其实是路由器
    */
    r.Run(":9999")
}
​
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

接着我们用gitbash将这个day1的实验结束

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号