示例是最好的文档,我们为大家准备了一个简单的API示例项目,大家可以通过示例项目源码更进一步学习框架使用。当大家在阅读源码时有疑问的地方,在官网文档中均有答案,请有效利用好官网WIKI的搜索功能。

一、项目介绍

我们以一个简单的基于HTTPAPI Service为例来介绍如何使用GoFrame框架以及相应的CLI工具来开发一个接口项目。

代码地址:https://github.com/gogf/gf-demo-user

git clone https://github.com/gogf/gf-demo-user

请先尝试将此项目在本地运行起来。再接下来我们将会给大家介绍这个示例项目的一些细节。

二、要点介绍

1、接口定义

接口注册文件位于api目录下,由于该项目采用了规范路由注册方式,因此在API结构体的属性中包含一些标签。其中结构体属性的v标签表示校验规则,请求参数进入HTTP Server后将会被自动执行校验(框架有非常强大的数据校验组件,更详细的介绍请参考章节:数据校验

框架中所有涉及到的标签请参考章节:常见问题(FAQ)

2、路由注册

路由注册往往在cmd包中,在本项目中,仍旧采用灵活的分组路由注册方式。在部分路由中带有鉴权中间件,这部分路由需要鉴权后才能访问,感兴趣的小伙伴可以仔细研究下源码的实现原理。关于路由中间件的详细介绍请参考章节:路由管理-中间件/拦截器

3、常量管理

项目的全局访问常量位于internal/consts包下,供项目所有的包全局可访问,全局常量通过不同的文件以及名称命名前缀来区分不同的业务模块。需要注意的是,不建议所有的常量都丢到internal/consts下,非公开的常量建议放到对应的包下面闭环维护。

4、控制器定义

控制器往往不带有任何的业务逻辑,负责API接口数据结构的输入与输出,调用一个或多个service实现具体的业务逻辑。关于项目工程设计中各个部分的职责请参考章节:工程目录设计??

5、数据库访问

1)驱动引入(仅一次)

首先,需要引入对应的驱动文件,由于我们这里使用的是MySQL,我们需要在main.go中引入以下驱动文件:

关于驱动的支持以及使用请参考链接:https://github.com/gogf/gf/tree/master/contrib/drivers

2)数据库配置

数据库的配置使用database配置项,关于数据库配置的详细介绍请参考章节:ORM使用配置

3)dao代码生成

在业务项目中,我们推荐使用dao/do/entity的方式操作数据库,这些文件都是通过开发工具自动生成的,由开发工具统一维护

代码生成方式通过 make dao命令,或者gf gen dao命令,如下:

关于数据库痛点及设计请参考章节:DAO封装设计,关于数据库代码文件生成工具的介绍请参考章节:数据规范-gen dao

6、业务模型

业务项目中内部模块间交互的数据结构model包维护,供全局访问。更多的介绍请参考章节:数据模型与业务模型

7、服务接口

为了降低业务项目内部模块间的耦合,框架将模块间的依赖抽象为了接口,由internal/service包维护。internal/service可以由开发者自定义维护接口,也可以通过internal/logic业务封装的代码按照一定规则自动生成接口代码文件。具体请参考章节:模块规范-gen service

8、业务实现

业务的具体实现由internal/logic包维护,通过依赖注入的方式注册具体的实现对象到internal/service包下。

1)依赖注入

业务实现的依赖注入使用的是匿名包初始化方法init,在匿名包初始化方法内部使用service.RegisterXxx的方式注入具体的接口实现对象。

2)增加引入(仅一次)

匿名包初始化方法需要通过import方式引入,该引入用于将业务逻辑具体实现注册到internal/service下。这种依赖往往需要在main.go中顶部引入。

需要注意,在通过框架开发工具自动生成service层接口文件时,开发工具同时也会自动更新最外层的main.go,自动增加logic引入,无需开发者操心。

三、代码生成

框架的目的是让开发者将精力聚焦于业务逻辑实现本身。在开发业务项目时,非业务相关的冗余代码都可以通过开发工具生成,例如以下层级代码:

  1. controller
  2. dao/entity/do
  3. service

更详细的介绍请参考开发工具章节:代码生成-gen(🔥重点🔥)

四、接口测试

我们通过curl命令来对其中两个接口执行简单的测试。

1、用户注册 - /user/signup

注册一个账号test001,昵称为john,密码为123456

curl -d 'nickname=john&passport=test001&password=123456&password2=123456' http://127.0.0.1:8000/user/sign-up
{"code":0,"message":"","data":null}

