学习了Go语言密码学算法(14天搞定Go语言,从0到1保姆级教程-Go语言密码学算法)。为了让大家能够更牢固的掌握之前学习的知识,提高实际应用编程能力, 本书希望通过实际的应用场景和项目实战,使读者能够将功能开发和业务场景进行结合,同时具备独立开发业务模块的能力。本篇主要从Beego框架介绍及项目初始化配置、Elm后台管理平台项目介绍、数据库配置及ORM映射。

Beego框架介绍及项目初始化配置、Elm后台管理平台项目介绍、数据库配置及ORM映射

ØBeego简介

Beego是一个使用Go语言来开发Web应用的GoWeb框架,该框架起始于2012年。Beego可以用来快速开发API、Web、后端服务等各种应用,主要设计灵感来源于Tornado、Sinatra、Flask这三个框架,但是结合了Go本身的一些特性(interface、struct继承等)。该框架采用模块封装,使用简单,容易学习。方便技术开发者快速学习并进行实际开发。对程序员来说,Beego掌握起来非常简单,只需要关注业务逻辑实现即可,框架自动为项目需求提供不同的模块功能。

Ø Beego框架的主要特性

简单化: Beego使用MVC模型,支持RESTful;可以使用bee工具来提高开发效率,如监控代码修改进行热编译,自动化测试代码,自动化打包部署等。

智能化:Beego框架封装了路由模块,支持智能路由,智能监控,并可以监控内存消耗,CPU使用以及Goroutine的运行状况,方便开发者对线上应用进行监控分析。

模块化:Beego根据功能对代码进行节耦封装,形成了Session、Cache、Log、配置解析、性能监控、上下文操作、ORM等独立的模块,方便开发者使用。

高性能:Beego采用Go原生的HTTP请求、Goroutine的并发效率应付大流量Web应用和API应用。

其中,MVC的全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,是一种软件设计典范。它是用业务逻辑、数据与界面显示分离的方法来组织代码,将众多的业务逻辑聚集到一个部件里面,在需要改进和个性化定制界面及用户交互的同时,不必重新编写业务逻辑,达到减少编码的时间。

REST全称为 Resource Representational State Transfer。意思是:资源在网络中以某种表现形式进行状态转移。RESTfal是通用的、被程序开发人员所遵循的一种设计风格。如表所示。


操作方法Api备注及说明
GET/admin/info获取管理员信心
GET/admin/singout管理员退出系统
POST/shopping/addShop添加商品
DELETE/shopping/restaurant/:id删除商铺


如上表格中的形式,操作方法有GET,POST,DELETE类型,对应的HTTP请求类型,除此之外,还有OPTIONS,HEAD等操作。API列所对应的是请求资源所在的路径,根据路径命名就能见名知义地了解该接口API所对应的功能。人们通常把这种前后端进行数据交互的形式称之为RESTful风格。

Ø Beego安装

(1)在安装Beego之前,需要先安装Git,之前在学习数据库的时候已经安装过了,这里不再赘述。

(2)打开DOS命令行窗口,执行go get http://github.com/astaxie/beego下载 Beego 源码。

(3)执行go get http://github.com/beego/bee 安装bee工具。

下载后可以在GoLand上看到项目目录,如图所示。

Ø bee工具的使用

bee工具命令与功能如表所示。

命令用途
bee new ProjectName新建一个全新的web项目
bee api ProjectNames创建开发API应用
bee run运行项目
bee pack打包操作
bee version查看当前bee,Beego,go的版本


使用new命令有一点需要注意,该命令必须在src目录下执行才能生效,自动生成Web项目的目录结构。如果在其他目录下面执行bee new命令,也同样会是在src目录下面生成对应新项目的目录结构,这是bee工具在构建项目的时候默认寻找创建的目录。

Ø 创建项目

执行bee new BeegoDemo。命令执行效果如图所示。

终端中输出了bee的图标和版本,并且打印出了很多日志,创建很多文件和目录。这就是bee new命令的执行效果,表示新建一个项目。

现在使用开发工具GoLand来打开新建的BeegoDemo项目,并查看一下项目目录组织结构。如图所示。

接下来使用bee命令运行案例,看一下效果。在开发工具下方的terminal中,打开terminal,输入命令:bee run。

