用 Go 实现一个 http server 非常容易,Go 语言标准库 net/http 自带了一系列结构和方法来帮助开发者简化 HTTP 服务开发的相关流程。因此,我们不需要依赖任何第三方组件就能构建并启动一个高并发的 HTTP 服务器。
基于 HTTP 构建的服务标准模型包括两个端,客户端 (Client) 和服务端 (Server)。HTTP 请求从客户端发出,服务端接受到请求后进行处理然后将响应返回给客户端。所以 http 服务器的工作就在于如何接受来自客户端的请求,并向客户端返回响应。
Demo1
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | package main
 import (
 "fmt"
 "net/http"
 )
 
 func HelloHandler(w http.ResponseWriter, r *http.Request) {
 fmt.Fprintf(w, "Hello World")
 }
 
 func main () {
 http.HandleFunc("/", HelloHandler)
 http.ListenAndServe(":8080", nil)
 }
 
 | 
Demo2
实现ServeHTTP方法
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 
 | package main
 import (
 "fmt"
 "net/http"
 )
 
 type HelloHandlerStruct struct {
 content string
 }
 
 func (handler *HelloHandlerStruct) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 fmt.Fprintf(w, handler.content)
 }
 
 func main()  {
 http.Handle("/", &HelloHandlerStruct{content: "Hello World"})
 http.ListenAndServe(":8000", nil)
 }
 
 | 
我们查看net/http包可以看到Handler的定义
| 12
 3
 
 | type Handler interface {ServeHTTP(ResponseWriter, *Request)
 }
 
 | 
定义一个类型,实现ServeHTTP方法,这个类型可以是一个func类型
| 12
 3
 4
 5
 6
 
 | type HandlerFunc func(ResponseWriter, *Request)
 // ServeHTTP calls f(w, r).
 func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
 f(w, r)
 }
 
 | 
通过反射调用func
| 12
 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
 
 | type Handle func(w http.ResponseWriter, r *http.Request)
 type Router struct {
 paths map[string]Handle
 }
 
 //register handle
 func (r *Router) AddPath(path string, controller Handle) {
 if r.paths == nil {
 r.paths = map[string]Handle{}
 }
 paths := r.paths
 paths[path] = controller
 r.paths = paths
 }
 
 func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 if handle, ok := r.paths[req.URL.Path]; ok {
 handle(w, req)
 } else {
 //method not register
 
 w.WriteHeader(http.StatusInternalServerError)
 err := fmt.Errorf("method %s is not found", req.URL.Path)
 w.Write([]byte(err.Error()))
 
 }
 }
 
 | 
注册handle
| 1
 | r.AddPath("/hello", Action((*controllers.HelloController).Hello))
 | 
通过反射,动态调用handle
| 12
 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
 
 | // 反射执行方法调用func Action(action interface{}) Handle {
 val := reflect.ValueOf(action)
 if val.Kind() != reflect.Func {
 panic("action not func")
 }
 t := val.Type()
 
 //确保方法返回参数为error
 out := t.Out(0)
 if !out.Implements(interfaceOf((*error)(nil))) {
 fmt.Println("Action return not error")
 }
 
 t = t.In(0)
 for t.Kind() == reflect.Ptr {
 t = t.Elem()
 }
 // 确保
 if !reflect.PtrTo(t).Implements(interfaceOf((*controllers.Controller)(nil))) {
 panic("not implement controller")
 }
 
 return func(w http.ResponseWriter, r *http.Request) {
 v := reflect.New(t)
 
 //反射获取controller
 c := v.Interface().(controllers.Controller)
 //init
 err := c.Init(w, r)
 defer c.Destroy()
 if err != nil {
 c.Error(err)
 return
 }
 //反射调用方法
 ret := val.Call([]reflect.Value{v})[0].Interface()
 //fmt.Println(reflect.TypeOf(ret))
 if ret != nil {
 c.Error(ret.(error))
 return
 }
 }
 }
 
 func interfaceOf(value interface{}) reflect.Type {
 t := reflect.TypeOf(value)
 
 for t.Kind() == reflect.Ptr {
 t = t.Elem()
 }
 
 return t
 }
 
 | 
源码https://github.com/pangxieke/simple
复杂框架
上面的框架组件基本自己开发,但现在已经有很多完善的组件,我们只要好好利用,就可以开发出适合自己的框架。
例如logger,router等都不需要自己开发
自己将常用的框架文件,config配置,数据库连接等集合在一起,组成了一个工作中实际可用的框架。
源码https://github.com/pangxieke/portray
参考文章
Go Web 编程入门–深入学习用 Go 编写 HTTP 服务器]