Go项目(商品微服务-1)

news/2024/4/20 13:30:59/文章来源:https://blog.csdn.net/weixin_39757637/article/details/129222068

文章目录

  • 简介
  • 建表
  • proto
  • handler
    • 商品
  • 小结

简介

  • 商品微服务主要在于表的设计,建哪些表?表之间的关系是怎样的?
    • 主要代码就是 CURD
    • 表和字段的设计是一个比较有挑战性的工作,比较难说清楚,也需要经验的积累,这里关注点在微服务,暂时先 “借鉴” 别人的设计
    • 一般需要多次迭代才能设计出比较合理的表结构
  • 我们将商品相关的服务都放在这部分,方便建表和管理;微服务并不是越多越好,分成太多服务可能会让系统太复杂难以管理
    • 如何划分微服务需要积累经验,也有针对性的方法可以套用,需要单独学习

建表

  • 新建商品微服务 Service 层,直接把 user_srv 的目录拷过来,整体替换相关路径
    1
  • 表设计及相关操作,主要有四张表
    2
  • 放个商品表的结构
    // 商品表
    // 某一个具体的商品
    type Goods struct {BaseModelCategoryID int32    `gorm:"type:int;not null"`Category   Category // 一对多/一对一BrandsID   int32    `gorm:"type:int;not null"`Brands     Brands   // 一对一OnSale   bool `gorm:"default:false;not null"`ShipFree bool `gorm:"default:false;not null"`IsNew    bool `gorm:"default:false;not null"`IsHot    bool `gorm:"default:false;not null"`Name            string   `gorm:"type:varchar(50);not null"`GoodsSn         string   `gorm:"type:varchar(50);not null"`ClickNum        int32    `gorm:"type:int;default:0;not null"`SoldNum         int32    `gorm:"type:int;default:0;not null"`FavNum          int32    `gorm:"type:int;default:0;not null"`MarketPrice     float32  `gorm:"not null"`ShopPrice       float32  `gorm:"not null"`GoodsBrief      string   `gorm:"type:varchar(100);not null"`Images          GormList `gorm:"type:varchar(1000);not null"`DescImages      GormList `gorm:"type:varchar(1000);not null"`GoodsFrontImage string   `gorm:"type:varchar(200);not null"`
    }
    
  • 对字段的限制一般都要求 not null,也就是必须有值,然后限制用户必须输入或者我们设置 default
    • 设置为 null 带来的问题
  • 定义 model
    • 注意表之间的关联关系,查看 gorm 文档了解使用方式
  • 生成表结构
    • 新建数据库,直接在(109.128)机器上操作,方便启动项目
    • CREATE DATABASE IF NOT EXISTS shop_goods_srv DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
    • 一个微服务对应一个数据库,要和其他微服务隔离开
    • 还是在 model/main 下面运行一次 main 方法即可
      4
    • 运行 sql 文件,导入数据;将上面创建的表结构全部删掉(不删也行),因为 SQL 文件里包含了建表语句
      3

proto

  • proto 文件的设计又是一个重点,首先要根据页面进行需求分析(前端页面和后台管理页面),需要哪些接口?传递哪些参数?会有什么响应?
  • 接口定义也不是一蹴而就的,后面可能会修改,不必在一开始追求完美
  • protoc -I . goods.proto --go_out=plugins=grpc:. 生成 stub 文件
    • 遇到点小问题,empty.proto 找不到,拷过来放到 proto/google/protobuf 下面试试
  • 定义 Service 层(Server端)接口(handler),直接搜 GoodsServer,将接口定义拷过来
    • 这里接口太多,我们分在不同 handler 文件实现,不着急实现,先把接口定义拷过去修改一下引用,因为没有实现的话项目无法启动,
    • 再修改 main.go 和 nacos 配置文件(本地/中心配置),启动项目看能否注册成功
      1

