Beego:简约 & 强大并存的 Go 应用框架

引言:

Beego 是一个快速开发 Go 应用的 HTTP 框架,他可以用来快速开发 API、Web 及后端服务等各种应用,是一个 RESTful 的框架,主要设计灵感来源于 tornado、sinatra 和 flask 这三个框架,但是结合了 Go 本身的一些特性(interface、struct 嵌入等)而设计的一个框架。

目录:

1. Beego框架架构介绍

2. Beego框架项目结构

3. Beego框架优势

1.  Beego框架架构介绍

介绍beego框架之前先来了解下Go语言吧。

Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。

Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。

Go 语言被设计成一门应用于搭载 Web 服务器,存储集群或类似用途的巨型中央服务器的系统编程语言。

对于高性能分布式系统领域而言,Go 语言无疑比大多数其它语言有着更高的开发效率。它提供了海量并行的支持,这对于游戏服务端的开发而言是再好不过了。

Golang安装和使用请参考https://golang.google.cn/doc/

什么是Beego?

Beego 是一个快速开发 Go 应用的 HTTP 框架,他可以用来快速开发 API、Web 及后端服务等各种应用,是一个 RESTful 的框架,主要设计灵感来源于 tornado、sinatra 和 flask 这三个框架,但是结合了 Go 本身的一些特性(interface、struct 嵌入等)而设计的一个框架。

Beego是基于八大独立的模块之上构建的,是一个高度解耦的框架。当初设计Beego的时候就是考虑功能模块化,用户即使不使用Beego的http逻辑,也是可以使用其他独立模块,例如你可以使用cache模块来做你的缓存逻辑,使用logs模块来记录你的操作信息,使用config模块来解析你各种格式的文件,使用orm操作数据库等。各个模块就类似积木,堆积起来就是功能强大的Beego框架。

运行逻辑可以拆分以下几段:

1. main文件监听启动端口接收请求。

2. 请求经过路由和参数过滤功能转发给绑定url的controller处理。

3. Controller可调用辅助工具包、model、session管理、日志处理、缓存处理模块进行相应的业务处理。其中model(orm)直接操作数据库。

4. 业务处理完成,返回响应或视图给请求方。

2. Beego框架项目结构最小的Beego项目

package main
  
import (
    "github.com/astaxie/beego"  //导入beego依赖
)
  
type MainController struct {
    beego.Controller    //匿名包含beego.Controller
}
  
func (this *MainController) Get() {
    this.Ctx.WriteString("hello world")  //实现get响应
}
  
func main() {
    beego.Router("/", &MainController{})  //设置路由
    beego.Run()   //启动Beego       
}

把上面的代码保存为main.go,然后通过命令行进行编译并执行:

$ go build main.go
$ ./hello

启动之后打开http://127.0.0.1:8080浏览器显示“hello world”

代码详解:

1、首先引入了包github.com/astaxie/beego, beego包中会初始化一个BeeAPP的应用,初始化一些参数。

2、定义Controller,这里定义了一个struct为MainController,充分利用了Go语言的组合的概念,匿名包含了beego.Controller,这样MainController就拥有了beego.Controller的所有方法。

3、定义RESTFul方法,通过匿名组合之后,MainController已经拥有了Get、Post、Delete、Put等方法,这些方法是分别用来对应用户请求的Method函数,如果用户发起的是POST请求,那么就执行Post函数。所以这里我们定义了MainController的Get方法用来重写继承的Get函数,这样当用户GET请求的时候就会执行该函数。

4、定义main函数,所有的Go应用程序和C语言一样都是Main函数作为入口,所以这里定义应用的入口。

5、Router注册路由,路由就是告诉beego,当用户来请求的时候,该如何去调用相应的Controller,这里注册了请求/的时候,请求到MainController。需注意,Router函数的两个参数函数,第一个是路径,第二个是Controller的指针。

6、Run应用,内部监听了8080端口:Go默认情况会监听你本机所有的IP上面的8080端口。

安装beego

go get github.com/astaxie/beego

bee 工具是一个为了协助快速开发 beego 项目而创建的项目,通过 bee 您可以很容易的进行 beego 项目的创建、热编译、开发、测试、和部署。

go get github.com/beego/bee

当我们安装好bee之后,bee命令默认是放在GOPATH/bin里面,所以需要把GOPATH/bin里面,所以需要把GOPATH/bin 添加到您的环境变量中。

