返回顶部
首页 > 资讯 > 后端开发 > GO >Go快速开发一个RESTfulAPI服务
  • 689
分享到

Go快速开发一个RESTfulAPI服务

2024-04-02 19:04:59 689人浏览 薄情痞子
摘要

目录何时使用单体 RESTful 服务商城单体 RESTful 服务单体服务实现Mall api 定义账号模块 API 定义订单模块 API 定义商品模块 API 定义生成单体服务实

何时使用单体 RESTful 服务

对于很多初创公司来说,业务的早期我们更应该关注于业务价值的交付,而单体服务具有架构简单,部署简单,开发成本低等优点,可以帮助我们快速实现产品需求。我们在使用单体服务快速交付业务价值的同时,也需要为业务的发展预留可能性,所以我们一般会在单体服务中清晰的拆分不同的业务模块。

商城单体 RESTful 服务

我们以商城为例来构建单体服务,商城服务一般来说相对复杂,会由多个模块组成,比较重要的模块包括账号模块、商品模块和订单模块等,每个模块会有自己独立的业务逻辑,同时每个模块间也会相互依赖,比如订单模块和商品模块都会依赖账号模块,在单体应用中这种依赖关系一般是通过模块间方法调用来完成。一般单体服务会共享存储资源,比如 MysqlRedis 等。

单体服务的整体架构比较简单,这也是单体服务的优点,客户请求通过 DNS 解析后通过 Nginx 转发到商城的后端服务,商城服务部署在 ECS 云主机上,为了实现更大的吞吐和高可用一般会部署多个副本,这样一个简单的平民架构如果优化好的话也是可以承载较高的吞吐的。

商城服务内部多个模块间存在依赖关系,比如请求订单详情接口 /order/detail,通过路由转发到订单模块,订单模块会依赖账号模块和商品模块组成完整的订单详情内容返回给用户,在单体服务中多个模块一般会共享数据库缓存

单体服务实现

接下来介绍如何基于 Go-zero 来快速实现商城单体服务。使用过 go-zero 的同学都知道,我们提供了一个 API 格式的文件来描述 Restful API,然后可以通过 goctl 一键生成对应的代码,我们只需要在 logic 文件里填写对应的业务逻辑即可。商城服务包含多个模块,为了模块间相互独立,所以不同模块由单独的 API 定义,但是所有的 API 的定义都是在同一个 service (mall-api) 下。

在 api 目录下分别创建 user.api, order.api, product.api 和 mall.api,其中 mall.api 为聚合的 api 文件,通过 import 导入,文件列表如下:

api
|-- mall.api
|-- order.api
|-- product.api
|-- user.api

Mall API 定义

mall.api 的定义如下,其中 syntax = “v1” 表示这是 zero-api 的 v1 语法

syntax = "v1"
import "user.api"
import "order.api"
import "product.api"

账号模块 API 定义

  • 查看用户详情
  • 获取用户所有订单
syntax = "v1"
type (
    UserRequest {
        ID int64 `path:"id"`
    }
    UserReply {
        ID      int64   `JSON:"id"`
        Name    string  `json:"name"`
        Balance float64 `json:"balance"`
    }
    UserOrdersRequest {
        ID int64 `path:"id"`
    }
    UserOrdersReply {
        ID       string `json:"id"`
        State    uint32 `json:"state"`
        CreateAt string `json:"create_at"`
    }
)
service mall-api {
    @handler UserHandler
    get /user/:id (UserRequest) returns (UserReply)
    @handler UserOrdersHandler
    get /user/:id/orders (UserOrdersRequest) returns (UserOrdersReply)
}

订单模块 API 定义

  • 获取订单详情
  • 生成订单
syntax = "v1"
type (
    OrderRequest {
        ID string `path:"id"`
    }
    OrderReply {
        ID       string `json:"id"`
        State    uint32 `json:"state"`
        CreateAt string `json:"create_at"`
    }
    OrderCreateRequest {
        ProductID int64 `json:"product_id"`
    }
    OrderCreateReply {
        Code int `json:"code"`
    }
)
service mall-api {
    @handler OrderHandler
    get /order/:id (OrderRequest) returns (OrderReply)
    @handler OrderCreateHandler
    post /order/create (OrderCreateRequest) returns (OrderCreateReply)
}

商品模块 API 定义

  • 查看商品详情
syntax = "v1"
type ProductRequest {
    ID int64 `path:"id"`
}
type ProductReply {
    ID    int64   `json:"id"`
    Name  string  `json:"name"`
    Price float64 `json:"price"`
    Count int64   `json:"count"`
}
service mall-api {
    @handler ProductHandler
    get /product/:id (ProductRequest) returns (ProductReply)
}

