GoFrame学习随便记1

用Yii1.1中典型的 blog 项目作为例子来学习Web应用应该不错。数据库 sqlite3,windows下可以下载 sqlite-tools-win-x64-***  (https://www.sqlite.org/download.htm),把下载的几个exe放到  %GOPATH%\bin 目录下,而该目录在 %PATH% 环境变量中,因此,可以直接使用 sqlite3.exe。

安装 GoFrame 框架工具 gf:我们使用编译安装方式,先切换到 %GOPATH%\src,然后执行

git clone https://github.com/gogf/gf && cd gf/cmd/gf && go install

就会把 gf 安装到 %GOPATH%\bin 目录下,可以任意目录输入   gf  -v 验证。

用模板创建项目:先切换到 %GOPATH%\src,然后执行

gf init blogdemo -u

就会生成  %GOPATH%\src\blogdemo 项目目录。可以切换到项目根目录 blogdemo 后运行

gf  run  main.go

编译项目并运行。默认项目中有OpenAPI接口文档、Swagger接口文档和一个 /hello 接口例子。我们将在此基础上添砖加瓦。

我们先需要一个数据库。为了简单,使用 sqlite3 数据库:在项目根目录下执行 

sqlite3  blogdemo.db

在项目根目录生成数据库文件 blogdemo.db (实际应用可能需要仔细考虑将数据库放置在更合适位置),然后在 sqlite3 命令行下执行下述 sql 语句:

CREATE TABLE tbl_lookup
(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,name VARCHAR(128) NOT NULL,code INTEGER NOT NULL,type VARCHAR(128) NOT NULL,position INTEGER NOT NULL
);CREATE TABLE tbl_user
(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,username VARCHAR(128) NOT NULL,password VARCHAR(128) NOT NULL,email VARCHAR(128) NOT NULL,profile TEXT
);CREATE TABLE tbl_post
(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,title VARCHAR(128) NOT NULL,content TEXT NOT NULL,tags TEXT,status INTEGER NOT NULL,create_time INTEGER,update_time INTEGER,author_id INTEGER NOT NULL,CONSTRAINT FK_post_author FOREIGN KEY (author_id)REFERENCES tbl_user (id) ON DELETE CASCADE ON UPDATE RESTRICT
);CREATE TABLE tbl_comment
(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,content TEXT NOT NULL,status INTEGER NOT NULL,create_time INTEGER,author VARCHAR(128) NOT NULL,email VARCHAR(128) NOT NULL,url VARCHAR(128),post_id INTEGER NOT NULL,CONSTRAINT FK_comment_post FOREIGN KEY (post_id)REFERENCES tbl_post (id) ON DELETE CASCADE ON UPDATE RESTRICT
);CREATE TABLE tbl_tag
(id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,name VARCHAR(128) NOT NULL,frequency INTEGER DEFAULT 1
);INSERT INTO tbl_lookup (name, type, code, position) VALUES ('Draft', 'PostStatus', 1, 1);
INSERT INTO tbl_lookup (name, type, code, position) VALUES ('Published', 'PostStatus', 2, 2);
INSERT INTO tbl_lookup (name, type, code, position) VALUES ('Archived', 'PostStatus', 3, 3);
INSERT INTO tbl_lookup (name, type, code, position) VALUES ('Pending Approval', 'CommentStatus', 1, 1);
INSERT INTO tbl_lookup (name, type, code, position) VALUES ('Approved', 'CommentStatus', 2, 2);INSERT INTO tbl_user (username, password, email) VALUES ('demo','$2a$10$JTJf6/XqC94rrOtzuF397OHa4mbmZrVTBOQCmYD9U.obZRUut4BoC','webmaster@example.com');
INSERT INTO tbl_post (title, content, status, create_time, update_time, author_id, tags) VALUES ('Welcome!','This blog system is developed using Yii. It is meant to demonstrate how to use Yii to build a complete real-world application. Complete source code may be found in the Yii releases.Feel free to try this system by writing new posts and leaving comments.',2,1230952187,1230952187,1,'yii, blog');
INSERT INTO tbl_post (title, content, status, create_time, update_time, author_id, tags) VALUES ('A Test Post', 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', 2,1230952187,1230952187,1,'test');INSERT INTO tbl_comment (content, status, create_time, author, email, post_id) VALUES ('This is a test comment.', 2, 1230952187, 'Tester', 'tester@example.com', 2);INSERT INTO tbl_tag (name) VALUES ('yii');
INSERT INTO tbl_tag (name) VALUES ('blog');
INSERT INTO tbl_tag (name) VALUES ('test');

可以执行 SELECT  *  FROM  tbl_lookup; 简单验证数据是否已经生成,最后  .quit 退出命令行。

GoFrame 能直接根据数据库表生成一些代码吗?答案是 Yes, it is。GoFrame对于代码生成工具,专门有一个配置文件   hack/config.yaml  (Yii2 中 migrate 使用 console 对应配置文件,而代码生成有专用Web客户端gii,还是要更方便一些),我们在这个文件中添加

gfcli:
.....................................gen:dao:- link: "sqlite::@file(blogdemo.db)"tables: "tbl_lookup,tbl_user,tbl_post,tbl_comment,tbl_tag"jsonCase: "CamelLower"removePrefix: "tbl_"

在项目根目录执行  gf  gen  dao ,就会在 internal/dao、internal/model/entity 和 internal/model/do 三个目录下生成文件。用 yii2 方式来理解,yii2的model 包含了这里的 entity和dao,entity差不多就是字段映射而已,dao 中可以额外添加对表的操作。而 do 和 yii2 的 search model中的字段映射部分比较接近。换句话说,如果没有额外自定义的表操作,这三个部分都是无聊的。

GoFrame 能生成 controller 吗?答案是肯定的。GoFrame 允许根据你设计的 API 来“反向”生成 controller: 我们在 api 目录下创建子目录 lookup,然后在 api/lookup 下创建子目录 v1,最后在 api/lookup/v1 下创建 lookup.go 文件

package v1import ("blogdemo/internal/model/entity""github.com/gogf/gf/v2/frame/g"
)type LookupGetListReq struct {g.Meta   `path:"/lookup" method:"get"`Id       int    `json:"id"       dc:"ID"`   //Name     string `json:"name"     dc:"名称"`   //Code     int    `json:"code"     dc:"代码"`   //Type     string `json:"type"     dc:"类别"`   //Position int    `json:"position" dc:"排序位置"` //
}type LookupGetListRes struct {List []*entity.Lookup `json:"list" dc:"条目列表"`
}

(注意:反引号字符串中最后不能是空格,gf 不能识别此类错误) 为了能自动生成 controller,上述结构体必须按命名规范来命名,即 Xxx + 操作 + Req/Res 。文件中至少要有一个 path 命名(如 /lookup),不然无法生成controller。在项目根目录执行  gf  gen  ctrl 后,不仅会在 internal/controller下创建带3个文件的 lookup 子目录,还会在 api/lookup下创建 lookup.go 接口定义文件。api/lookup/lookup.go接口定义文件定义了 ILookupV1 接口,该接口包含 LookupGetList方法(对应我们设计接口时所用的操作)。internal/controller/lookup下分别是基本空的 lookup.go文件,定义“空”类型 ControllerV1 和工厂方法 NewV1() 的文件 lookup_new.go文件,定义“空”类型所含方法LookupGetList(这个方法是我们需要修改成具体实际实现的) 的 lookup_v1_lookup_get_list.go 文件。

和 API / controller 相关的另一个部分是路由。我们需要在 internal/cmd/cmd.go 中加入

var (Main = gcmd.Command{.............Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {s := g.Server()s.Group("/", func(group *ghttp.RouterGroup) {group.Middleware(ghttp.MiddlewareHandlerResponse)group.Bind(hello.NewV1(),lookup.NewV1(),   // 加入这一句)})s.Run()return nil},}
)

意思差不多相当于让控制器 ControllerV1 处理对应路由。

GoFrame还有一个代码生成是根据具体业务逻辑代码生成服务接口代码。一些框架中其实这两个部分是不分的,统一为 service层。对于yii2来说,更是粗粒度的把业务逻辑直接放入model中的。我们在 internal/logic下创建子目录lookup,然后在 internal/logic/lookup下创建 lookup.go文件:

package lookupimport ("blogdemo/internal/dao""blogdemo/internal/model/entity""blogdemo/internal/service""context"
)type sLookup struct{}func init() {service.RegisterLookup(New())
}func New() *sLookup {return &sLookup{}
}func (s *sLookup) GetList(ctx context.Context) (list []*entity.Lookup, err error) {err = dao.Lookup.Ctx(ctx).OrderAsc(dao.Lookup.Columns().Code).OrderAsc(dao.Lookup.Columns().Id).Scan(&list)return
}

(注意:IDE可能会识别有些东西不存在,这是正常的,因为是反向去生成service接口文件的。注意,sLookup类型需要用小写s开头。) sLookup“空”类型拥有 GetList方法,它使用dao来获得数据(这个也是我们需要具体实现的)。init()初始化方法和工厂方法 New() 实现了依赖注入。执行 gf  gen  service,会在 internal/service下创建服务接口文件lookup.go。如果此前从来没有生成过,还会在 internal/logic生成 logic.go 接口实现注册文件(也就是用 import 触发 internal/logic/lookup/lookup.go中的init()。此前如果已经生成logic.go文件,只会更新该文件。)。

有了 logic 中 GetList 的具体实现,我们在 controller 中就可以调用这个实现来返回数据了。修改 internal/controller/lookup/lookup_v1_lookup_get_list.go:

package lookupimport ("context"v1 "blogdemo/api/lookup/v1""blogdemo/internal/service"
)func (c *ControllerV1) LookupGetList(ctx context.Context, req *v1.LookupGetListReq) (res *v1.LookupGetListRes, err error) {//return nil, gerror.NewCode(gcode.CodeNotImplemented)res = &v1.LookupGetListRes{}res.List, err = service.Lookup().GetList(ctx)return
}

到这里,还剩最后一个问题:gf 自身是包含了 sqlite驱动的,因此 hack/config.yaml中配置后就可以生成 dao/entity/do 代码,但我们的应用不会自动识别数据库驱动,需要引入并配置。在 main.go开头引入      _  "github.com/gogf/gf/contrib/drivers/sqlite/v2"   (可能需要 go get 一下,具体参考 https://github.com/gogf/gf/tree/master/contrib/drivers)。修改配置文件 manifest/config/config.yaml

.........................................
database:logger:path:   "temp/logs/sql"level:  "all"stdout: truectxKeys:  ["RequestId"]default:link:   "sqlite::@file(blogdemo.db)"debug:  true

最后,用浏览器访问 http://127.0.0.1:8000/lookup 将返回

{"code":0,"message":"","data":{"list":[{"id":1,"name":"Draft","code":1,"type":"PostStatus","position":1},{"id":4,"name":"Pending Approval","code":1,"type":"CommentStatus","position":1},{"id":2,"name":"Published","code":2,"type":"PostStatus","position":2},{"id":5,"name":"Approved","code":2,"type":"CommentStatus","position":2},{"id":3,"name":"Archived","code":3,"type":"PostStatus","position":3}]}}

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

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

相关文章

MATLAB中zticks函数用法

目录 语法 说明 示例 指定 z 轴刻度值和标签 指定非均匀 z 轴刻度值 以 2 为增量递增 z 轴刻度值 将 z 轴刻度值设置回默认值 指定特定坐标区的 z 轴刻度值 删除 z 轴刻度线 zticks函数的功能是设置或查询 z 轴刻度值。 语法 zticks(ticks) zt zticks zticks(auto)…

java解析Cron时间表达式为中文描述

碰到个需求,后端返回给前端的时候如果直接返回表达式给前端在页面展示,用户会看不懂!所以要转为非开发人员看到也能明白的中文描述 这里说一下后端解析,无非就是空格切分一个个判断了: 前端js解析在这里:…

ReportLab创建合同PDF

一、前言 有一个项目需要将电子签名后的报价合同和生成的发票发送给客户,这种发送给客户的文件一般都是使用PDF格式,主要是因为PDF特别适合阅读且不同平台打开文件格式不会变形,不过要在程序中生成PDF还是比较麻烦的,我们的发票是…

TCP与UDP协议

TCP与UDP协议 1、TCP协议: 1、TCP特性: TCP 提供一种面向连接的、可靠的字节流服务。在一个 TCP 连接中,仅有两方进行彼此通信。广播和多播不能用于 TCP。TCP 使用校验和,确认和重传机制来保证可靠传输。TCP 给数据分节进行排序…

AdaBoost 算法:理解、实现和掌握 AdaBoost

一、介绍 Boosting 是一种集成建模技术,由 Freund 和 Schapire 于 1997 年首次提出。从那时起,Boosting 就成为解决二元分类问题的流行技术。这些算法通过将大量弱学习器转换为强学习器来提高预测能力 。 Boosting 算法背后的原理是,我们首先…

万宾科技智能传感器EN100-C2有什么作用?

在日常生活中井盖是一种常见的城市设施,但井盖出现问题可能会对人们的生活造成什么影响呢?移位或老化的井盖可能会威胁人们的安全,同时也会影响城市生命线的正常运行。然而智能井盖的出现为解决这些问题提供了有效的应对方案。 WITBEE万宾智能…

udp多点通信-广播-组播

单播 每次只有两个实体相互通信,发送端和接收端都是唯一确定的。 广播 主机之间的一对多的通信所有的主机都可以接收到广播消息(不管你是否需要)广播禁止穿过路由器(只能做局域网通信)只有UDP可以广播广播地址 有效网络号全是1的主机号 192.1…

Pikachu(皮卡丘靶场)初识XSS(常见标签事件及payload总结)

目录 1、反射型xss(get) 2、反射性xss(post) 3、存储型xss 4、DOM型xss 5、DOM型xss-x XSS又叫跨站脚本攻击,是HTML代码注入,通过对网页注入浏览器可执行代码,从而实现攻击。 ​ 1、反射型xss(get) Which NBA player do you like? 由…

nvm安装详细教程(卸载旧的nodejs,安装nvm、node、npm、cnpm、yarn及环境变量配置)

文章目录 一、完全卸载旧的nodejs1、打开系统的控制面板,点击卸载程序,卸载nodejs(1)打开系统的控制面板,点击程序下的卸载程序(2)找到node.js,鼠标右击出现下拉框,点卸载…

《Effective C++》条款12

复制对象时勿忘其每一个成分 我们都知道,我们不主动写拷贝构造函数或者赋值重载运算符,那么编译器就会自动生成默认的函数。当我们写时,编译器不会自动生成,它只会找对应我们写的函数,如果此时我们写的函数出现了问题&…

YOLO改进系列之注意力机制(EffectiveSE模型介绍)

模型结构 ESE(Effective Squeeze and Extraction) layer是CenterMask模型中的一个block,基于SE(Squeeze and Extraction)改进得到。与SE的区别在于,ESE block只有一个fc层,(CenterMask : Real-Time Anchor-Free Insta…

【git】远程远程仓库命令操作详解

这篇文章主要是针对git的命令行操作进行讲解,工具操作的基础也是命令行,如果基本命令操作都不理解,就算是会工具操作,真正遇到问题还是一脸懵逼 如果需要查看本地仓库的详细操作可以看我上篇文件 【git】git本地仓库命令操作详解…

IIC总线概述和通信时序代码详细图文解析

IIC总线 1 IIC总线概述 I2C总线两线制包括:串行数据SDA(Serial Data)、串行时钟SCL(Serial Clock)。总线必须由主机(通常为微控制器)控制,主机产生串行时钟(SCL&#x…

【TDSQL-PG数据库简单介绍】

TDSQL-PG数据库简单介绍 TDSQL-PGTDSQL-PG 设计目标 TDSQL-PG 腾讯 TDSQL-PG 分布式关系型数据库是一款面向海量在线实时分布式事务交易和 MPP 实时数据分析 通用型高性能数据库系统。 面对应用业务产生的不定性数据爆炸需求,不管是高并发的交易还是海量的实时数据…

Panda3d 动画序列

动画序列 文章目录 动画序列使用动画序列Lerp动画序列基于 NodePath 的 LerpIntervals 概述一些方便快捷的函数功能其余基于 NodePath 的 LerpIntervals其他类型的 LerpInterval使用 Func 来处理动画序列Actor 动画序列声音动画序列序列和平行运动路径粒子动画序列射弹动画序列…

Linux安装DMETL5与卸载

Linux安装DMETL5与卸载 环境介绍1 DM8数据库配置1.1 DM8数据库安装1.2 初始化达梦数据库1.3 创建DMETL使用的数据库用户 2 配置DMETL52.1 解压DMETL5安装包2.2 安装调度器2.3 安装执行器2.4 安装管理器2.5 启动dmetl5 调度器2.6 启动dmetl5 执行器2.7 启动dmetl5 管理器2.8 查看…

跨境电商与文化多样性:市场中的机遇

在数字时代,跨境电商已经成为全球贸易的主要驱动力之一。随着互联网的普及和物流的改善,企业有机会将产品和服务推向全球市场。 然而,随着全球市场的扩大,文化多样性也成为了一个重要的考虑因素。本文将深入探讨跨境电商与文化多…

【408】计算机学科专业基础 - 操作系统

一、计算机系统概述 1.简介 什么是操作系统? 操作系统(Operating Ststem, OS)是指控制和管理整个计算机系统的硬件和软件资源,并合理地组织调度计算机的工作和资源的分配,以提供给用户和其他软件方便的接口…

成功解决:文档根元素 “mapper“ 必须匹配 DOCTYPE 根 “null“

文章底部有个人公众号:热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享? 踩过的坑没必要让别人在再踩,自己复盘也能加深记忆。利己利人、所谓双赢。 文章目录 前言错误信息解决方法 前言 错误…

【中间件篇-Redis缓存数据库07】Redis缓存使用问题及互联网运用

Redis缓存使用问题 数据一致性 只要使用到缓存,无论是本地内存做缓存还是使用 redis 做缓存,那么就会存在数据同步的问题。 我以 Tomcat 向 MySQL 中写入和删改数据为例,来给你解释一下,数据的增删改操作具体是如何进行的。 我…