handler

  • 具体实现各接口,先从品牌和轮播图开始,这里放个获取品牌列表的例子
    // 品牌
    func (s *GoodsServer) BrandList(ctx context.Context, req *proto.BrandFilterRequest) (*proto.BrandListResponse, error) {brandListResponse := proto.BrandListResponse{}var brands []model.Brands// 分页:第几页,每页数量// Scopes 需要传一个匿名函数进去,在里面做一些判断并查询数据result := global.DB.Scopes(Paginate(int(req.Pages), int(req.PagePerNums))).Find(&brands)if result.Error != nil {return nil, result.Error}var total int64global.DB.Model(&model.Brands{}).Count(&total) // 单独再获取一次品牌总数brandListResponse.Total = int32(total)// 准备响应数据,单个品牌的BrandInfoResponse 和品牌列表的 brandListResponse,要根据 proto 定义的 message 安排好var brandResponses []*proto.BrandInfoResponsefor _, brand := range brands {brandResponses = append(brandResponses, &proto.BrandInfoResponse{Id:   brand.ID,Name: brand.Name,Logo: brand.Logo,})}brandListResponse.Data = brandResponsesreturn &brandListResponse, nil
    }
    
  • 回答一个上一篇的问题:查询数据时不传表名,传入 model 定义的 struct 就可以吗?
    • 是的,比如 DB.First(&model.Brands{}),因为 struct 名就是表名,改表名也是通过绑在 struct 上的函数进行的
  • 商品分类
    • 先看 GetAllCategorysList,这里比较 tricky,因为有多级分类,需要同时查询两级 subCategory
    • 我们希望得到的数据格式
      [{"id":xxx,"name":"","level":1,"is_tab":false,"parent":13xxx,"sub_category":["id":xxx,"name":"","level":1,"is_tab":false,"sub_category":["id":xxx,"name":"",]]}
      ]
      
    • 通过 gorm 提供的预加载(反向查询)实现
    • 条件查询一级目录:global.DB.Where(&model.Category{Level: 1})
    • 反向查询两级子类目:Preload("SubCategory.SubCategory")
    • 再贴一个获取子分类的函数,grpc 的接口实现都是三步走
      // 获取子分类,传入一级或二级类别ID
      func (s *GoodsServer) GetSubCategory(ctx context.Context, req *proto.CategoryListRequest) (*proto.SubCategoryListResponse, error) {// 1.准备返回值categoryListResponse := proto.SubCategoryListResponse{} // total, info(parent), sub// 2.根据请求参数查询数据+判空var category model.Categoryif result := global.DB.First(&category, req.Id); result.RowsAffected == 0 {return nil, status.Errorf(codes.NotFound, "商品分类不存在")}// 3.填充返回值各字段-InfocategoryListResponse.Info = &proto.CategoryInfoResponse{Id:             category.ID,Name:           category.Name,Level:          category.Level,IsTab:          category.IsTab,ParentCategory: category.ParentCategoryID,}var subCategorys []model.Categoryvar subCategoryResponse []*proto.CategoryInfoResponse// 如果要获取三级子分类,默认获取下面一级//preloads := "SubCategory"//if category.Level == 1 {//	preloads = "SubCategory.SubCategory"//}// 只有在一级时才有获取三级的需求,但是这里没必要,这里把这个接口做的小一点,限制在只获取下一级,需要三级的话再在二级一一请求global.DB.Where(&model.Category{ParentCategoryID: req.Id}).Find(&subCategorys)for _, subCategory := range subCategorys {subCategoryResponse = append(subCategoryResponse, &proto.CategoryInfoResponse{Id:             subCategory.ID,Name:           subCategory.Name,Level:          subCategory.Level,IsTab:          subCategory.IsTab,ParentCategory: subCategory.ParentCategoryID,})}// 3.填充返回值各字段-SubCategoryscategoryListResponse.SubCategorys = subCategoryResponsereturn &categoryListResponse, nil
      }
      
    • 这里需要写接口测试,可以在 test 目录写 UT 或者每个 handler 新建目录在 main 函数运行看效果(一个目录下只能有一个main)
  • 品牌分类
    • 查询品牌和分类数据表,这是个中间表,内容较多,相关操作也较为复杂一点
      5
    • model 定义如下
      type GoodsCategoryBrand struct {BaseModelCategoryID int32    `gorm:"type:int;index:idx_category_brand,unique"` // 外键Category   Category // 外键约束,约束谁就指向谁BrandsID int32 `gorm:"type:int;index:idx_category_brand,unique"` // 外键Brands   Brands
      }
      
  • 这些接口都是给 web 层调用,但有的是给用户准备数据,有的是给后台管理员准备

