环境

系统

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编写简单接口的过程的更多相关文章

  1. Hadoop基础-MapReduce入门篇之编写简单的Wordcount测试代码

    Hadoop基础-MapReduce入门篇之编写简单的Wordcount测试代码 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本文主要是记录一写我在学习MapReduce时的一些 ...

  2. 使用Flask开发简单接口

    作为测试人员,在工作或者学习的过程中,有时会没有可以调用的现成的接口,导致我们的代码没法调试跑通的情况. 这时,我们使用python中的web框架Flask就可以很方便的编写简单的接口,用于调用或调试 ...

  3. 【转】用systemJS+karma+Jasmine+babel环境去编写简单的ES6工程

    原文链接:http://www.cnblogs.com/shuoer/p/7779131.html 用systemJS+karma+Jasmine+babel环境去编写简单的ES6工程 首先解释下什么 ...

  4. SLAM+语音机器人DIY系列:(二)ROS入门——6.编写简单的service和client

    摘要 ROS机器人操作系统在机器人应用领域很流行,依托代码开源和模块间协作等特性,给机器人开发者带来了很大的方便.我们的机器人“miiboo”中的大部分程序也采用ROS进行开发,所以本文就重点对ROS ...

  5. Java开发笔记(五十八)简单接口及其实现

    前面介绍了抽象方法及抽象类的用法,看似解决了不确定行为的方法定义,既然叫唤动作允许声明为抽象方法,那么飞翔.游泳也能声明为抽象方法,并且鸡类涵盖的物种不够多,最好把这些行为动作扩展到鸟类这个群体,于是 ...

  6. .NET Core微服务之路:利用DotNetty实现一个简单的通信过程

    上一篇我们已经全面的介绍过<基于gRPC服务发现与服务治理的方案>,我们先复习一下RPC的调用过程(笔者会在这一节的几篇文章中反复的强调这个过程调用方案),看下图

  7. day1作业:编写登陆接口

    作业一:编写登陆接口 1.输入用户名和密码 2.认证成功后显示欢迎信息 3.输错三次后锁定 思路:要求是编写登陆接口,那么要有一个存放用户信息的模块:三次后锁定,要有一个存放锁定用户信息的模块:我们知 ...

  8. C++编写简单的俄罗斯方块游戏

    代码地址如下:http://www.demodashi.com/demo/14593.html C++编写简单的俄罗斯方块游戏 使用C++编写一个简单的俄罗斯方块游戏. 1 环境要求 使用C++图形库 ...

  9. 学习 Linux,101: 自定义或编写简单脚本【转】

    转自:http://www.ibm.com/developerworks/cn/linux/l-lpic1-105-2/index.html 学习如何使用标准的 shell 语法.循环和控制结构,以及 ...

随机推荐

  1. .net core允许跨域

    // 设置允许所有来源跨域 app.UseCors(options => { options.AllowAnyHeader(); options.AllowAnyMethod(); option ...

  2. ELK学习实验009:安装kibana的仪表盘

    一 metricbeat仪表盘 1.1 安装metricbeat仪表盘 可以将metricbeat数据在kibana中展示 [root@node4 ~]# cd /usr/local/metricbe ...

  3. Java动态代理 ----- jdk代理与cglib代理

    1.jdk代理 针对接口进行代理,接口可以没有方法, InvocationHandler会拦截所有方法,不过好像意义不大....只能执行Object类的方法,执行结果有点奇怪... package t ...

  4. 浅谈Redis的基本原理和数据类型结构的特性和应用开发场景

    一.Redis介绍 1,redis介绍(Redis安装在磁盘:Redis数据存储在内存) redis是一种基于键值对(key-value)数据库,其中value可以为string.hash.list. ...

  5. xshell连接不上ubuntu---could not connect to 'ip' (port 22): Connection failed.

    可能是没有开启ssh server,接下来就是开启服务就好.命令如下: sudo apt-get install openssh-server 这样就OK啦

  6. 洛谷$P2523\ [HAOI2011]\ Problem\ c$ $dp$

    正解:$dp$ 解题报告: 传送门$QwQ$ 首先港下不合法的情况.设$sum_i$表示$q\geq i$的人数,当且仅当$sum_i>n-i+1$时无解. 欧克然后考虑这题咋做$QwQ$. 一 ...

  7. $Noip2011/Luogu1311$ 选择客栈

    $Luogu$ $Sol$ 暴力十分显然叭.正解不是很好想. 我最开始想维护所有色调的客栈的前缀和后缀,然后每扫到一个最低消费合法的就统计一次答案.但是这样会重复计数,两个合法客栈之间有几个消费合法的 ...

  8. 力扣208——实现 Trie (前缀树)

    这道题主要是构造前缀树节点的数据结构,帮助解答问题. 原题 实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作. 示例: Trie trie = ...

  9. C++指针声明

    指针声明 void f(int) void (*p1)(int)=&f; void (*p2)(int)=f; 调用例子: int f(); int (*p) ()=f; //指针p指向f i ...

  10. Java面向对象之异常详解

    目录 Java面向对象之异常[一] Java面向对象之异常[二] 捕获异常的规则 访问异常信息 异常对方法重写的影响 finally详解 Java面向对象之异常[一] Java面向对象之异常[二] 往 ...