用 Go 实现一个 http server 非常容易,Go 语言标准库 net/http 自带了一系列结构和方法来帮助开发者简化 HTTP 服务开发的相关流程。因此,我们不需要依赖任何第三方组件就能构建并启动一个高并发的 HTTP 服务器。
基于 HTTP 构建的服务标准模型包括两个端,客户端 (Client) 和服务端 (Server)。HTTP 请求从客户端发出,服务端接受到请求后进行处理然后将响应返回给客户端。所以 http 服务器的工作就在于如何接受来自客户端的请求,并向客户端返回响应。
Demo1
1 2 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
方法
1 2 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
的定义
1 2 3
| type Handler interface { ServeHTTP(ResponseWriter, *Request) }
|
定义一个类型,实现ServeHTTP
方法,这个类型可以是一个func
类型
1 2 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
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
| 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
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
| // 反射执行方法调用 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 服务器]