bee常用的命令:

bee new <项目名> :创建一个项目,这样的项目一般是web项目

需要注意的是这个命令须在 $GOPATH/src 下执行。

Beego目录结构

├── conf           //配置文件
│   └── app.conf
├── controllers    //控制器
│   ├── admin
│   └── default.go
├── main.go        //项目入口
├── models         //模型   
│   └── models.go
├── routers       //路由
│   └──router.go
├── static         //静态文件
│   ├── css
│   ├── ico
│   ├── img
│   └── js
└── views          //界面模板
    ├── admin
    └── index.tpl

Beego框架是一个典型的mvc框架。M(models 目录)、V(views 目录)和 C(controllers 目录)的结构。

路由设置

路由的主要功能是实现从请求地址到实现的方法,beego中封装了Controller,所以路由是从路径到ControllerInterface的过程,ControllerInterface的方法有如下:

type ControllerInterface interface {
Init(ct *Context, cn string)
Prepare()
Get()
Post()
Delete()
Put()
Head()
Patch()
Options()
Finish()
Render() error
}

这些方法beego.Controller都已经实现了,所以只要用户定义struct的时候匿名包含就可以了。当然更灵活的方法就是用户可以去自定义类似的方法,然后实现自己的逻辑。

用户可以通过如下的方式进行路由设置:

beego.Router("/user", &controllers.UserController{})
beego.Router("/bill", &controllers.BillController{})
beego.Router("/log", &controllers.LogController{})

为了用户更加方便的路由设置,beego参考了sinatra的路由实现,支持多种方式的路由:

beego.Router("/api/:id([0-9]+)", &controllers.RController{})
自定义正则匹配 //匹配 /api/123 :id= 123
beego.Router("/news/:all", &controllers.RController{})
全匹配方式 //匹配 /news/path/to/123.html :all= path/to/123.html
beego.Router("/user/:username([\w]+)", &controllers.RController{})
正则字符串匹配 //匹配 /user/astaxie :username = astaxie
beego.Router("/download/*.*", &controllers.RController{})
*匹配方式 //匹配 /download/file/api.xml :path= file/api :ext=xml
beego.Router("/download/ceshi/*", &controllers.RController{})
*全匹配方式 //匹配 /download/ceshi/file/api.json :splat=file/api.json
beego.Router("/int", &controllers.RController{})
int类型设置方式 //匹配 :id为int类型,框架帮你实现了正则([0-9]+)
beego.Router("/:hi:string", &controllers.RController{})
string类型设置方式 //匹配 :hi为string类型。框架帮你实现了正则([\w]+)

Controller设置

beego.Controller实现了接口beego.ControllerInterface,beego.ControllerInterface定义了如下函数:

type ControllerInterface interface {
    Init(ct *Context, cn string)
    Prepare()
    Get()
    Post()
    Delete()
    Put()
    Head()
    Patch()
    Options()
    Finish()
    Render() error
}

Init(ct *Context, cn string)

这个函数主要初始化了Context、相应的Controller名称,模板名,初始化模板参数的容器Data

Prepare()

这个函数主要是为了用户扩展用的,这个函数会在下面定义的这些Method方法之前执行,用户可以重写这个函数实现类似用户验证之类。

Get()

如果用户请求的HTTP Method是GET, 那么就执行该函数,默认是403,用户继承的子struct中可以实现了该方法以处理Get请求.

Post()

如果用户请求的HTTP Method是POST, 那么就执行该函数,默认是403,用户继承的子struct中可以实现了该方法以处理Post请求.

Delete()

如果用户请求的HTTP Method是DELETE, 那么就执行该函数,默认是403,用户继承的子struct中可以实现了该方法以处理Delete请求.

Put()

如果用户请求的HTTP Method是PUT, 那么就执行该函数,默认是403,用户继承的子struct中可以实现了该方法以处理Put请求.

Head()

如果用户请求的HTTP Method是HEAD, 那么就执行该函数,默认是403,用户继承的子struct中可以实现了该方法以处理Head请求.

Patch()

如果用户请求的HTTP Method是PATCH, 那么就执行该函数,默认是403,用户继承的子struct中可以实现了该方法以处理Patch请求.

Options()

如果用户请求的HTTP Method是OPTIONS, 那么就执行该函数,默认是403,用户继承的子struct中可以实现了该方法以处理Options请求.

