go编写简单接口的过程
环境
系统
Windows server 2016 Datacener
go version
go1.13.3 windows/amd64
数据库
Microsoft SQL Server 2014(64位)
基本构成
接口代码使用扩展类库
"crypto/md5"
"encoding/json"
"fmt"
_ "github.com/denisenkom/go-mssqldb"
"github.com/gin-gonic/gin"
"github.com/go-xorm/xorm"
"github.com/satori/go.uuid"
gin web框架 负责web服务器及路由请求处理
xorm和go-mssqldb 数据库对象orm处理
go.uuid 生成uuid标识
代码
main.go
package main
import (
"crypto/md5"
"encoding/json"
"fmt"
_ "github.com/denisenkom/go-mssqldb"
"github.com/gin-gonic/gin"
"github.com/go-xorm/xorm"
"github.com/satori/go.uuid"
)
func main() {
//关闭gin debug
gin.SetMode(gin.ReleaseMode)
router := gin.Default()
//提交生产api
router.POST("/test", productionOrderHandler)
//测试api是否正常访问
router.GET("/ping", func(c *gin.Context) {
c.String(200, "pong")
})
router.Run(":8080")
}
/**
获取uuid
*/
func GetUuid() string {
// or error handling
val, err := uuid.NewV4()
if err != nil {
panic("生成uuid错误:"+err.Error())
}
return val.String()
}
/**
md函数
*/
func GetMd5(str string) string {
hash := md5.New()
hash.Write([]byte(str))
result := hash.Sum([]byte(""))
return fmt.Sprintf("%x",result)
}
/**
提交生产逻辑
*/
func productionOrder(orderNo interface{}, orderMap []interface{}, booksMap []interface{}, engineDb *xorm.Engine) (bool, string) {
message := "执行成功"
//事务开启
session := engineDb.NewSession()
defer session.Close()
//4.1 pm_order表
var orderData pm_order
for _, item := range orderMap {
// 类型转换
orderItem := item.(map[string]interface{})
orderData.Key_seq = GetUuid()
//此处隐藏数据结构
if _, err := engineDb.Insert(orderData); err != nil {
session.Rollback()
message = "pm_order添加数据失败:" + err.Error()
return false, message
}
}
//4.2 pm_order表 PM_OrderStatus表 PM_OrderStatusDetail表
var bookData pm_books
var orderStatusData pm_orderstatus
var orderStatusDetailData pm_orderstatusdetail
for _, item := range booksMap {
// 类型转换
bookItem := item.(map[string]interface{})
//4.2.1 pm_order数据处理
bookData.Key_seq = GetUuid()
//此处隐藏数据结构
//4.2.2 PM_OrderStatus数据处理
orderStatusData.Orderno = bookItem["OrderNo"].(string)
//此处隐藏数据结构
//4.2.3 PM_OrderStatusDetail表
orderStatusDetailData.Orderno = bookItem["OrderNo"].(string)
//此处隐藏数据结构
if _, err := engineDb.Insert(bookData, orderStatusData, orderStatusDetailData); err != nil {
session.Rollback()
message = "pm_books/pm_orderstatus/pm_orderstatusdetail添加数据失败:" + err.Error()
return false, message
}
}
session.Commit()
return true, message
}
func productionOrderHandler(c *gin.Context) {
message := "未知错误"
//c.Request.ParseForm()
//for k, v := range c.Request.PostForm {
// fmt.Printf("%v=>%v\n", k,v)
//}
//c.String(200, message)
//return
//验证数据合法性
orderInfoJson := c.PostForm("OrderInfo")
if false {
message = "验证数据合法性失败"
c.String(200, message)
return
}
//1.获取post数据并解析
var orderInfo map[string]interface{}
// 解析字符串为Json
json.Unmarshal([]byte(orderInfoJson), &orderInfo)
//转换成map对象
orderMap := orderInfo["PM_Order"].([]interface{})
booksMap := orderInfo["PM_Books"].([]interface{})
if orderMap == nil || booksMap == nil{
message = "数据json解析失败"
c.String(200, message)
return
}
var orderNo string
for _, item := range orderMap {
// 类型转换
orderItem := item.(map[string]interface{})
orderNo = orderItem["OrderNo"].(string)
if orderNo == "" {
message = "数据json解析失败:orderno解析失败"
c.String(200, message)
return
}
}
//2 建立连接
var dbConfig = [...]string{
"127.0.0.1",
"sa",
"123456",
"test",
}
//fmt.Println(dbConfig)
//c.String(200, message)
//return
connString := fmt.Sprintf("server=%s;port%d;user id=%s;password=%s;database=%s;", dbConfig[0], 1433, dbConfig[1], dbConfig[2], dbConfig[3])
engineDb, err := xorm.NewEngine("mssql", connString)
if err != nil {
message = "连接数据库失败"
c.String(200, message)
return
}
//3 检查订单是否已提交,已提交则返回成功
has, err := engineDb.SQL("select * from PM_Order where orderNo = ?", orderNo).Exist()
if err != nil {
message = "数据查询失败"
c.String(200, message)
return
}
if has {
c.String(200, "ok")
return
}
//4.开始提交订单数据
result, errmsg := productionOrder(orderNo, orderMap, booksMap, engineDb)
if result == false {
c.String(200, errmsg)
return
}
c.String(200, "ok")
return
}
com_model.go
/**
数据库对应的struct
*/
package main
import "time"
//PM_Order表
type pm_order struct {
Key_seq string
...
}
//PM_Books表
type pm_books struct {
Key_seq string
Orderno string
...
}
//PM_OrderStatus表
type pm_orderstatus struct {
Orderno string
...
Updatetime time.Time `xorm:"created"`
}
//PM_OrderStatusDetail表
type pm_orderstatusdetail struct {
Key_seq string
...
Createtime time.Time `xorm:"created"`
}
可执行文件压缩
使用upx打压缩壳, upx 下载地址 https://upx.github.io/
编译无符号表和调试信息的可执行文件
go build -ldflags "-s -w"
调用upx压缩
upx.exe -9 ginTest.exe
go编写简单接口的过程的更多相关文章
- Hadoop基础-MapReduce入门篇之编写简单的Wordcount测试代码
Hadoop基础-MapReduce入门篇之编写简单的Wordcount测试代码 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本文主要是记录一写我在学习MapReduce时的一些 ...
- 使用Flask开发简单接口
作为测试人员,在工作或者学习的过程中,有时会没有可以调用的现成的接口,导致我们的代码没法调试跑通的情况. 这时,我们使用python中的web框架Flask就可以很方便的编写简单的接口,用于调用或调试 ...
- 【转】用systemJS+karma+Jasmine+babel环境去编写简单的ES6工程
原文链接:http://www.cnblogs.com/shuoer/p/7779131.html 用systemJS+karma+Jasmine+babel环境去编写简单的ES6工程 首先解释下什么 ...
- SLAM+语音机器人DIY系列:(二)ROS入门——6.编写简单的service和client
摘要 ROS机器人操作系统在机器人应用领域很流行,依托代码开源和模块间协作等特性,给机器人开发者带来了很大的方便.我们的机器人“miiboo”中的大部分程序也采用ROS进行开发,所以本文就重点对ROS ...
- Java开发笔记(五十八)简单接口及其实现
前面介绍了抽象方法及抽象类的用法,看似解决了不确定行为的方法定义,既然叫唤动作允许声明为抽象方法,那么飞翔.游泳也能声明为抽象方法,并且鸡类涵盖的物种不够多,最好把这些行为动作扩展到鸟类这个群体,于是 ...
- .NET Core微服务之路:利用DotNetty实现一个简单的通信过程
上一篇我们已经全面的介绍过<基于gRPC服务发现与服务治理的方案>,我们先复习一下RPC的调用过程(笔者会在这一节的几篇文章中反复的强调这个过程调用方案),看下图
- day1作业:编写登陆接口
作业一:编写登陆接口 1.输入用户名和密码 2.认证成功后显示欢迎信息 3.输错三次后锁定 思路:要求是编写登陆接口,那么要有一个存放用户信息的模块:三次后锁定,要有一个存放锁定用户信息的模块:我们知 ...
- C++编写简单的俄罗斯方块游戏
代码地址如下:http://www.demodashi.com/demo/14593.html C++编写简单的俄罗斯方块游戏 使用C++编写一个简单的俄罗斯方块游戏. 1 环境要求 使用C++图形库 ...
- 学习 Linux,101: 自定义或编写简单脚本【转】
转自:http://www.ibm.com/developerworks/cn/linux/l-lpic1-105-2/index.html 学习如何使用标准的 shell 语法.循环和控制结构,以及 ...
随机推荐
- 第二阶段:2.商业需求分析及BRD:7.商业需求文档3
BRD模版 阐述需求来源以及调研分析情况 百度指数工具.定量的数据.发展趋势,是否与公司的战略冲突.环境政策:比如做内容的运营. 决策层看重的! 第二大块. 通过什么方式解决这个需求. 规划能力.类似 ...
- 日期格式化跨年bug,是否与你不期而遇?
2020年来临之前,日期格式化操作也为程序员准备了一个跨年级别的bug,不知你的系统是否遇到? 临近2020年元旦的几天,不少网站出现了类似2020/12/29,2020/12/30,2020/12/ ...
- mysql 时间函数总结
1. 获取当前时间 select now(); // 2018-08-24 11:01:26 select unix_timestamp(); // 1535079695 总结:unix_ ...
- C# 将PDF转为Word、Html、XPS、SVG、PCL、PS——基于Spire.Cloud.PDF
Spire.Cloud.PDF提供了接口PdfConvertApi可用于将PDF文档转换为其他格式文档,如Word(docx/doc).Html.XPS.SVG.PCL.PS.Png以及XPS转成PD ...
- 用c++ 给易语言写支持库学习记录
废话我就不对说 直接开始 易语言官方下载的易语言安装路径下 有一个SDK文件夹 我们点进入cpp文件夹里面提供是c++的SDK elib文件夹里就是sdk 我们新建一个win32项目 这里我用的是VS ...
- 关于有向图走“无限次”后求概率/期望的口胡/【题解】HNCPC2019H 有向图
关于有向图走"无限次"后求概率/期望的口胡/[题解]HNCPC2019H 有向图 全是口胡 假了不管 讨论的都是图\(G=(V,E),|V|=n,|E|=m\)上的情况 " ...
- 洛谷P1020 导弹拦截 题解 LIS扩展题 Dilworth定理
题目链接:https://www.luogu.com.cn/problem/P1020 题目大意: 给你一串数,求: 这串数的最长不上升子序列的长度: 最少划分成多少个子序列是的这些子序列都是不上升子 ...
- 「洛谷P1198」 [JSOI2008]最大数 解题报告
P1198 [JSOI2008]最大数 题目描述 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值. 限制: ...
- js中getBoundingClientrRect()方法的详解
getBoundingClientRect(): 这个方法返回一个矩形对象,包含四个属性:left.top.right和buttom.分别表示元素各边与页面各边的距离 例如: var boxPosit ...
- 从零开始学asyncio(中)
本篇文章主要是讲解asyncio模块的实现原理. 这个系列还有另外两篇文章: 从零开始学asyncio(上) 从零开始学asyncio(下) 一. asyncio模块简介 asyncio是python ...