从零实现gin day01

898 阅读2分钟

前言

刚开始学go想着不能一直输入,得有点输出才能记得住学的东西,故决定写一些学习笔记来记录自己的学习历程.

知识点

  • 使用go开启TCP服务
  • 使用go发送http请求
  • 实现TCP监听回调服务

http请求封装

怎么用go开启TCP服务

package main  
  
import (  
    "fmt"  
    "log"  
    "net/http"  
)  
  
func main() {  
    http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {  
    writer.Write([]byte(fmt.Sprintf("hello %s\n", "cc")))  
})  
  
    log.Fatal(http.ListenAndServe(":7999", nil))  
}

http.HandleFunc 添加一个路由,添加了路由我们怎么去监听这个路由是否正确呢?http.ListenAndServe中的第二个参数就派上用场了,从源码中可以看到,在开启TCP监听端口之后会回调一个handler requests这个Handler是一个接口,里面有一个ServeHTTP方法,所以只要实现了这个方法的都可以作为参数传给ListenAndServe

监听源码

type Handler interface {  
    ServeHTTP(ResponseWriter, *Request)  
}
// ListenAndServe listens on the TCP network address addr and then calls  
// Serve with handler to handle requests on incoming connections.  
// Accepted connections are configured to enable TCP keep-alives.
// ListenAndServe always returns a non-nil error.  
func ListenAndServe(addr string, handler Handler) error {  
    server := &Server{Addr: addr, Handler: handler}  
    return server.ListenAndServe()  
}

实现

package main  
  
import (  
    "fmt"  
    "net/http"  
)  
  
type Engine struct {  
}  
  
func (e *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) {  
    path := r.URL.Path  
    if path == "/" {  
        fmt.Fprint(w, "index")  
    } else if path == "/hello" {  
        fmt.Fprint(w, "hello world")  
    } else {  
        fmt.Fprint(w, "404")  
    }  
}

那么main函数中的ListenAndServe就可以直接使用这个作为回调方法传入.

func main() {  
    http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {  
        writer.Write([]byte(fmt.Sprintf("hello %s\n", "cc")))  
    })   
    e := new(Engine)  
    log.Fatal(http.ListenAndServe(":7999", e))  
}

我们使用postman进行测试,都出现了我们预期的结果,但是在http.HandleFunc中写的匿名函数并没有执行,要想这个匿名函数执行就要把其放到ServeHTTP中去.所以我们可以进一步改造.

给Engine添加router,封装Post,Get,Run方法

package main  
  
import (  
    "fmt"  
    "net/http"  
)  
  
type HandleFunc http.HandlerFunc  
  
type Engine struct {  
    router map[string]HandleFunc  
}  
  
func newEngine() *Engine {  
    return &Engine{router: make(map[string]HandleFunc)}  
}  
  
func (e *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) {  
    key := r.Method + "-" + r.URL.Path  
    if h, ok := e.router[key]; ok {  
        h(w, r)  
    } else {  
        w.WriteHeader(http.StatusNotFound)
        fmt.Fprint(w, "404")  
    }  
}  
func (e *Engine) AddRouter(method string, path string, handle HandleFunc) {  
    key := method + "-" + path  
    e.router[key] = handle  
}  
func (e *Engine) Post(path string, handle HandleFunc) {  
    e.AddRouter("POST", path, handle)  
}  
func (e *Engine) Get(path string, handle HandleFunc) {  
    e.AddRouter("GET", path, handle)  
}  
  
func (e *Engine) Run(addr string) (err error) {  
    return http.ListenAndServe(addr, e)  
}

我们给Engine添加了一个router变量,类型为map[string]HandleFunc这样就能通过key找到其对应的HandleFunc方法,从而执行.

总结

本章我们完成了TCP服务监听的封装,并能通过Post,Get添加路由请求,并且能对不存在的路由进行提示.

更多详情连接:geektutu.com/post/gee.ht…