HTTP服务已经在http://localhost:8080端口运行,接下来打开浏览器中验证一下,效果如图所示。

Ø 结构分析

1. 简单案例分析

上小节中展示的页面是默认初始化好的页面。下面分析程序如何设置这个页面。Go语言程序执行时候是执行main包下面的init函数,main函数依次执行,因此需要先找到main.go文件。

首先,看到import()导入了两个包,一个是routers,一个是Beego。而routers包前面有一个“_”,这表明是引入routers包,并执行ini()t方法。

这里涉及一个知识点,就是Go语言的执行过程,程序执行流程如图所示。

所以,程序首先到routers包下执行init()方法。router.go里面的代码参见。

router.go文件中有一个init()方法,可以看到beego.Router()这句代码。router表示的是路由,这个函数的功能是映射URL到 controller,第一个参数是URL (用户请求的地址),这里注册的是/,也就是访问的不带任何参数的URL,第二个参数是对应的 controller,也就是即将把请求分发到那个控制器来执行相应的逻辑,MainController结构体及函数声明在default.go文件中,这里有一个Get()方法,方法中有三行代码,参见。

之前在浏览器中访问的是:http://localhost:8080,这是一个GET请求,请求到了后台以后,如果没有任何请求参数,就会被“/”拦截,执行MainController中的代码,因为是GET请求,所以这里自动找到Get()函数并进行执行。

在Get()函数里面,可以看到三句代码,前两句c.Data[]= ""表示设置返回的数据字段及内容,最后一句c.TplName表示设置处理该请求指向某个模板文件,这里指向了index.tpl,index.tpl文件在存放在views下面,views下面存放一些模板文件(html+css+js等)。

init()方法分析完毕后,程序会继续往下执行,就到了main()函数,在main()函数中执行beego.Run()代码。下面大致分析一下代码的逻辑。

在Run()方法内部,主要做了如下事情。

(1)解析配置文件,也就是app.conf文件,包括端口、应用名称等信息。

(2)检查是否开启session,如果开启session,就会初始化一个session对象。

(3)是否编译模板,Beego框架会在项目启动的时候根据配置把views目录下的所有模板进行预编译,然后存放在map中,这样可以有效的提高模板运行的效率,不需要进行多次编译。

(4)监听服务端口。根据app.conf文件中的端口配置,启动监听。

2. 组织结构详解

经过对Beego的案例简单分析,总结Beego项目的组织结构如下所示

conf:项目配置文件所在的目录,项目中有一些全局的配置都可以放在此目录下。

app.conf文件中默认指定了三个配置:

(1)appname = BeegoDemo 指定项目名称。

(2)httpport = 8080 指定项目服务监听端口。

(3)runmode = dev 指定执行模式。

controllers:该目录是存放控制器文件的目录,所谓控制器就是控制应用调用哪些业务逻辑,由controllers处理HTTP请求,并负责返回给前端调用者。

models:models层可以解释为实体层或者数据层,在models层中实现和用户和业务数据的处理,数据库表相关的一些主要操作会在这一目录中实现,执行后的结果数据返回给controller层。如向数据库中插入新数据、删除数据库表数据、修改某一条数据、从数据库中查询业务数据等都是在models层实现。

routers:该层是路由层。所谓路由就是分发的意思,当前端浏览器进行一个HTTP请求到后台Web项目时,程序必须要能够根据浏览器的请求URL进行不同的业务处理,从接收到前端请求到判断执行具体的业务逻辑的过程的工作,就由routers来实现。

static:在static目录下,存放的是Web项目的静态资源文件,主要有css、img、js、html这几类文件。html中存放应用的静态页面文件。

views:views中存放的就是应用中存放html模版页面的目录。所谓模版,就是页面框架和布局是已经使用html写好了,只需要在进行访问和展示时,将获取到的数据动态填充到页面中,能够提高渲染效率。因此,使用模版是非常常见的一种方式。

整个框架的执行逻辑如图所示。

Ø 路由设置

Beego框架支持4种路由设置,它们分别是:基础路由,固定路由,正则路由和自动路由。具体说明如下。

1. 基础路由

