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

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}

go server框架学习之路 - 写一个自己的go框架的更多相关文章

  1. 郑晔谈 Moco 框架的开发:写一个好的内部 DSL ,写一个表达性好的程序

    作者:张龙 出处:http://www.infoq.com/cn/news/2013/07/zhengye-on-moco 郑晔谈Moco框架的开发:写一个好的内部DSL,写一个表达性好的程序 作者  ...

  2. 用Python写一个简单的Web框架

    一.概述 二.从demo_app开始 三.WSGI中的application 四.区分URL 五.重构 1.正则匹配URL 2.DRY 3.抽象出框架 六.参考 一.概述 在Python中,WSGI( ...

  3. 【SpringCloud之pigx框架学习之路 】1.基础环境安装

    [SpringCloud之pigx框架学习之路 ]1.基础环境安装 [SpringCloud之pigx框架学习之路 ]2.部署环境 1.Cmder.exe安装 (1) windows常用命令行工具 下 ...

  4. 【SpringCloud之pigx框架学习之路 】2.部署环境

    [SpringCloud之pigx框架学习之路 ]1.基础环境安装 [SpringCloud之pigx框架学习之路 ]2.部署环境 1.下载代码 git clone https://git.pig4c ...

  5. 自己的Scrapy框架学习之路

    开始自己的Scrapy 框架学习之路. 一.Scrapy安装介绍 参考网上资料,先进行安装 使用pip来安装Scrapy 在开始菜单打开cmd命令行窗口执行如下命令即可 pip install Scr ...

  6. Summer——从头开始写一个简易的Spring框架

    Summer--从头开始写一个简易的Spring框架                ​ 参考Spring框架实现一个简易类似的Java框架.计划陆续实现IOC.AOP.以及数据访问模块和事务控制模块. ...

  7. 动手写一个简单的Web框架(模板渲染)

    动手写一个简单的Web框架(模板渲染) 在百度上搜索jinja2,显示的大部分内容都是jinja2的渲染语法,这个不是Web框架需要做的事,最终,居然在Werkzeug的官方文档里找到模板渲染的代码. ...

  8. 动手写一个简单的Web框架(Werkzeug路由问题)

    动手写一个简单的Web框架(Werkzeug路由问题) 继承上一篇博客,实现了HelloWorld,但是这并不是一个Web框架,只是自己手写的一个程序,别人是无法通过自己定义路由和返回文本,来使用的, ...

  9. 动手写一个简单的Web框架(HelloWorld的实现)

    动手写一个简单的Web框架(HelloWorld的实现) 关于python的wsgi问题可以看这篇博客 我就不具体阐述了,简单来说,wsgi标准需要我们提供一个可以被调用的python程序,可以实函数 ...

随机推荐

  1. 关于图数据库HugeGraph的百万,千万,亿量级测试

    1.Hugegraph测试硬件 1.1.本机硬件 本机测试hugeGraph版本:0.10.4 后置存储数据库:rocksdb,1TB的普通硬盘 1.2.测试服务器硬件 测试服务器hugegraph版 ...

  2. DIV的失去焦点(blur)实现

    用防抖实现DIV鼠标移出消失   由于div标签本身不支持onblur事件,所以对于点击一个按钮弹出的div,我们想要当这个div失去焦点的时候,让它消失不能使用的onblur来实现.  但是可以利用 ...

  3. 【jQuery学习日记】jQuery实现滚动动画

    需要实现的效果 样式分析: 2个主要部分,头部的标题和导航部分,和主要的功能实现区域: 1.头部 <div id="header"> <h1>动漫视频< ...

  4. 使用PHP语言制作具有加减乘除取余功能的简单计算器

    准备工作: 使用环境 :PHPStudy 开启Apache和Mysql 打开代码编辑器 <!DOCTYPE html> <html lang="en"> & ...

  5. sass片段

    变量: $color: #333; body { color: $color;} -----> body { color: #333; } 嵌套: nav { ul { margin: 0; } ...

  6. linux 读取 USB HID鼠标坐标和点击 在 LCD上显示

    首先要,编译内核时启用了 USB HID 设备.启用了 鼠标 . 在开发板上插入usb 时会有如下提示. 可以看到,多了一个 mouse0 和 eventX 打出来的是我的 联想鼠标. 1, 在 终端 ...

  7. scrapy pip中间件个人处理

    import pymongo from scrapy.conf import settings import pymysql class Mongodb_Pipeline(object): def _ ...

  8. go学习第四天、条件和循环

    循环 Go语言仅支持循环关键字 for for i := 0; i<5; i++ 示例 while 条件循环 while(n<5) n := 0 for n < 5 { n++ fm ...

  9. Spring Cloud 系列之 Netflix Hystrix 服务容错

    什么是 Hystrix Hystrix 源自 Netflix 团队于 2011 年开始研发.2012年 Hystrix 不断发展和成熟,Netflix 内部的许多团队都采用了它.如今,每天在 Netf ...

  10. ADO.NET 的使用(一)

    一.ADO.NET概要 ADO.NET 是一组向 .NET Framework 程序员公开数据访问服务的类. ADO.NET 为创建分布式数据共享应用程序提供了一组丰富的组件. 它提供了对关系数据.X ...