beego 例子_beego框架代码分析

前言

也许beego框架在国内应该是众多PHPer转go的首选,因为beego的MVC、ORM、完善的中文文档让PHPer们得心应手,毫无疑问我也是。这种感觉就像当年入门PHP时使用ThinkPHP一样。

也许随着你的认知的提升,你会讨厌现在东西,比如某一天你可能慢慢的开始讨厌beego,你会发现go语言里包的真正意义,你开始反思MVC真的适合go吗,或者你开始觉着ORM在静态语言里的鸡肋,等等。我只想说:“也许你成长了~”。但是这些都不重要,每一个受欢迎的事物自然有我们值的学习的地方。今天这篇文章很简单,像一篇笔记,记录了我这几天抽空读beego源码的记录。

如何读一个框架?

毫无疑问读go的框架和PHP框架也是一样的:

配置加载:如何加载配置文件的。

路由:分析框架如何通过URI执行对应业务的。

ORM:ORM如何实现的。

这里(1.)和(3.)无非就是加载个文件和sql解析器的实现,我就忽略了,重点就看看路由的实现。

安装

简单带过:

// Step1: 安装beego

go get github.com/astaxie/beego

// Step2: 安装bee

go get github.com/beego/bee

// Step3: 用bee工具创建一个新的项目

bee new beego-code-read

代码分析

go有自己实现的http包,大多go框架也是基于这个http包,所以看beego之前我们先补充或者复习下这个知识点。如下:

go如何启动一个http server

package main

import (

// 导入net/http包

"net/http"

)

func main() {

// ------------------ 使用http包启动一个http服务 方式一 ------------------

// *http.Request http请求内容实例的指针

// http.ResponseWriter 写http响应内容的实例

http.HandleFunc("/v1/demo", func(w http.ResponseWriter, r *http.Request) {

// 写入响应内容

w.Write([]byte("Hello TIGERB !\n"))

})

// 启动一个http服务并监听8888端口 这里第二个参数可以指定handler

http.ListenAndServe(":8888", nil)

}

// 测试我们的服务

// --------------------

// 启动:bee run

// 访问: curl "http://127.0.0.1:8888/v1/demo"

// 响应结果:Hello TIGERB !

ListenAndServe是对http.Server的进一步封装,除了上面的方式,还可以使用http.Server直接启服务,这个需要设置Handler,这个Handler要实现Server.Handler这个接口。当请求来了会执行这个Handler的ServeHTTP方法,如下:

package main

// 导入net/http包

import (

"net/http"

)

// DemoHandle server handle示例

type DemoHandle struct {

}

// ServeHTTP 匹配到路由后执行的方法

func (DemoHandle) ServeHTTP(w http.ResponseWriter, r *http.Request) {

w.Write([]byte("Hello TIGERB !\n"))

}

func main() {

// ------------------ 使用http包的Server启动一个http服务 方式二 ------------------

// 初始化一个http.Server

server := &http.Server{}

// 初始化handler并赋值给server.Handler

server.Handler = DemoHandle{}

// 绑定地址

server.Addr = ":8888"

// 启动一个http服务

server.ListenAndServe()

}

// 测试我们的服务

// --------------------

// 启动:bee run

// 访问: curl "http://127.0.0.1:8888/v1/demo"

// 响应结果:Hello TIGERB !

beego路由分析

接下里我们开始看beego的代码。拿访问"http://127.0.0.1:8080/"来说,对于beego代码来说有三个关键点,分别如下:

启动:main.go -> beego.Run()

注册路由:routersrouter.go -> beego.Router("/", &controllers.MainController{})

控制器:controllersdefault.go -> Get()

下面来看3个关键点的详细分析:

beego.Run()主要的工作

// github.com/astaxie/beego/beego.go

func Run(params ...string) {

// 启动http服务之前的一些初始化 忽略 往下看

initBeforeHTTPRun()

// http服务的ip&port设置

if len(params) > 0 && params[0] != "" {

strs := strings.Split(params[0], ":")

if len(strs) > 0 && strs[0] != "" {

BConfig.Listen.HTTPAddr = strs[0]

}

if len(strs) > 1 && strs[1] != "" {

BConfig.Listen.HTTPPort, _ = strconv.Atoi(strs[1])

}

}

// 又一个run 往下看

BeeApp.Run()

}

// github.com/astaxie/beego/app.go

func (app *App) Run(mws ...MiddleWare) {

// ... 省略

// 看了下这里app.Server的类型就是*http.Server 也就是说用的原生http包 且是上面“go如何启动一个http server”中的第二种方式

app.Server.Handler = app.Handlers

// ... 省略

if BConfig.Listen.EnableHTTP {

go func() {

app.Server.Addr = addr

logs.Info("http server Running on http://%s", app.Server.Addr)

// 默认配置false不强制tcp4

if BConfig.Listen.ListenTCP4 {

//...

// 忽略 默认false

} else {

// 关键点 ListenAndServe: app.Server的类型就是*http.Server 所以这里就启动了http服务

if err := app.Server.ListenAndServe(); err != nil {

logs.Critical("ListenAndServe: ", err)

time.Sleep(100 * time.Microsecond)

endRunning

}

}

}()

}

// 阻塞到服务启动

}