生成单体服务

已经定义好了 API,接下来用 API 生成服务就会变得非常简单,我们使用 goctl 生成单体服务代码。

$ goctl api go -api api/mall.api -dir .

生成的代码结构如下:

.
├── api
│   ├── mall.api
│   ├── order.api
│   ├── product.api
│   └── user.api
├── etc
│   └── mall-api.yaml
├── internal
│   ├── config
│   │   └── config.go
│   ├── handler
│   │   ├── ordercreatehandler.go
│   │   ├── orderhandler.go
│   │   ├── producthandler.go
│   │   ├── routes.go
│   │   ├── userhandler.go
│   │   └── userordershandler.go
│   ├── logic
│   │   ├── ordercreatelogic.go
│   │   ├── orderlogic.go
│   │   ├── productlogic.go
│   │   ├── userlogic.go
│   │   └── userorderslogic.go
│   ├── svc
│   │   └── servicecontext.go
│   └── types
│       └── types.go
└── mall.go

解释一下生成的代码结构:

  • api:存放 API 描述文件
  • etc:用来定义项目配置,所有的配置项都可以写在 mall-api.yaml 中
  • internal/config:服务的配置定义
  • internal/handler:API 文件中定义的路由对应的 handler 的实现
  • internal/logic:用来放每个路由对应的业务逻辑,之所以区分 handler 和 logic 是为了让业务处理部分尽可能减少依赖,把 Http requests 和逻辑处理代码隔离开,便于后续拆分成 rpc service
  • internal/svc:用来定义业务逻辑处理的依赖,我们可以在 main 函数里面创建依赖的资源,然后通过 ServiceContext 传递给 handler 和 logic
  • internal/types:定义了 API 请求和返回数据结构
  • mall.go:main 函数所在文件,文件名和 API 定义中的 service 同名,去掉了后缀 -api

生成的服务不需要做任何修改就可以运行:

$ go run mall.go
Starting server at 0.0.0.0:8888...

实现业务逻辑

接下来我们来一起实现一下业务逻辑,出于演示目的逻辑会比较简单,并非真正业务逻辑。

首先,我们先来实现用户获取所有订单的逻辑,因为在用户模块并没有订单相关的信息,所以我们需要依赖订单模块查询用户的订单,所以我们在 UserOrdersLogic 中添加对 OrderLogic 依赖

type UserOrdersLogic struct {
    logx.Logger
    ctx        context.Context
    svcCtx     *svc.ServiceContext
    orderLogic *OrderLogic
}
func NewUserOrdersLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserOrdersLogic {
    return &UserOrdersLogic{
        Logger:     logx.WithContext(ctx),
        ctx:        ctx,
        svcCtx:     svcCtx,
        orderLogic: NeWorderLogic(ctx, svcCtx),
    }
}

在 OrderLogic 中实现根据 用户id 查询所有订单的方法

func (l *OrderLogic) ordersByUser(uid int64) ([]*types.OrderReply, error) {
    if uid == 123 {
        // It should actually be queried from database or cache
        return []*types.OrderReply{
            {
                ID:       "236802838635",
                State:    1,
                CreateAt: "2022-5-12 22:59:59",
            },
            {
                ID:       "236802838636",
                State:    1,
                CreateAt: "2022-5-10 20:59:59",
            },
        }, nil
    }
    return nil, nil
}

在 UserOrdersLogic 的 UserOrders 方法中调用 ordersByUser 方法

func (l *UserOrdersLogic) UserOrders(req *types.UserOrdersRequest) (*types.UserOrdersReply, error) {
    orders, err := l.orderLogic.ordersByUser(req.ID)
    if err != nil {
        return nil, err
    }
    return &types.UserOrdersReply{
        Orders: orders,
    }, nil
}

这时候我们重新启动 mall-api 服务,在浏览器中请求获取用户所有订单接口

http://localhost:8888/user/123/orders

返回结果如下,符合我们的预期

{
    "orders": [
        {
            "id": "236802838635",
            "state": 1,
            "create_at": "2022-5-12 22:59:59"
        },
        {
            "id": "236802838636",
            "state": 1,
            "create_at": "2022-5-10 20:59:59"
        }
    ]
}

接下来我们再来实现创建订单的逻辑,创建订单首先需要查看该商品的库存是否足够,所以在订单模块中需要依赖商品模块。