商品

  • 商品接口,关系到最终展示给用户的数据,最重要
  • 注:这部分有很多入口:搜索、新品、热门、价格区间、商品分类,都需要调用接口获取对应商品,这些都可以看做是查询条件
  • 注意下面几点
    • 条件是可以叠加的,所有用 localDB 接收前面过滤出的数据体
    • 分类条件要考虑层级
  • 后续会集成 elastic 用于搜索

小结

  • 快速开发了商品微服务的 Service 层,服务配置项还是和 user_srv 相同,包括 nacos,mysql,consul,serverConfig,不需要更改定义
  • 接下来是商品微服务 API 层的快速开发

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

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

相关文章

【机器学习笔记】Python基础笔记

目录基础语法加载数据:pd.read_csv查看数据大小:shape浏览数据行字段:columns浏览少量数据:head()浏览数据概要:describe()输出:to_csv基础功能语法缺省值去除缺失值:dropna按行删除&#xff1a…

Paddle配置

目录: 1.激活环境 2.版本选择 突发情况:ModuleNotFoundError: No module named paddle 检验是否安装成功 1.激活环境 Anaconda: conda remove -n paddle --all conda activate paddle 2.版本选择 打开链接:https://www.pa…

基于企业微信应用消息的每日早安推送

基于企业微信应用消息的每日早安推送 第一步:注册企业微信 企业微信注册地址:https://work.weixin.qq.com/wework_admin/register_wx 按照正常流程填写信息即可,个人也可以注册企业微信,不需要公司 注册完成后,登录…

Google Guice 4:Bindings(2)

4 Scopes (实例的作用域) 4.1 默认规则:unreuse instance 到目前为止,通过bind().to()和Provides定义的binding,每次需要注入实例对象时,Guice都会创建一个新的实例 // 修改DatabaseTransactionLog,使其打…

Ncvicat 打开sql文件方法

Nacicat打开sql文件时,有比较多的文章介绍可以直接打开,方法介绍的比较多,但是我遇到了一个坑,就是如何配置环境都无法打开。 本机环境: windows10 mysql 5.7.40 Navicat12.1 一、遇到问题情况 1.1、通过navicat…

【python量化】大幅提升预测性能,将NSTransformer用于股价预测

写在前面 NSTransformer模型来自NIPS 2022的一篇paper《Non-stationary Transformers: Exploring the Stationarity in Time Series Forecasting》。NSTransformer的目的主要是为了解决其他方法出现过平稳化处理的问题。其通过提出序列平稳化以及去平稳化注意力机制可以使得模型…

2023年三月份图形化二级打卡试题

活动时间 从2023年3月1日至3月21日,每天一道编程题。 本次打卡的规则如下: 小朋友每天利用10~15分钟做一道编程题,遇到问题就来群内讨论,我来给大家答疑。 小朋友做完题目后,截图到朋友圈打卡并把打卡的截图发到活动群…

【尚硅谷MySQL入门到高级-宋红康】数据库概述

1、为什么要使用数据库 数据的持久化 2、数据库与数据库管理系统 2.1 数据库的相关概念 2.2 数据库与数据库管理系统的关系 3、 MySQL介绍 MySQL从5.7版本直接跳跃发布了8.0版本 ,可见这是一个令人兴奋的里程碑版本。MySQL 8版本在功能上做了显著的改进与增强&a…

CXL技术分析

CXL,全称Compute Express Link,该技术由Intel牵头开发用于高性能计算、数据中心,主要解决处理器、加速器和内存之间的cache一致性问题,可消除CPU、专用加速器的计算密集型工作负载的传输瓶颈,显著提升系统性能。 一、…