直接通过beego.Get()、beego.POST()、beego.Head()、beego.Delete()等方法来进行路由的映射,通过代码来进行演示。常见的HTTP请求方法操作有,GET、HEAD、PUT、POST、DELETE、OPTIONS等。

首先是基础的GET路由。方法如下所示。

基础的POSt路由。方法如下所示。

除此之外,还支持Patch、Head、Delete等基础路由。

以上这种请求和对应找到请求方法类型的方式就是RESTful形式, RESTful是目前开发API中非常常用的一种形式,其实就是根据协议判断请求方式,而不是根据url字段。如果用户发送Get请求就执行Get()方法,如果发送Post请求就执行Post()方法。

2. 固定路由

方法如下所示。

Get请求就会对应到Get()方法,Post就会对应到Post()方法,Delete就会对应到Delete()方法,Header方法就会对应Header()方法。

3. 正则路由

正则路由是指可以在进行固定路由的基础上,支持匹配一定格式的正则表达式。比如:id,:username,自定义正则,file的路径和后缀切换以及全匹配等操作。

上面两种路由都是默认的根据请求的类型,Get就执行Get()方法,Post执行Post()方法,有局限性。因为在开发的时候常需要使用固定匹配,直接执行对应的逻辑控制方法,因此Beego提供了可以自定义的自定义路由配置。方式如下所示。

在beego.Controller中,定义了很多的方法用来解决常用的HTTP Method,比如Init()、Prepare()、Post()、Get()、Head()、Delete()等方法。

Elm后台管理平台项目介绍

Ø 项目介绍

如今很多人已经养成了使用软件点外卖的习惯。这些外卖公司在移动端接受客户的网上点餐,而商家端可以接受商家的入驻和食品的添加。一家外卖公司需要有自己的后台管理系统来对系统内已经入驻的商家、用户及推广活动等进行管理和统计。本章以外卖餐饮公司为实际使用场景,来实现餐饮公司的后台管理系统。通过该后台管理系统,能够统计到用户的信息和增长情况,还可以对商家进行添加,修改等管理操作,商家端可以对食品进行相关的业务操作。

Ø 项目效果演示

管理平台的登录页面如图所示。

管理平台的数据统计页面如图所示。

管理平台的数据管理页面如图所示。

Ø 整体架构简介

整体的项目架构如下。

(1)后台:Beego框架。

(2)前端:vue框架。

(3)数据库:mysql数据库+redis数据库。


数据库配置及ORM映射

Ø ORM简介

ORM(Object Relationship Mapping), 通常翻译为对象关系映射,ORM模式是一种解决面向对象与关系数据库存在的互不匹配的现象的技术。ORM中间件能在任何一个应用的业务逻辑层和数据库层之间充当桥梁。一般情况下,一个持久化结构体和一个表对应,结构体的每个实例对应表中的一条记录,结构体的每个属性对应表的每个字段。在Beego框架中,ORM被单独封装称一个模块,也被命名为orm。此项目中会进行实际的使用和操作。ORM其中缺点之一就是可能会使程序运行效率降低。

Ø Beego项目中使用MySQL

在Beego中使用MySQL,步骤如下。

(1)导入对应数据库的驱动。

(2)注册驱动,注册数据库并进行连接。

(3)在执行数据库连接,数据库操作之前,要首先在数据库中创建一个新的数据库,否则会报错找不到数据库,字符编码采用utf8,能够存储汉字,否则容易出错。

列出数据库结构体代码列表,代码参见。

这里有很多的结构体类型,这些类型就是根据数据库中的表的字段,以及这些实体之间的关系来进行创建的。接下来,可以通过orm代码把这些实体注册到数据库中进行自动创建。

(4)注册数据库表模型,将设计的数据库表结构模型进行注册,核心代码如下所示。

(5)执行数据库操作,方法如下所示

关于结构体实体模型设计和定义,需要注意的是。

(1)一个结构体会形成一个表,一个字段名对应一个字段,字段名需要大写。在数据库中,驼峰命名的字段名从第二个驼峰开始在数据库中会以"_"表示。

(2)为了解析方便,可以为每一个字段赋值一个tag,模式类似这里的`json:"leve"`。