我们再次使用刚才的信息注册一次试试。

curl -d 'nickname=john&passport=test001&password=123456&password2=123456' http://127.0.0.1:8000/user/sign-up
{"code":50,"message":"Passport \"test001\" is already token by others","data":null}

可以看到注册失败了,相同名称只能注册一个账号。

2、用户登录 - /user/signin

我们先访问获取用户信息的接口,验证鉴权中间件是否生效。

curl http://127.0.0.1:8000/user/profile
Forbidden

我们用刚才注册的账号登录。

curl -i -d 'passport=test001&password=123456' http://127.0.0.1:8000/user/sign-in
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Origin,Content-Type,Accept,User-Agent,Cookie,Authorization,X-Auth-Token,X-Requested-With
Access-Control-Allow-Methods: GET,PUT,POST,DELETE,PATCH,HEAD,CONNECT,OPTIONS,TRACE
Access-Control-Allow-Origin: *
Access-Control-Max-Age: 3628800
Content-Type: application/json
Server: GoFrame HTTP Server
Set-Cookie: gfsessionid=14sc9nep0u6yl0cieluexn0n0w2008q7; Path=/; Expires=Wed, 09 Mar 2022 15:52:44 GMT; SameSite
Trace-Id: 4830f6adbb72da16f34b7162f93080d8
Date: Tue, 08 Mar 2022 15:52:44 GMT
Content-Length: 35

{"code":0,"message":"","data":null}

我们这里使用了-i选项用于终端打印出服务端返回的Header信息,目的是为了获取sessionidGoFrame框架默认的sessionid名称为gfsessionid,我们看到返回的Header中已经有了,并且是通过Cookie方式返回的。

随后我们再次访问获取用户信息接口,并且这次提交gfsessionid,该信息可以通过Header也可以通过Cookie提交,服务端都是能够自动识别的。

curl -H 'gfsessionid:14sc9nep0u6yl0cieluexn0n0w2008q7' http://127.0.0.1:8000/user/profile
{"code":0,"message":"","data":{"id":1,"passport":"test001","password":"123456","nickname":"john","createAt":"2022-03-08 23:51:40","updateAt":"2022-03-08 23:51:40"}}

五、更多示例

我们提供了另一个较为完整的示例项目,感兴趣可以研究一下源码:https://github.com/gogf/focus-single

Content Menu

  • No labels

11 Comments

  1. dao代码生成,使用 gf gen dao,如果字段是中文,会出错,我用mysql和MariaDB试过,改成英文就好了。提示

    error format "internal\dao\internal\traveler_list.go" go files: internal\dao\internal\traveler_list.go:44:13: expected operand, found ':' (and 2 more errors)

    具体生成的结构中文字段不会显示。

  2. dao代码生成, PQ数据库,生成失败。

    fetching tables failed: missing "=" after "postgres:admin@tcp(127.0.0.1:5432)/dtcloud1" in connection info string", SELECT TABLENAME FROM PG_TABLES WHERE SCHEMANAME = 'public' ORDER BY TABLENAME
    1. missing "=" after "postgres:admin@tcp(127.0.0.1:5432)/dtcloud1" in connection info string", SELECT TABLENAME FROM PG_TABLES WHERE SCHEMANAME = 'public' ORDER BY TABLENAME

    1. 用最新的版本解决了。 

  3. 实例项目中,cmd.go中提示  

    duplicated route registry "/user/profile/check-passport@default" at /Users/wings/go/learn/demo/internal/cmd/cmd.go:36 , already registered at /Users/wings/go/learn/demo/internal/cmd/cmd.go:30

  4. 郭大侠 刚刚学goframe,把这个DEMO应用导进去跑了一把,竟然在https://github.com/gogf/focus-single这里发现了彩蛋!

  5. 2.5.2版本用vscode开发的花太麻烦了

  6. 2.5.4 版本,用postman请求 /user/sign-up 接口,报 Forbidden 错误,请问是什么原因呢?

    1. 他有一个鉴权的地方,注释了就好了

    2. 看这个:https://github.com/gogf/gf-demo-user/issues/29


      group.ALLMap(g.Map{
      "/user/profile": userCtrl.Profile,
      })

      请求也要带上"Cookie: xx"的前缀。
      curl -H "Cookie: gfsessionid=1mydni0ty31v70cww1ouyykius600ikl" http://127.0.0.1:8000/user/profile

  7. cgd

    如何获取请求用户的IP?

    1. ng配置下

      proxy_set_header           X-Real-IP        $remote_addr;

      然后

      r.GetHeader("X-Real-IP"),