zoukankan      html  css  js  c++  java
  • go语言web开发系列之一:gin+gorm开发一个简单的热榜接口站

    一,热榜的例子:

    以抽屉新热榜为例,只存储资讯的链接和提示,

    用户点击时会跳转到外部的网站阅读

    我们在这里只实现了显示单条内容和多条内容的功能,

    主要是把它做为后续功能集成演示的一个基础

    后续的集成包括:

    1.  
      统一报错信息
    2.  
       
    3.  
      统一rest输出
    4.  
       
    5.  
      validator
    6.  
       
    7.  
      日志功能
    8.  
       
    9.  
      安全
    10.  
       
    11.  
      接口文档
    12.  
       
    13.  
      统一读取配置文件
    14.  
       
    15.  
      ...
    16.  
       
    17.  
      其他想到再补充吧

    说明:刘宏缔的go森林是一个专注golang的博客,
              地址:https://blog.csdn.net/weixin_43881017

    说明:作者:刘宏缔 邮箱: 371125307@qq.com

    二,演示项目的相关信息

    1,项目地址:

    https://github.com/liuhongdi/digv01

    2,项目功能:输出一条资讯的信息、输出多条资讯的信息

    3,项目结构:

        

    4,  项目各文件夹的说明:

        controller:  控制器,负责接收参数、验证参数,调用service,统一输出

        dao:          到数据库的访问

        doc:          文档

        global:      全局用到的变量,主要是配置、数据库连接、日志功能等

        model:    数据模型

        router:   路由

       service:   主要的业务逻辑

    三,sql相关说明:     

    1.  
      CREATE TABLE `article` (
    2.  
      `articleId` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
    3.  
      `type` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '类型',
    4.  
      `subject` varchar(500) NOT NULL DEFAULT '' COMMENT '标题',
    5.  
      `addTime` datetime NOT NULL DEFAULT '2020-11-19 00:00:00' COMMENT '添加时间',
    6.  
      `isHot` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '是否热榜,0:非热,1,热',
    7.  
      `url` varchar(500) NOT NULL DEFAULT '' COMMENT '链接地址',
    8.  
      `domain` varchar(100) NOT NULL DEFAULT '' COMMENT '域',
    9.  
      `userId` bigint unsigned NOT NULL DEFAULT '0' COMMENT '推荐用户',
    10.  
      `approvalStaffId` int unsigned NOT NULL DEFAULT '0' COMMENT '批准员工',
    11.  
      `digSum` int unsigned NOT NULL DEFAULT '0' COMMENT '被顶的次数',
    12.  
      `commentSum` int unsigned NOT NULL DEFAULT '0' COMMENT '被评论的次数',
    13.  
      `isPublish` tinyint NOT NULL DEFAULT '0' COMMENT '0,未发布,1,已发布',
    14.  
      PRIMARY KEY (`articleId`),
    15.  
      KEY `isPublish` (`isPublish`)
    16.  
      ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='文章表'

       插入6条演示数据:

    1.  
      INSERT INTO `article` (`articleId`, `type`, `subject`, `addTime`, `isHot`, `url`, `domain`, `userId`, `approvalStaffId`, `digSum`, `commentSum`, `isPublish`) VALUES
    2.  
      (1, 0, '【最近,南非发现一座大油田】石油和天然气两种重要资源是南非储量的最短板,“贫油”的帽子也一直扣在南非的头上摘不下来。可就在最近,在南非海域进行油气勘探已久的道达尔透露了其新的勘探成果:在距离南非南部海岸约175公里的奥特尼夸盆地的11B/12B地区,再次发现了重要的凝析气,可能蕴藏着大量天然气及原油。', '2020-11-19 00:00:00', 1, 'https://mp.weixin.qq.com/s/1btbmouH-2KuIHUMoucq2w', '', 1, 1, 0, 0, 1),
    3.  
      (2, 1, '让喵喵来开启周五的早晨吧!', '2020-11-19 00:00:00', 0, 'https://m.weibo.cn/status/4573112073720433?', 'm.weibo.cn', 0, 0, 0, 0, 1),
    4.  
      (3, 0, '汤姆·赫兰德、黛茜·雷德利、麦斯·米科尔森、尼克·乔纳斯主演的《混沌漫步》公开预告。影片由《明日边缘》导演道格·里曼执导,暂时定档明年1月22日上映。', '2020-11-19 00:00:00', 1, 'http://news.mtime.com/2020/11/19/1604795.html', 'news.mtime.com', 0, 0, 0, 0, 1),
    5.  
      (4, 1, '扫地机器人这个东西确实方便,大多数时候把房间扫的比较干净,但还有很多边边角角清扫不上,希望厂家能够在app上显示出机器人的路线图,明确告知哪些路段没有照顾到,要不然就再开发一个项目经理机器人,跟在扫地机器人屁股后面监督。//@大窑儿:可以弄个步数排行榜,让机器人们互相点赞,揣摩,攀比,内卷,无意义竞争。', '2020-11-19 00:00:00', 0, '', '', 0, 0, 0, 0, 1),
    6.  
      (5, 0, '【世卫组织建议医生不要使用瑞德西韦治疗新冠】世卫组织指导小组表示,证据显示,瑞德西韦对提高新冠肺炎患者的存活率没有显著影响。这项建议发表在上周五的《英国医学杂志》中。', '2020-11-19 00:00:00', 0, 'https://www.thepaper.cn/newsDetail_forward_10067542', 'thepaper.cn', 0, 0, 0, 0, 1),
    7.  
      (6, 0, '11月19日0—24时,31个省(自治区、直辖市)和新疆生产建设兵团报告新增确诊病例17例,均为境外输入病例(福建6例,上海4例,陕西3例,广东2例,北京1例,四川1例);无新增死亡病例;新增疑似病例1例,为本土病例(在天津)。', '2020-11-19 00:00:00', 0, 'http://m.news.cctv.com/2020/11/20/ARTIIR9o72TuDF80s6hY2IvD201120.shtml', 'm.news.cctv.com', 0, 0, 0, 0, 1);

    四,go代码说明

    1,main.go

    1.  
      package main
    2.  
       
    3.  
      import (
    4.  
      _ "github.com/jinzhu/gorm/dialects/mysql"
    5.  
      "github.com/liuhongdi/digv01/global"
    6.  
      "github.com/liuhongdi/digv01/router"
    7.  
      "log"
    8.  
      )
    9.  
       
    10.  
      func init() {
    11.  
      err := global.SetupDBLink()
    12.  
      if err != nil {
    13.  
      log.Fatalf("init.setupDBEngine err: %v", err)
    14.  
      }
    15.  
      }
    16.  
       
    17.  
      func main() {
    18.  
      //引入路由
    19.  
      r := router.Router()
    20.  
      //run
    21.  
      r.Run(":8080")
    22.  
      }

    2,router/router.go

    1.  
      package router
    2.  
       
    3.  
      import (
    4.  
      "github.com/gin-gonic/gin"
    5.  
      "github.com/liuhongdi/digv01/controller"
    6.  
      )
    7.  
       
    8.  
      func Router() *gin.Engine {
    9.  
      router := gin.Default()
    10.  
      // 路径映射
    11.  
      router.GET("/article/getone/:id", controller.NewArticleController().GetOne);
    12.  
      router.GET("/article/list", controller.NewArticleController().GetList);
    13.  
      return router
    14.  
      }

    3,controller/articleController.go

    1.  
      package controller
    2.  
       
    3.  
      import (
    4.  
      "fmt"
    5.  
      "github.com/gin-gonic/gin"
    6.  
      "github.com/liuhongdi/digv01/service"
    7.  
      "net/http"
    8.  
      "strconv"
    9.  
      )
    10.  
       
    11.  
      type ArticleController struct{}
    12.  
       
    13.  
      func NewArticleController() ArticleController {
    14.  
      return ArticleController{}
    15.  
      }
    16.  
      //得到一篇文章的详情
    17.  
      func (a ArticleController) GetOne(c *gin.Context) {
    18.  
       
    19.  
      id := c.Params.ByName("id")
    20.  
      fmt.Println("id:"+id);
    21.  
       
    22.  
      articleId,err := strconv.ParseInt(id, 10, 64);
    23.  
      if (err != nil) {
    24.  
      c.AbortWithStatus(400)
    25.  
      fmt.Println(err.Error())
    26.  
      }
    27.  
       
    28.  
      articleOne,err := service.GetOneArticle(articleId);
    29.  
      if err != nil {
    30.  
      c.AbortWithStatus(404)
    31.  
      fmt.Println(err.Error())
    32.  
      } else {
    33.  
      c.JSON(http.StatusOK, &articleOne)
    34.  
      }
    35.  
      return
    36.  
      }
    37.  
       
    38.  
      //得到多篇文章,按分页返回
    39.  
      func (a ArticleController) GetList(c *gin.Context) {
    40.  
       
    41.  
      page := c.DefaultQuery("page", "0")
    42.  
      pageInt, err := strconv.Atoi(page)
    43.  
      if (err != nil) {
    44.  
      c.AbortWithStatus(400)
    45.  
      fmt.Println(err.Error())
    46.  
      }
    47.  
      pageSize := 2;
    48.  
      pageOffset := pageInt * pageSize
    49.  
       
    50.  
      articles,err := service.GetArticleList(pageOffset,pageSize)
    51.  
      if err != nil {
    52.  
      c.AbortWithStatus(404)
    53.  
      fmt.Println(err.Error())
    54.  
      } else {
    55.  
      c.JSON(http.StatusOK, &articles)
    56.  
      }
    57.  
      return
    58.  
      }

    4,service/article.go

    1.  
      package service
    2.  
       
    3.  
      import (
    4.  
      "fmt"
    5.  
      "github.com/liuhongdi/digv01/dao"
    6.  
      "github.com/liuhongdi/digv01/model"
    7.  
      )
    8.  
      //得到一篇文章的详情
    9.  
      func GetOneArticle(articleId int64) (*model.Article, error) {
    10.  
      return dao.SelectOneArticle(articleId)
    11.  
      }
    12.  
       
    13.  
      //得到多篇文章,按分页返回
    14.  
      func GetArticleList(page int ,pageSize int) ([]*model.Article,error) {
    15.  
      articles, err := dao.SelectAllArticle(page,pageSize)
    16.  
      if err != nil {
    17.  
      fmt.Println("is error")
    18.  
      return nil,err
    19.  
      } else {
    20.  
      fmt.Println("not is error")
    21.  
      return articles,nil
    22.  
      }
    23.  
      }

    5,dao/article.go

    1.  
      package dao
    2.  
       
    3.  
      import (
    4.  
      "fmt"
    5.  
      "github.com/liuhongdi/digv01/global"
    6.  
      "github.com/liuhongdi/digv01/model"
    7.  
      )
    8.  
      //查询一条数据
    9.  
      func SelectOneArticle(articleId int64) (*model.Article, error) {
    10.  
      fields := []string{"articleId", "subject", "url"}
    11.  
      articleOne:=&model.Article{}
    12.  
      err := global.DBLink.Select(fields).Where("articleId=?",articleId).First(&articleOne).Error
    13.  
      if (err != nil) {
    14.  
      return nil,err
    15.  
      } else {
    16.  
      return articleOne,nil
    17.  
      }
    18.  
      }
    19.  
      //查询总数
    20.  
      func SelectcountAll() (int, error) {
    21.  
      var count int
    22.  
      err := global.DBLink.Where("isPublish=?",1).Count(&count).Error
    23.  
      if err != nil {
    24.  
      return 0, err
    25.  
      }
    26.  
      return count, nil
    27.  
      }
    28.  
      //查询多条数据
    29.  
      func SelectAllArticle(pageOffset int,pageSize int) ([]*model.Article, error) {
    30.  
      fields := []string{"articleId", "subject", "url"}
    31.  
      rows,err := global.DBLink.Select(fields).Table(model.Article{}.TableName()).Where("isPublish=?",1).Offset(pageOffset).Limit(pageSize).Rows()
    32.  
       
    33.  
      if err != nil {
    34.  
      fmt.Println("sql is error:")
    35.  
      fmt.Println(err)
    36.  
      return nil, err
    37.  
      }
    38.  
       
    39.  
      defer rows.Close()
    40.  
      var articles []*model.Article
    41.  
      for rows.Next() {
    42.  
      fmt.Println("rows.next:")
    43.  
      r := &model.Article{}
    44.  
      if err := rows.Scan(&r.ArticleId, &r.Subject, &r.Url); err != nil {
    45.  
      fmt.Println("rows.next:")
    46.  
      fmt.Println(err)
    47.  
      return nil, err
    48.  
      }
    49.  
      articles = append(articles, r)
    50.  
      }
    51.  
      return articles, nil
    52.  
      }

    6,model/article.go

    1.  
      package model
    2.  
       
    3.  
      type Article struct {
    4.  
      ArticleId int64 `gorm:"column:articleId",json:"articleId"` // 自增
    5.  
      Subject string `gorm:"column:subject",json:"title"` //
    6.  
      Url string `gorm:"column:url",json:"url"`
    7.  
      ImgUrl string `json:"imgurl"`
    8.  
      HeadUrl string `json:"headurl"`
    9.  
      }
    10.  
      //返回表名
    11.  
      func (Article) TableName() string {
    12.  
      return "article"
    13.  
      }

    7,global/db.go

    1.  
      package global
    2.  
       
    3.  
      import "github.com/jinzhu/gorm"
    4.  
       
    5.  
      var (
    6.  
      DBLink *gorm.DB
    7.  
      )
    8.  
      //连接到数据库
    9.  
      func SetupDBLink() error {
    10.  
      var err error
    11.  
      DBLink, err = gorm.Open("mysql", "root:password@tcp(127.0.0.1:3306)/dig?charset=utf8&parseTime=True&loc=Local")
    12.  
      if err == nil {
    13.  
      // 全局禁用表名复数
    14.  
      DBLink.SingularTable(true)
    15.  
      //打开sql日志
    16.  
      DBLink.LogMode(true)
    17.  
      return nil
    18.  
      } else {
    19.  
      return err
    20.  
      }
    21.  
      }

    五,测试效果

    1,一条数据:访问:

    http://127.0.0.1:8080/article/getone/1

    返回:

    2,多条数据:访问:

    http://127.0.0.1:8080/article/list?page=2

    返回:

    六,查看库的版本:

    1.  
      module github.com/liuhongdi/digv01
    2.  
       
    3.  
      go 1.15
    4.  
       
    5.  
      require (
    6.  
      github.com/gin-gonic/gin v1.6.3
    7.  
      github.com/jinzhu/gorm v1.9.16
    8.  
      )
  • 相关阅读:
    antd4.0 踩坑记录
    使用movable-view制作可拖拽的微信小程序弹出层效果。
    Taro踩坑记录一: swiper组件pagestate定制,swiperChange中setState导致组件不能滚动。
    Failed to load resource: net::ERR_INSECURE_RESPONSE 问题解决记录
    Vue-cli中使用vConsole,以及设置JS连续点击控制vConsole按钮显隐功能实现
    dvajs+antd定制主题踩坑记录
    关于iosselectjs插件设置同步值的操作实践
    《你不知道的javascript》上卷笔记整理(一)
    三次面试总结以及今后的todolist
    前端Vue中常用rules校验规则
  • 原文地址:https://www.cnblogs.com/ExMan/p/14312130.html
Copyright © 2011-2022 走看看