type OrderCreateLogic struct {
    logx.Logger
    ctx    context.Context
    svcCtx *svc.ServiceContext
    productLogic *ProductLogic
}
func NewOrderCreateLogic(ctx context.Context, svcCtx *svc.ServiceContext) *OrderCreateLogic {
    return &OrderCreateLogic{
        Logger:       logx.WithContext(ctx),
        ctx:          ctx,
        svcCtx:       svcCtx,
        productLogic: NewProductLogic(ctx, svcCtx),
    }
}

创建订单的逻辑如下

const (
    success = 0
    failure = -1
)
func (l *OrderCreateLogic) OrderCreate(req *types.OrderCreateRequest) (*types.OrderCreateReply, error) {
    product, err := l.productLogic.productByID(req.ProductID)
    if err != nil {
        return nil, err
    }
    if product.Count > 0 {
        return &types.OrderCreateReply{Code: success}, nil
    }
    return &types.OrderCreateReply{Code: failure}, nil
}

依赖的商品模块逻辑如下

func (l *ProductLogic) Product(req *types.ProductRequest) (*types.ProductReply, error) {
    return l.productByID(req.ID)
}
func (l *ProductLogic) productByID(id int64) (*types.ProductReply, error) {
    return &types.ProductReply{
        ID:    id,
        Name:  "apple watch 3",
        Price: 3333.33,
        Count: 99,
    }, nil
}

以上可以看出使用 go-zero 开发单体服务还是非常简单的,有助于我们快速开发上线,同时我们还做了模块的划分,为以后做微服务的拆分也打下了基础。

总结

通过以上的示例可以看出使用 go-zero 实现单体服务非常简单,只需要定义 api 文件,然后通过 goctl 工具就能自动生成项目代码,我们只需要在logic中填写业务逻辑即可,这里只是为了演示如何基于 go-zero 快速开发单体服务并没有涉及数据库和缓存的操作,其实我们的 goctl 也可以一键生成 CRUD 代码和 cache 代码,对于开发单体服务来说可以起到事半功倍的效果。

并且针对不同的业务场景,定制化的需求也可以通过自定义模板来实现,还可以在团队内通过远程 git 仓库共享自定义业务模板,可以很好的实现团队协同。

项目地址 GitHub.com/zeromicro/g…

以上就是Go快速开发一个RESTful API服务的详细内容,更多关于Go开发RESTful API服务的资料请关注编程网其它相关文章!

您可能感兴趣的文档:

--结束END--

本文标题: Go快速开发一个RESTfulAPI服务

