返回顶部
+
-

go server框架学习之路 - 写一个自己的go框架

go server框架学习之路 - 写一个自己的go框架

推荐上 极客兔兔

他写的gee 相当一个精简的gin 关键 讲的比我好
具体链接 上我的首页置顶 资源帖

1 创建一个简单的框架

代码

package https

import "net/http"

// 创建自己的引擎
type Engine struct {

}
// 实现engine的ServeHTTP  有了这个方法 engine就属于一个http的handle了
func (e *Engine)ServeHTTP(w http.ResponseWriter, r *http.Request)  {
	w.Write([]byte("HTTP/1.0 200 OK\r\n" +
		"\r\n" +
		"你好中国"))
}

func Run()  {
	http.ListenAndServe(":8080",&Engine{})
}

测试代码和执行结果:

package main

import "gcw/pkg/https"

func main() {
	https.Run()
}


****************************************
HTTP/1.0 200 OK

你好中国

2 封装请求和响应

代码

package https

import "net/http"

// 统一上下文 以后写自己的 视图函数就不用写一长串参数了
type Context struct {
	Request *http.Request
	Writer  http.ResponseWriter
}
// 定义自己的HandlerFunc
type HandlerFunc func(*Context)

// 实现自己的HandlerFunc的ServeHTTP方法
func (f HandlerFunc) ServeHTTP(c *Context) {
	f(c)
}

// 创建自己的引擎
type Engine struct {}

// 实现engine的ServeHTTP  有了这个方法 engine就属于一个http的handle了
func (e *Engine)ServeHTTP(w http.ResponseWriter, r *http.Request)  {
	c := &Context{
		Request: r,
		Writer:  w,
	}
	testHandlerFunc(c)
}

func testHandlerFunc(c *Context)  {
	c.Writer.Write([]byte("测试2"))
}

func Run()  {
	//http.Handle("/", &Engine{})
	http.ListenAndServe(":8080",&Engine{})
}

测试代码和执行结果:

测试代码同1

************************
测试2

3 实现路由功能

代码

package https

import "net/http"

// 统一上下文 以后写自己的 视图函数就不用写一长串参数了
type Context struct {
	Request *http.Request
	Writer  http.ResponseWriter

	index 	int8		    // 配合next 执行handlers
	handlers []HandlerFunc  // 
	
}
// 执行下一个handle
func (c *Context) Next() {
	c.index++
	for c.index < int8(len(c.handlers)) {
		c.handlers[c.index](c)
		c.index++
	}
}
// 定义自己的HandlerFunc
type HandlerFunc func(*Context)

// 实现自己的HandlerFunc的ServeHTTP方法
func (f HandlerFunc) ServeHTTP(c *Context) {
	f(c)
}

// 路由
type Router struct {
	method	string
	root 	string
	handles []HandlerFunc
}
// 往engine 的 routers 中添加路由
func (e *Engine)AddRouter(method string, path string , h []HandlerFunc)  {
	e.routers[method+"_"+path] = &Router{
		method:  method,
		root:    path,
		handles: h,
	}
}
func (e *Engine)Get(path string, h ...HandlerFunc)  {
	e.AddRouter("GET", path, h)
}
func (e *Engine)POST(path string, h ...HandlerFunc)  {
	e.AddRouter("POST", path, h)
}
// 创建自己的引擎
type Engine struct {
	routers map[string]*Router
}

// 通过new 创建engine 初始化参数
func New() *Engine{
	return &Engine{routers:make(map[string]*Router)}
}


// 实现engine的ServeHTTP  有了这个方法 engine就属于一个http的handle了
func (e *Engine)ServeHTTP(w http.ResponseWriter, r *http.Request)  {
	method := r.Method
	path := r.RequestURI
	//remoteAddr := r.RemoteAddr
	router := e.routers[method+"_"+path]


	c := &Context{
		Request:  r,
		Writer:   w,
		index:    -1,
		handlers: router.handles,
	}
	c.Next()
}


func (e *Engine)Run()  {
	//http.Handle("/", &Engine{})
	http.ListenAndServe(":8080",e)
}

测试代码和执行结果:

package main

import "gcw/pkg/https"

func main() {
	app := https.New()
	app.Get("/hello", testHandlerFunc)
	app.Run()
}

func testHandlerFunc(c *https.Context)  {
	c.Writer.Write([]byte("测试3"))
}

4 完善路由404

代码

// 实现engine的ServeHTTP  有了这个方法 engine就属于一个http的handle了
func (e *Engine)ServeHTTP(w http.ResponseWriter, r *http.Request)  {
	method := r.Method
	path := r.RequestURI
	//remoteAddr := r.RemoteAddr
	router := e.routers[method+"_"+path]
	if router == nil {
		w.Write([]byte("404 你访问的页面不存在"))
		return
	}

	c := &Context{
		Request:  r,
		Writer:   w,
		index:    -1,
		handlers: router.handles,
	}
	c.Next()
}

测试代码和执行结果:

404 你访问的页面不存在

5 日志打印功能

新建logger.go

package https

import (
	"fmt"
	"path"
	"runtime"
	"time"
)
type loggerMessage struct {
	Millisecond       int64  `json:"timestamp"`
	MillisecondFormat string `json:"time_format"`
	LevelString       string `json:"level_string"`
	Body              string `json:"body"`
	Position          string `json:"position"`
}

type Logger struct {

}

func (logger *Logger) Writer(level string, msg string){
	funcName := "null"
	pc, file, line, ok := runtime.Caller(2)
	if !ok {
		file = "null"
		line = 0
	} else {
		funcName = runtime.FuncForPC(pc).Name()
	}
	_, filename := path.Split(file)

	loggerMsg := &loggerMessage{
		Millisecond:       time.Now().UnixNano() / 1e6,
		MillisecondFormat: time.Now().Format("2006-01-02 15:04:05.999"),
		LevelString:       level,
		Body:              msg,
		Position:          fmt.Sprintf("%s %d %s", filename, line, funcName),
	}

	logger.OutPut(loggerMsg)
}
func (logger *Logger)OutPut(msg *loggerMessage) {
	fmt.Println(msg)
}
func (logger *Logger)Info(msg string) {
	logger.Writer("info", msg)
}

engine 和 new中添加初始化log


func New() *Engine{
	return &Engine{
		routers:make(map[string]*Router),
		log:Logger{},
	}
}

type Engine struct {
	routers map[string]*Router
	log Logger
}

使用 及效果

tts = time.Now().UnixNano() - tts
e.log.Info(fmt.Sprintf("%s %s %s %3.6fs",remoteAddr, method, path, float64(float64(tts)/1e9)))

func (e *Engine)Run()  {
	//http.Handle("/", &Engine{})
	e.log.Info("服务器启动: 127.0.0.1:8080")
	http.ListenAndServe(":8080",e)
}

***************************************
&{1586071294752 2020-04-05 15:21:34.752 info 服务器启动: 127.0.0.1:8080 server.go 79 gcw/pkg/https.(*Engine).Run}
&{1586071298492 2020-04-05 15:21:38.492 info 127.0.0.1:54446 GET /hello 0.000000s server.go 66 gcw/pkg/https.(*Engine).ServeHTTP}

posted @ 2020-04-05 16:09  ham_731  阅读(602)  评论(0编辑  收藏  举报