(3)表的关联关系和字段长度限制可以使用orm相关的设置来实现,也是tag的形式。

Ø 数据导入

创建好数据库表以后,进行数据导入。相关数据在资料文件夹内(通过扫二维码领取),拷贝,导入(在Dos窗口登录MySQL后执行 source .sql文件)即可。打开终端,登录数据库,执行插入语句,成功后查看数据库表内容。

Ø 接口文档说明

在正常的后台业务功能开发时,如何对数据接口进行定义,如何请求数据格式,如何返回数据格式,这些都需要一个标准的形式来规范,方便后端开发和其他端开发者进行对接。在现实的项目中,经常会有团队内部维护的wiki文档来存放接口文档。本书的实战项目的接口文档通过扫码领取。

Ø 模块开发

1.获取管理员信息

在router中注册路由方法,如下所示。

在AdminController结构体中定义GetAdminInfo方法来处理获取管理员信息的业务逻辑。

2.管理员退出账号

在router中注册路由方法,如下所示。

在AdminController结构体中定义SignOut方法并进行逻辑处理。

3.获取管理员列表信息

在router中注册路由方法,如下所示。

在AdminController结构体中定义GetAdminList方法并进行逻辑处理。

具体代码参见。

Ø 数据格式封装

Beego支持返回多种类型的数据格式,框架已经封装好了JSOM,XML等返回数据的格式封装供开发者调用。

JSON格式:controller.ServeJSON()方法可以自动将controller.Data["json"]中的数据按照json格式进行组装,开发者们只需要关注本身的字段名字和对应的字段值即可,大大提高了开发效率。

XML格式:controller.ServeXML()方法可以自动将controller.Data["xml"]中的数据按照XML格式进行组装。

Redis、项目功能完善

Ø Redis简介

Redis是一个非关系型(key-value)存储系统。它支持存储的value类型很多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,并且都是原子操作。Redis的数据缓存在内存中。redis会周期性的将更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

Ø Redis安装

首先进入Redis官方下载地址并挑选可以直接安装运行的msi文件下载,然后点击msi文件,顺着指引,点击Next,即可安装成功。安装过程中要设置安装目录、监听端口、最大存储值。

安装完毕。接下来验证Redis服务是否安装并启动成功,首先找到自己安装Redis的目录,查看安装的文件是否存在。

随后打开cmd终端,并进入到redis安装目录:执行redis-cli.exe文件,如图所示。

出现上面的画面,表示安装成功。

Ø Redis操作与使用

Redis支持数据类型:string,hash,list,set,sorted set

1. String(字符串)

string类型是Redis最基本的类型,一个key对应一个value。Redis的string可以包含任何数据,比如jpg图片,或者序列化的对象,都可以存储。string类型最大的能够存储512MB。

存储String操作命令如下所示。

获取String操作命令如下所示

2.Hash( 哈希类型)

Redis中的Hash是一个(key=>value)对集合。

设置hash的操作命令如下所示。

获取hash的操作命令如下所示。

3. List(列表)

按照插入顺序保存字符串列表,有顺序,支持push操作。

添加list字符的操作命令如下所示。

获取list字符的操作:命令如下所示。

4. set(集合)

Redis中的set是string类型的无序集合。集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。

添加的操作命令如下所示。

获取的操作操作命令如下所示。

5.zset(sorted set:有序集合)

zset和set一样,都是存储string类型的集合,且都不允许重复;区别是zset是为每一个元素都关联一个double类型的分数,并使用该分数对集合成员进行从小到大的排序。

添加元素的操作命令如下所示。

获取zset元素的操作命令如下所示。

Ø 项目中使用Redis

项目中把不会经常变的数据以缓存的形式存放,在Beego中,Redis属于cache缓存模块的相关内容。Beego框架目前支持File、Memcache、Memory和Redis四种引擎。如果要独立的安装引用缓存模块,安装方式如下:go get http://github.com/astaxie/beego/cache。

如果使用redis驱动就需要手工安装引入包:go get -u http://github.com/astaxie/beego/cache/redis

使用操作步骤:

(2)初始化对象:bm, err := cache.NewCache("memory", `{"interval":60}`)。

(3)常见的操作方法如下所示。