本文链接: https://lsjlt.com/news/152119.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Go快速开发一个RESTfulAPI服务
    目录何时使用单体 RESTful 服务商城单体 RESTful 服务单体服务实现Mall API 定义账号模块 API 定义订单模块 API 定义商品模块 API 定义生成单体服务实...
    99+
    2024-04-02
  • 如何快速开发一个Webpack Loader
    本篇内容主要讲解“如何快速开发一个Webpack Loader”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何快速开发一个Webpack Loader”吧!L...
    99+
    2024-04-02
  • 用Go+WebSocket快速实现一个chat服务
    前言 在 go-zero 开源之后,非常多的用户询问是否可以支持以及什么时候支持 websocket,终于在 v1.1.6 里面我们从框架层面让websocket 的支持落地了,下...
    99+
    2024-04-02
  • 如何快速开发一个小程序
    本文小编为大家详细介绍“如何快速开发一个小程序”,内容详细,步骤清晰,细节处理妥当,希望这篇“如何快速开发一个小程序”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。  注册小程序账号,下载IDE  官方文档一向都是...
    99+
    2023-06-26
  • 用Go+WebSocket快速实现一个chat服务
    前言 在 go-zero 开源之后,非常多的用户询问是否可以支持以及什么时候支持 websocket,终于在 v1.1.6 里面我们从框架层面让websocket 的支持落地...
    99+
    2022-06-07
    GO chat websocket
  • 如何快速搭建一个Java开发环境
    如何快速搭建一个Java开发环境?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。Java开发环境配置(win7-64bit)1.概述搭建Java开发环境一般需要同...
    99+
    2023-05-31
    java ava
  • 如何快速搭建一个Android开发环境
    这篇文章将为大家详细讲解有关如何快速搭建一个Android开发环境,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。一、安装JDK安装JavaJDK的路径:C:\Java\jdk1.7.0_80...
    99+
    2023-05-31
    android roi
  • 怎么使用Go+WebSocket快速实现一个chat服务
    这篇文章将为大家详细讲解有关怎么使用Go+WebSocket快速实现一个chat服务,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。前言在 go-zero 开源之后,非常多的用户询问是否可以支持以及什么时候...
    99+
    2023-06-14
  • go doudou开发单体RESTful服务快速上手教程
    目录引言需求清单学习目标开发环境准备安装go-doudou初始化工程定义接口生成代码启动服务数据库和表结构准备生成domain和dao层代码用户注册接口修改domainPublicS...
    99+
    2022-12-08
    go doudou单体RESTful服务 go doudou教程
  • 介绍一个软件开发工具,堪称快速开发神器
    软件快速开发平台是一种软件开发工具,以通用技术架构(如MVC)为基础,集成常用建模工具、二次开发包、基础解决方案等而成。可以大幅缩减编码率,使开发者有更多时间关注客户需求,在项目的需求、设计、开发、测试、部署、维护等各个阶段均可提供强大的支...
    99+
    2023-06-03
  • 如何快速搭建一个Android开发测试平台
      初学Android,以便记录学习过程,增强学习效果。   1. 下载搭建android开发平台的必要工具   1) Jdk1.6 -http://www.ora...
    99+
    2022-06-06
    android开发 测试 Android
  • 推荐一款快速开发平台,web中最好的快速开发平台
    力软快速开发平台是力软自主开发的基于SOA面向服务的应用系统开发平台,可以方便快捷的搭建企业、医院、工厂、学校等行业的企业级运营管理平台。平台采用.net.技术架构,webapi服务搭建。 力软...
    99+
    2024-04-02
  • Linux开发:快速开发游戏的9个关键!
    根据在游戏开发和游戏开发方面的经验,陕西优就业小编整理了条条关于游戏引擎、编码和快速游戏开发的经验教训。快来看看吧!1、限定规模很容易想要去做一个规模宏大的冒险游戏或者可以比拟你最喜欢的游戏的东西。如果你有一些经验,追求超乎游戏 Jam 活...
    99+
    2023-06-05
  • Go语言开发快速学习CGO编程
    目录快速上手 CGO 程序基于 C 标准库实现最简单的 CGO 程序基于自己写的 C 函数构建 CGO 程序模块化以上例子用 Go 实现 C 函数并导出用 C 接口的方式实现 Go ...
    99+
    2023-05-14
    Go语言开发CGO编程 CGO编程
  • 【Python】快速创建一个简易 HTTP 服务器(http.server)
    引言 http.server 是 socketserver.TCPServer 的子类,它在 HTTP 套接字上创建和监听,并将请求分派给处理程序。本文是关于如何使用 Python 的 http.s...
    99+
    2023-09-28
    python http server
  • 一个稳定、快速的云服务器——萤光云
    目录 一、服务器商简介         1.1、品牌介绍         1.2、服务商官网         1.3、服务器价格&简介 二、服务器基本信息         2.1、CPU         2.2、内存 三...
    99+
    2023-09-06
    服务器 运维 php linux centos
  • 如何通过nodejs快速搭建一个服务器
            在前端开发过程中,可能某些时候需要自己搭建一台服务器用于一些文件图片请求或者进行后端相关知识的学习。本文主要讲解如何通过nodejs进行一个基础服务器的搭建,包括如何将文件布置的服务器,以及基础接口的开发。后面可能会更新关于...
    99+
    2023-09-01
    前端 javascript 开发语言 node.js
  • “Go语言实时开发技术:如何快速掌握?”
    Go语言是一种相对年轻的编程语言,由于其高效、高并发、易于学习等优点,越来越多的开发者开始使用它来开发各种应用程序。但是,对于初学者来说,Go语言的学习曲线可能比较陡峭,需要一些实时开发技巧来帮助他们快速掌握这门语言。 本文将介绍一些Go语...
    99+
    2023-10-23
    教程 开发技术 实时
  • 解析Go语言微服务开发的关键步骤,助您快速入门
    快速入门Go语言微服务开发的关键步骤解析 随着云计算和大数据时代的到来,微服务架构(Microservices Architecture)也成为了一种流行的架构模式。Go语言作为一种效率高、性能强、并发能力突...
    99+
    2024-01-23
    入门:快速 语言:Go 开发:微服务
  • godoudou开发gRPC服务快速上手实现详解
    目录引言准备安装go安装gRPC编译器和插件安装编译器protoc安装插件安装go-doudou初始化项目定义服务生成代码实现接口测试服务总结引言 go-doudou从v2版本开...
    99+
    2022-12-08
    go doudou开发gRPC服务 go gRPC
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作