// 看到这里http已经启动了 而且是注册Handler的方式

接着去找这个Handler的ServeHTTP方法,通过上面的这段代码app.Server.Handler = app.Handlers,我们找到了下面的定义,Handler即是ControllerRegister的值,所以每次亲求来了就会去执行ControllerRegister.ServeHTTP(rw http.ResponseWriter, r *http.Request)。

// src/github.com/astaxie/beego/app.go

func init() {

// 调用 创建beego框架实例的方法

BeeApp = NewApp()

}

// App结构体

type App struct {

// 关键的请求回调Handler

Handlers *ControllerRegister

// http包的服务

Server *http.Server

}

func NewApp() *App {

// 初始化http handler

cr := NewControllerRegister()

// 创建beego 实例

app := &App{Handlers: cr, Server: &http.Server{}}

return app

}

通过我们追beego.Run()的代码,目前我们得到的结论就是:

使用的http包启动的服务

没有使用http.HandleFun()的定义路由策略,而是注册Handler的方式

所以beego就是通过beego.Router()自己管理路由,如果http请求来了,回调ControllerRegister.ServeHTTP(rw http.ResponseWriter, r *http.Request)方法,在ControllerRegister.ServeHTTP(rw http.ResponseWriter, r *http.Request)方法中去匹配路由并执行对应的controller 也就是beegoControllerInterface类型的控制器的方法,比如RESTFUL或者自定义啊等。

beego.Router() 如何注册路由

首先路由文件是如何加载的,我们发现在main.go文件里导入了路由包:

package main

import (

// 导入routers包 只执行init方法

_ "beego-code-read/routers"

"github.com/astaxie/beego"

)

func main() {

beego.Run()

}

上面我们启动了http服务,接着关键就是beego.Router()如何注册路由了。追了下代码如下:

beego.Router()

-> BeeApp.Handlers.Add(rootpath, c, mappingMethods...)

-> ControllerRegister.addWithMethodParams(pattern, c, nil, mappingMethods...)

-> ControllerRegister.addToRouter(method, pattern string, r *ControllerInfo)

-> *Tree.AddRouter(pattern string, runObject interface{})

最后就是在*Tree.AddRouter()完成了路由注册,这里的代码逻辑暂时就先不看了,至此这个beego框架的流程就其本理顺了,最后我们在回头总结下整个流程如下图:

备注:go导入包相当于入栈过程,先import后执行init

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/552576.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

kali2020识别不到网卡_WIN10环境下台式机找不到RealTek HD管理器解决耳塞式耳机外放问题...

最近想在工作休息闲暇时开个音乐播放器或者小游戏放松一下,需要戴上耳塞式耳机,但是最近这个耳机在公司台式电脑突然识别不到了,如果是自己的笔记本电脑在控制面板 - 硬件和声音里是可以找到“RealTek高清晰音频管理器”选项的,然…

韵乐x5效果器ktv最佳参数_家庭ktv(卡拉ok)家庭影院ktv选购推荐攻略