python的装饰器与设计模式中的装饰器模式

相信很多人在初次接触python中的装饰器时,会跟我一样有个疑问,这跟设计模式中的装饰器模式有什么区别吗?本质上是一样的,都是对现有对象,包括函数或者类的一种扩展。这篇文档将进行对比分析。 python的装饰器 装饰器…

duboo+zookeeper分布式架构入门

分布式 dubbo Zookeeper 分布式系统就是若干独立计算机的集合(并且这些计算机之间相互有关联,就像是一台计算机中的C盘F盘等),这些计算对于用户来说就是一个独立的系统。 zookeeper安装 下载地址:Index of /dist/z…

【数据库系统概论】基础知识总结

🌹作者:云小逸 📝个人主页:云小逸的主页 📝Github:云小逸的Github 🤟motto:要敢于一个人默默的面对自己,强大自己才是核心。不要等到什么都没有了,才下定决心去做。种一颗树,最好的时间是十年前…

C++10:非类型模板参数以及模板的特化

目录 非类型模板参数 模板的特化 模板类的特化 1.全特化 2.偏特化 模板其实还有其他的玩法&#xff0c;比如非类型模板参数以及模板的特化。 非类型模板参数 在记述非类型模板参数前&#xff0c;我们认识一下C中一个比较鸡肋的类&#xff0c;array #include<iostream&g…

k8s-yaml文件

文章目录一、K8S支持的文件格式1、yaml和json的主要区别2、YAML语言格式二、YAML1、查看 API 资源版本标签2、编写资源配置清单2.1 编写 nginx-test.yaml 资源配置清单2.2 创建资源对象2.3 查看创建的pod资源3、创建service服务对外提供访问并测试3.1 编写nginx-svc-test.yaml文…

数据仓库Hive

HIve介绍 Hive是建立在Hadoop上的数据仓库基础构架。它提供了一系列的工具&#xff0c;可以用来进行数据提取转化加载&#xff0c;可以简称为ETL。 Hive 定义了简单的类SQL查询语言&#xff0c;称为HQL&#xff0c;它允许熟悉SQL的用户直接查询Hadoop中的数据&#xf…

如何从0创建Spring Cloud Alibaba(多模块)

以一个父工程带两个Module&#xff08;test1、test2&#xff09;为例。 一、创建父工程 由于是模块化项目&#xff0c;那么父工程不需要实际的代码逻辑&#xff0c;因此无需创建src&#xff0c;那么可以有几种方式创建&#xff0c;例如&#xff1a; 使用Spring Initializr脚…

腾讯一面—Android 系统启动流程详解

正文AMS 是 Android 中最核心的服务之一&#xff0c;主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作&#xff0c;其职责与操作系统中的进程管理和调度模块相类似&#xff0c;它本身也是一个 Binder 的实现类&#xff0c;应用进程能通过 Binder 机制调用…

ARM Context synchronization event和Instruction Synchronization Barrier

在Arm architecture里&#xff0c;经常提到Context synchronization event(CSE)和Explicit synchronization&#xff0c;Context synchronization events在之前是叫作context synchronization operations。Explicit synchronization是Context synchronization event的结果&…

基于yolov5与改进VGGNet的车辆多标签实时识别算法

摘 要 为了能快速、有效地识别视频中的车辆信息&#xff0c;文中结合YOLOv3算法和CNN算法的优点&#xff0c;设计了一种能实时识别车辆多标签信息的算法。首先&#xff0c;利用具有较高识别速度和准确率的YOLOv3实现对视频流中车辆的实时监测和定位。在获得车辆的位置信息后…

如何提高机器人专业课讲师的收入

先放一些总结&#xff1a;为什么我是不合格的高校机器人工程专业讲师&#xff1f;2020不合格肯定收入不会提升&#xff0c;甚至失业风险会非常高的。为何所做的课程努力几乎全部失败呢&#xff1f;→机器人工程类← 2022不能一次次失败&#xff0c;因为只有自己会为失败买单&am…