Finish()

这个函数实在执行完相应的http Method方法之后执行的,默认是空,用户可以在子Strcut中重写这个函数,执行例如数据库关闭,清理数据之类的工作。

Render() error

这个函数主要用来实现渲染模板,如果beego.AutoRender为true的情况下才会执行。

Session模块

Beego内置了session模块,目前session模块支持的后端引擎包括memory、file、mysql、redis四中,用户也可以根据相应的interface实现自己的引擎。

Beego中使用session相当方便,只要在main入口函数中设置如下:

beego.SessionOn = true

或者通过配置文件配置如下:

sessionon = true

session有几个方便的方法:

SetSession(name string, value interface{})
GetSession(name string) interface{}
DelSession(name string)

例子:

func (this *MainController) Get() {
    v := this.GetSession("asta")
    if v == nil {
        this.SetSession("asta", int(1))
        this.Data["num"] = 0
    } else {
        this.SetSession("asta", v.(int)+1)
        this.Data["num"] = v.(int)
    }
    this.TplNames = "index.tpl"
}

session操作主要有设置session、获取session、删除session。当然你要可以通过下面的方式自己控制相应的逻辑这些逻辑:

sess:=this.StartSession()
defer sess.SessionRelease()

sess对象具有如下方法:

sess.Set()
sess.Get()
sess.Delete()
sess.SessionID()

但是我还是建议大家采用SetSession、GetSession、DelSession三个方法来操作,避免自己在操作的过程中资源没释放的问题。关于Session模块使用中的一些参数设置:

SessionOn

设置是否开启Session,默认是false,配置文件对应的参数名:sessionon

SessionProvider

设置Session的引擎,默认是memory,目前支持还有file、mysql、redis等,配置文件对应的参数名:sessionprovider

SessionName

设置cookies的名字,Session默认是保存在用户的浏览器cookies里面的,默认名是beegosessionID,配置文件对应的参数名是:sessionname

SessionGCMaxLifetime

设置Session过期的时间,默认值是3600秒,配置文件对应的参数:sessiongcmaxlifetime

SessionSavePath

设置对应file、mysql、redis引擎的保存路径或者链接地址,默认值是空,配置文件对应的参数:sessionsavepath

当SessionProvider为file时,SessionSavePath是只保存文件的目录,如下所示:

beego.SessionProvider = "file"
beego.SessionSavePath = "./tmp"

当SessionProvider为mysql时,SessionSavePath是链接地址,采用go-sql-driver,如下所示:

beego.SessionProvider = "mysql"
beego.SessionSavePath = "username:password@protocol(address)/dbname?param=value"

当SessionProvider为redis时,SessionSavePath是redis的链接地址,采用了redigo,如下所示:

beego.SessionProvider = "redis"
beego.SessionSavePath = "127.0.0.1:6379"

Cache模块

Beego内置了一个cache模块,实现了类似memcache的功能,缓存数据在内存中。

通过beego.NewBeeCache初始化一个对象,然后设置过期时间,开启过期检测,在业务逻辑中就可以通过如下的接口进行增删改的操作:

Get(name string) interface{}
Put(name string, value interface{}, expired int) error
Delete(name string) (ok bool, err error)
IsExist(name string) bool

例子:

var (
    urllist *beego.BeeCache
)
  
func init() {
    urllist = beego.NewBeeCache()
    urllist.Every = 0 //不过期
    urllist.Start()
}
  
func (this *ShortController) Post() {
    var result ShortResult
    longurl := this.Input().Get("longurl")
    beego.Info(longurl)
    result.UrlLong = longurl
    urlmd5 := models.GetMD5(longurl)
    beego.Info(urlmd5)
    if urllist.IsExist(urlmd5) {
        result.UrlShort = urllist.Get(urlmd5).(string)
    } else {
        result.UrlShort = models.Generate()
        err := urllist.Put(urlmd5, result.UrlShort, 0)
        if err != nil {
            beego.Info(err)
        }
        err = urllist.Put(result.UrlShort, longurl, 0)
        if err != nil {
            beego.Info(err)
        }
    }
    this.Data["json"] = result
    this.ServeJson()
}

日志模块

Beego默认有一个初始化的BeeLogger对象输出内容到stdout中,你可以通过如下的方式设置自己的输出:

beego.SetLogger(*log.Logger)

可以通过下面的方式设置不同的日志分级:

beego.SetLevel(beego.LevelError)

日志等级的排序如下:LevelTrace、LevelDebug、LevelInfo、LevelWarning、 LevelError、LevelCritical
不同级别的log日志函数:

Trace(v …interface{})

Debug(v …interface{})

Info(v …interface{})

Warn(v …interface{})

Error(v …interface{})

Critical(v …interface{})

例子:

fd,err := os.OpenFile("/var/log/beeapp/beeapp.log", os.O_RDWR|os.O_APPEND, 0644)
if err != nil {
    beego.Critical("openfile beeapp.log:", err)
    return
}
lg := log.New(fd, "", log.Ldate|log.Ltime)
beego.SetLogger(lg)

配置

beego支持解析ini文件, beego默认会解析当前应用下的conf/app.conf文件

通过这个文件你可以初始化很多beego的默认参数:

appname = beepkg
httpaddr = "127.0.0.1"
httpport = 9090
runmode ="dev"
autorender = false
autorecover = false
viewspath = "myview"

你可以在配置文件中配置应用需要用的一些配置信息,例如下面所示的数据库信息:

mysqluser = "root"
mysqlpass = "rootpass"
mysqlurls = "127.0.0.1"
mysqldb = "beego"

那么你就可以通过如下的方式获取设置的配置信息:

beego.AppConfig.String("mysqluser")
beego.AppConfig.String("mysqlpass")
beego.AppConfig.String("mysqlurls")
beego.AppConfig.String("mysqldb")

AppConfig支持如下方法:

Bool(key string) (bool, error)
Int(key string) (int, error)
Int64(key string) (int64, error)
Float(key string) (float64, error)
String(key string) string

ORM模块

目前beego-orm支持的数据有:

-MySQL:https://github.com/go-sql-driver/mysql

-PostgreSQL:https://github.com/lib/pq

-Sqlite3:https://github.com/mattn/go-sqlite

beego-orm的相关特性:

– 支持 Go 的所有类型存储

– 轻松上手,采用简单的 CRUD 风格

– 自动 Join 关联表

– 跨数据库兼容查询

– 允许直接使用 SQL 查询/映射

– 严格完整的测试保证 ORM 的稳定与健壮

示例请参考beego官方:https://beego.me/docs/mvc/model/orm.md

3.Beego框架优势

优点:

1)使用简单:通过命令行创建beego项目;监控代码修改进行热编译;自动化测试代码以及自动化打包部署。

2)模块化:配置解析,缓存操作,日志记录,性能监测,ORM模块,请求模拟,上下文操作,session。

3)智能化:智能监控,智能router。可监控cpu、memory、goroutine,QPS

缺点:依赖库多,不利于掌握

使用场景

1. 适合用作服务器端开发,快速开发web服务,支持restful api。

2. 开发的后端服务可作为微服务的一部分,提供高并发的性能。

3. 可作为云平台的开发框架,目前国内很多云平台采用beego开发。

4. 开发的服务也可以用来进行分布式部署。

5. 可以开发高性能网关,提供高效路由功能。

6. 开发的服务支持生成docker镜像,使用docker容器部署。

【小结】通过上述介绍,可以看出Beego框架使用简单,快速开发非常方便,提供多个模块工具,智能监控,智能路由。依托于golang语言有着高效的性能,Beego可用于微服务、分布式、网关接入等场景开发,完全可以替代springboot进行项目快速开发。

【备注】本文参考自beego官网,地址:https://beego.me/docs/intro/

精选提问:

问1:能列出下常用的框架和库吗?

答:go web框架:Beego Buffalo  Echo Gin Iris Revel;golang:常用库请参考golang中文网:https://studygolang.com/articles/14828?fr=sidebar

问2:请问beego后续有计划增加哪些新的特性么?

答:目前来看,beego没有新的特性推出,旨在bug维护和框架稳定性。

问3:这种框架和gin区别是什么?优势是什么?beego本身集成了很多,有种大而全,却不精,每个功能点cover住的场景有限,还不如借助第三方来的高效,简单。

答:(1)Beego支持完整的mvc,Gin不支持完整的mvc。

(2) 路由:Beego支持完整正则路由,Gin不支持。