因为陆陆续续的给小区的邻居有推荐安装家庭KTV设备,根据他们的使用反馈和选购前遇到的问题,我做了汇总并整理了这篇文章. (不写复杂的参数,不堆积商品推荐,只推荐几款不同价位,真正性能优质、价格美丽的家庭…

cat3 utp是不是网线_小科普 | 网线也有高低?聊聊网线的差别

好电脑、好主板、好网卡、好运营商、好套餐,是不是就意味着有了极好的网络体验呢?对,但也未必。因为还少算了最后一道关卡——网线。▌线材网线这个东西,看着还真都差不多,插上就能用这能有什么差别呢?首先…

redis续期_面试官:Redis分布式锁如何解决锁超时问题的?

一、前言关于redis分布式锁, 查了很多资料, 发现很多只是实现了最基础的功能, 但是, 并没有解决当锁已超时而业务逻辑还未执行完的问题, 这样会导致: A线程超时时间设为10s(为了解决死锁问题), 但代码执行时间可能需要30s, 然后redis服务端10s后将锁删除, 此时, B线程恰好申请锁…

markdown如何设置图片大小_不会吧,还不会用markdown排版吗

请使用 Chrome 浏览器。请阅读下方文本熟悉工具使用方法,本文可直接拷贝到微信中预览。1 Markdown Nice 简介支持自定义样式的 Markdown 编辑器支持微信公众号、知乎和稀土掘金欢迎扫码回复「排版」加入用户群2 主题https://preview.mdnice.com/themes/欢迎提交主题…

此次边路调整系统推荐射手走哪路_王者荣耀地图重大对称改动,终于能射手对射手,上单对上单了...

兄弟萌,一直困扰大家的地图问题终于要改了,王者峡谷将在今年的周年庆版本,迎来一次玩法体验的大升级!调整介绍我们将尝试改造边路的地形&资源,促进更合理的同职业分路对线。以往通过职业、英雄的调整确实很难实质改…

二阶振荡环节的谐振频率_困惑了很久的串联/并联谐振电路详解

在含有电阻、电感和电容的交流电路中,电路两端电压与其电流一般是不同相的,若调节电路参数或电源频率使电流与电源电压同相,电路呈电阻性,称这时电路的工作状态为谐振。谐振现象是正弦交流电路的一种特定现象,它在电子…

安装不成功_iOS12.4.1 安装失败?教你百分百不掉签

说重点:近日,苹果频繁封杀证书,导致企业证书很缺,补上又封,想越狱又不能安装,实在困扰了很久,今天就分享百分百安装成功的方法,安装后配合自动续签插件,简直完美。接下来…

vsftpd设置被动模式_(1)vsftpd主、被动模式iptables配置方法

大多数的TCP服务是使用单个端口的连接,一般是用户向服务器的一个某个端口发起连接,然后使用这个连接进行通讯。但FTP协议却是例外,它使用双向的多个连接,而且使用的端口很难预计。FTP连接包括:一个控制连接 (controlco…

指定的参数已超出有效值的范围_整流二极管的特性和重要参数

一、 二极管的半导体原理略二、 二极管的特性曲线研究电路也有两种方法,一个是从它的内部工作原理去分析,另一个是从它表现出的外部特征去分析,把电路看成一个黑匣子,不管它内部什么结构什么原理,只研究它表现出来的特…

mysql boolean 和bool_关于 MySQL 的 boolean 和 tinyint(1)

boolean类型MYSQL保存BOOLEAN值时用1代表TRUE,0代表FALSE,boolean在MySQL里的类型为tinyint(1),MySQL里有四个常量:true,false,TRUE,FALSE,它们分别代表1,0,1,0,mysql> select true,false,TRUE,FALSE;--------------------------| TRUE | …

mysql存储过程触发器_【MySQL笔记】触发器,存储过程和函数

2)case语句mysql > DELIMITER //mysql >CREATEPROCEDUREproc3 (inparameterint)->begin->declarevarint;->setvarparameter1;->casevar->when0then->insertintotvalues(17);->when1then->insertintotvalues(18);->else->insertintotvalues…

count返回0_MySQL实战 | 14 为什么count(*)越来越慢?

select count(*) 应该是一个比较常用的语句,用来统计记录行数。但是,慢慢地你会发现,这个语句越来越慢了,为什么呢?count(*) 的实现方式首先,我们来看下它的实现方式。MySQL 中,不同的存储引擎&…

mysql info commit_mysql show processlist 发现大量的commit

今天执行show processlist 发现大量的commit;查看锁信息,发现基本上都是-----------------------------------------------------------------------------------------------------------------------------------------------------------------------…

sql管理:索引超出范围必须为非负值并小于集合大小_java面试基础知识-数据库基础知识(数据库索引部分)...

1.1数据库架构:如何设计一个关系型数据库?存储模块(文件系统)用块或者页作为存储单位 程序实例:存储管理缓存机制 不宜过大,要有淘汰机制SQL解析日志管理权限划分容灾机制索引管理锁管理1.2 索引为什么要使用索引&…

今日头条 mysql_今日头条的核心架构解析

一、产品背景今日头条是为用户提供个性化资讯客户端。下面就和大家分享一下当前今日头条的数据(据内部与公开数据综合):5亿注册用户2014年5月1.5亿,2015年5月3亿,2016年5月份为5亿。几乎为成倍增长。日活4800万用户2014年为1000万日活&#x…

编译原理语法分析_斯坦福大学《编译原理》学习记录 - 第二章:语法分析器

05-01: Introduction to Parsing 语法分析parser的作用:05-02: Context Free Grammars 上下文无关文法CFG(上下文无关文法)回答了一个字符串是否属于某语言:CFG的组成:终止符非终止符开始符生成式生成式production &am…

mysql中 视图的优缺点_数据库视图优缺点分析

视图作用是什么所谓视图(View)其实是执行查询语句后得到的结果,但这个查询结果可以仿真成数据表来使用,所以有人也称它为“虚拟数据表”,视图在操作上和数据表没有什么区别,但两者的差异是其本质是不同的:数据表是实际…

mysql永远不用utf8_永远不要在 MySQL 中使用「utf8」

题图:by apple from Instagram本文出自极客邦「聊聊架构」公众号的编译。我自己当年也被这个问题坑过,当时并没有如此详细的分析文章。我觉得有责任再次分享一下,让更多人知道这个事情。程序员不帮助程序员,还能指望谁呢&#xff…

sqoop mysql parquet_Sqoop抽取Hive Parquet表数据到MySQL异常分析

温馨提示:要看高清无码套图,请使用手机打开并单击图片放大查看。Fayson的github:https://github.com/fayson/cdhproject1.问题描述在CDH集群中我们需要将Hive表的数据导入到RDBMS数据库中,使用Sqoop工具可以方便的将Hive表数据抽取…