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. 提高开发效率之VS Code基础配置篇

    背景 之前一直是只用WebStorm作为IDE来编写代码,但是由于: 手中的这台Mac接了两个显示器以后,使用WebStorm会有卡顿. WebStorm需要付费(虽然可以通过某方法和谐). 所以需要 ...

  2. CSS-水平居中、垂直居中、水平垂直居中

    1.水平居中 水平居中可分为行内元素水平居中和块级元素水平居中 1.1 行内元素水平居中 这里行内元素是指文本text.图像img.按钮超链接等,只需给父元素设置text-align:center即可 ...

  3. Levenshtein Distance(编辑距离)算法与使用场景

    前提 已经很久没深入研究过算法相关的东西,毕竟日常少用,就算死记硬背也是没有实施场景导致容易淡忘.最近在做一个脱敏数据和明文数据匹配的需求的时候,用到了一个算法叫Levenshtein Distanc ...

  4. 带着问题,再读ijkplayer源码

    问题 主流程上的区别 缓冲区的设计 内存管理的逻辑 音视频播放方式 音视频同步 seek的问题:缓冲区flush.播放时间显示.k帧间距大时定位不准问题- stop时怎么释放资源,是否切换到副线程? ...

  5. WSGI-mini-web框架服务器

    前期准备: 安装python环境安装pycharm安装MySQL数据库安装pymsql创建一个学生表,存入数据我们只是实现一个非常简单的web服务,前端页面不会专门做页面文件,会在代码中以具体命令的形 ...

  6. 内存管理 malloc free 的实现

    libc 中提供非常好用的  malloc free 功能,如果自己实现一个,应该怎么做. 要实现 malloc free 需要有 可以分配内存使用的堆,和记录内存使用情况的链表. 如下图所示,堆从高 ...

  7. Django中使用CORS实现跨域请求

    跨域请求: ​    请求url包含协议.网址.端口,任何一种不同都是跨域请求. 1.安装cors模块 pip install django-cors-headers2.添加应用 INSTALLED_ ...

  8. Python - 常用内置变量

    直接上代码 #!/usr/bin/env python # -*- coding: utf-8 -*- """ 这是注释__doc__会打印这部分内容 "&qu ...

  9. URL及short URL短网址

    URL,uniform resource locator,经常被称为网址,尤其是在使用HTTP的时候.通常是一个指向某个资源的字符串.   URLs经常被用于网页(http),但也可以用于文件传输(f ...

  10. 服务发现组件之 — Eureka

    前言 现在流行的微服务体系结构正在改变我们构建应用程序的方式,从单一的单体服务转变为越来越小的可单独部署的服务(称为微服务),共同构成了我们的应用程序.当进行一个业务时不可避免就会存在多个服务之间调用 ...