(3) Beego在业务方面较Gin支持更多(Beego有多模块封装,且支持单独模块独立使用,构建项目更加方便)

(4) Gin在性能方面较Beego更好(遇到性能瓶颈适合使用Gin)

诚然Beego在性能方面确实不能和Gin比,但是在复杂业务转化为项目时更加方便,而Gin实现业务逻辑需要更多的代码和库引用。根据具体业务和性能选择适合自己的框架或库。

问4:能比较一下beego 和 go-restful 吗?

答:go-resful功能单一旨在提供高效的路由分发和restful访问,而此功能只是beego一个模块的功能,如果只是想单纯的路由转发和高的访问性能,建议使用go-restful,如果项目有复杂的业务且符合mvc模型,建议使用beego。

关于作者:十月,现任普元西安研发中心资深开发工程师,擅长Java、golang、大数据、云计算等领域技术;对公有云、混合云、微服务架构有着浓厚的兴趣。

关于EAWorld:微服务,DevOps,数据治理,移动架构原创技术分享

转载本文需注明出处:微信公众号EAWorld,违者必究。

Image placeholder
未设置
  19人点赞

没有讨论,发表一下自己的看法吧

推荐文章
如何统一服务调用框架?

转载本文需注明出处:微信公众号EAWorld,违者必究。引言:目前在Java微服务领域SpringCloud和Dubbo体系都被广泛使用。不同的用户会根据项目的需要选择合适的架构。但是在有些跨系统的场

002.07 MineSweeper - PsSimleGUI 的应用

建檔日期:2019/12/07 更新日期:None 语言:Python3.7.2,PySimpleGUI4.6.0 系统:Win10Ver.10.0.17763主题:002.07MineSweeper

GoWeb教程_05.5. 使用 Beego orm 库进行 ORM 开发

beegoorm是我开发的一个Go进行ORM操作的库,它采用了Gostyle方式对数据库进行操作,实现了struct到数据表记录的映射。beegoorm是一个十分轻量级的GoORM框架,开发这个库的本

Redis功能强大,那也顶不住被滥用啊!

Redis功能强大,数据类型丰富,再快的系统,也经不住疯狂的滥用。通过禁用部分高风险功能,并挂上开发的枷锁,业务更能够以简洁、通用的思想去考虑问题,而不是绑定在某种实现上。Redis根据不同的用途,会

R语言有多强大?十个你不知道的功能

大数据文摘出品编译:邬亮有些业界从业人士对R语言的价值并不认可,他们认为R语言只针对统计分析。R语言的确提供了很全面的统计分析的软件包,比如CRAN,Bioconductor,Neuroconduct

原生线程池这么强大,Tomcat 为何还需扩展线程池?

前言Tomcat/Jetty是目前比较流行的Web容器,两者接受请求之后都会转交给线程池处理,这样可以有效提高处理的能力与并发度。JDK提高完整线程池实现,但是Tomcat/Jetty都没有直接使用。

beego 使用 coding 的 webhook 2.0 进行自动部署

beego使用coding的webhook2.0进行自动部署本文介绍beego在coding上如果使用webhook2.0进行自动部署。coding的webhook1.0教程coding平台端的设置这

请你们不要调侃中台,它是我们赖以生存的镰刀

看本圣经,你就把自己当耶稣了?在这个世界上有两种人,一种人性情诙谐,喜欢开玩笑,另一种人万事较真,做事喜欢一板一眼。在爱开玩笑的人看来,只要不直接嘲笑对方,或不带来伤害,抓住一个热点调侃一番,甚至来点

002.06 Klondike Solitaire - PsSimleGUI 的应用

建檔日期:2019/12/04 更新日期:None 语言:Python3.7.2,PySimpleGUI4.6.0 系统:Win10Ver.10.0.17763主题:002.06KlondikeSol

AI 数据中台 Mega 及其应用

随着AI在各行业落地的进一步深化和应用数据量的飞速增长,越来越多的AI科学家痛苦地发现数据ETL、数据仓库和海量特征向量检索等数据处理流程花费了他们大量宝贵的时间和精力。AI数据中台Mega打破了人工

使用 Go Wails 框架来构建桌面应用(Go+Vue.js)

众所周知,Go主要用于构建API、web后端和CLI工具。但有趣的是,Go可以用在我们没有预料到的地方。 例如,我们可以使用Wails框架用Go和Vue.js构建一个桌面应用程序。 这是一个新框架,