注意:如果引入过程中报错提示找不到,有可能是没有下载依赖库的原因,请先下载依赖库:go get http://github.com/garyburd/redigo/redis。

Ø 登录管理员退出操作

管理员退出账号时,要将服务器端的session进行清除,使用this.DelSession(sessionName)来进行操作。具体代码参见。

Ø 文件操作

在Web开发过程中,文件操作也是常常会被涉及到的常规操作, 在文件上传的过程中,本项目采用post请求,类型是file,直接把文件进行上传。

在服务端,Beego框架封装了文件操作的相关的方法和API。

获取文件的方法如下所示。

保存文件的方法如下所示。

文件操作是比较重要的一项基本技能,大家应该牢牢掌握,多加练习。具体的文件操作代码逻辑较为复杂,可以查看本项目代码。

Ø 数据库表关系映射

如果有过数据库编程经验的读者,肯定都知道数据库表与表的关系有多种,实体关系一般来说有三种关系。

(1)一对一关系:比如一个学生只能有一个所属班级。

(2)一对多关系:比如一个老师可以有多个学生。

(3)多对多关系:比如一个老师可以教多名学生,而一名学生是由多名老师来教学的。

了解这三种关系以后,再来看在Beego的orm模块当中,如何来表示这些关系。在Beego中,三种关系的orm映射设置及反向关系设置如下。

(1)一对一关系,具体设置方法如下所示。

(2)一对多关系,具体设置方法如下所示。

(3)多对多关系,具体设置方法如下所示。

以上的代码设置,就是在Beego当中,要进行orm设置的一些实体关系。具体的在程序当中如何使用,大家可以查看项目代码。

项目功能完善

Ø 商户模块功能开发

在本项目中,商户是一个单独的模块,新建商户控制器文件shopController.go实现商户模块功能开发,解下来看下涉及到的一些功能:

(1)商户总数查询:该功能接口用于查询总的商户记录,并返回给浏览器前端进行展示。商户总数查询接口: /shopping/restaurants/count 。

(2)商户列表查询:该功能接口 用于返回商户列表记录数据。商户列表查询接口: /shopping/restaurants 。

(3)删除商户操作:删除商户需要用到商户的id,http请求方式为DELETE。具体的功能接口为: /shopping/restaurant/:id。

具体代码参见。

Ø 食品模块功能开发

开发食品模块功能新创建foodController.go文件以及model模块的foodModel.go文件,foodController.go为控制器文件,用来处理http请求逻辑实现,foodModel.go文件用于数据库model实体转换为json数据格式的操作。

(1)食品总数查询功能:食品总数查询用户返回食品总数记录数据,功能接口如下: /shopping/v2/foods/count。

(2)食品列表查询功能:食品列表接口: /shopping/v2/foods 。

在列表查询过程中,需要有两个参数,分别是:offset,limit。offset字段表示偏移,limit字段表示查询的记录限制。

Ø 订单模块功能开发

(1)订单总数接口查询:该功能接口为: /bos/orders/count 。

(2)订单列表查询。查询订单列表数据,这功能接口为: /bos/orders 。功能代码如下所示。

Ø 添加数据模块功能开发

(1)添加商铺记录操作:对于添加商铺记录的操作,需要用到事务操作和多对多关系操作的代码。在Beego中,事务的执行方法为:om.Begin()事务开始和om.Comiit()提交事务。对于多对多的关系操作,在Beego中使用om. QueryM2M 来进行操作对多多操作。多对多的关联操作包含:Add,Remove,Clear,Count()等方法操作。在本项目中,添加商铺记录接口为:/shopping/addShop 。

(2)添加食品记录:添加食品记录也是POST请求,服务器新添加端接收JSON格式的数据,并进行解析

需要注意的是,前端提交的数据字段个类型和格式和服务器端定义的结构体字段和类型必须一致,否则会JSON解析报错。添加食品接口定义: /shopping/addfood 。

功能开发代码如下所示。

Beego框架项目实战小结

Beego实战项目到此已经全部开发完成。建议读者要利用空闲的时间对项目功能进行代码开发,熟悉,巩固go语言和Beego框架知识。这个世界没有天才,有的只是“刻意练习”。所谓天才,就是练习次数最多的人。