一键“脱”衣应用DeepNude迅速下线,来看看它涉及的图像修复技术

大数据文摘出品来源:Github发布者:yuanxiaosc上周,又一AI偏门应用DeepNude爆出,一键直接“脱掉”女性的衣服,火爆全球。应用也很容易上手,只需要给它一张照片,即可借助神经网络技术

DeepFakes进化版DeepNude惊现!一键“脱衣“,火到宕机

大数据文摘出品作者:蒋宝尚、赵伟人工智能的黑暗面能有多黑?这边DeepFake带来的余震还没有被平息,本周,又一AI偏门应用爆出,一键直接“脱掉”女性的衣服!海外媒体Motherboard测试图片显然

IEEE态度转变:解除对华为评审限制

大数据文摘出品作者:周素云、魏子敏IEEE的态度发生变化。今晨,IEEE电气电子工程师学会中国官网及官方公众号同时发出声明,表示IEEE向美国商务部要求就出口管制条例在IEEE出版活动的适用性做出说明

PHP跌出前十,铁打的 Python 连续3年第一:IEEE Spectrum 2019编程语言排行榜出炉

Python势头不减,依旧第一,而且进一步拉开了与其他语言的差距。这一结果,来自IEEESpectrum2019年度编程语言排行榜。这已经是Python连续3年保持第一。在Python之下,第二交椅的

IEEE官方禁止华为参与期刊审稿,当全球最大技术学术机构向政治弯腰

大数据文摘出品作者:魏子敏、宋欣仪5月29日,作为全球最大专业技术组织之一的IEEE(电气和电子工程师协会)被曝出,在发给会员的内部邮件中禁止华为员工作为旗下期刊杂志的编辑和审稿人。今天早晨,IEEE

SpringBoot个人应用开发框架(SpringBoot版本2.1)+IDEA

前言: 此笔记为本人首个SpringBoot项目框架学习实践记录,期间参考了许多大神的笔记和心得。 参考文档如下: 项目git地址: 一、创建SpringBoot工程 1.1创建父POM工程结

2021适合移动和桌面应用的JavaScript框架是什么

课程推荐:Java开发工程师--学习猿地--送7个上线商业项目 当听到JavaScript这个词的时候,“web开发”会一下子出现在我们的脑海中,因为JavaScript在很长一段时间里一直是web应

Laravel shop 5.8 关于面包屑 category 为空,前端页面报错问题。

进入本章的:3.体验优化现在商品列表页还比较简陋,接下来我们就要针对类目做一些前端方面的体验优化。类目面包屑前面测试还正常,地址栏输入 还能正常获取到商品信息,自从前端的商品index模板中加入了

js框架与css框架的区别?

js框架与css框架的区别?一、JavaScript框架●Javascript框架是指以Javascript语言为基础搭建的编程框架。●Javascript框架就是将常用的方法进行封装,方便调取使用。

Mac 跑代码报 Illegal key size 错误的解决方法

异常原因:如果密钥大于128,会抛出java.security.InvalidKeyException:Illegalkeysize异常.因为密钥长度是受限制的,java运行时环境读到的是受限的pol

一直使用AtomicInteger?试一试FiledUpdater

1.背景在进入正题之前,这里先提出一个问题,如何在多线程中去对一个数字进行+1操作?这个问题非常简单,哪怕是Java的初学者都能回答上来,使用AtomicXXX,比如有一个int类型的自加,那么你可以

正则表达式 Regular Expression

历史正则表达式出现于理论计算机科学的自动控制理论和形式化语言理论中。在这些领域中有对计算(自动控制)的模型和对形式化语言描述与分类的研究。1它可以转化成形式化语言或者确定型自动机。它们是语义上等价的,

Go语言高级编程_4.7 pbgo: 基于Protobuf的框架

4.7pbgo:基于Protobuf的框架 pbgo是我们专门针对本节内容设计的较为完整的迷你框架,它基于Protobuf的扩展语法,通过插件自动生成rpc和rest相关代码。在本章第二节我们已经展示

GoWeb教程_12.1. 应用日志

我们期望开发的Web应用程序能够把整个程序运行过程中出现的各种事件一一记录下来,Go语言中提供了一个简易的log包,我们使用该包可以方便的实现日志记录的功能,这些日志都是基于fmt包的打印再结合pan