golang gin框架实例

一直用postman测试接口,用golang写接口性能测试的testcase,还从未自己动手写过gin框架,利用稍空闲的时间研究了gin的框架,参考之前测试过的研发童鞋写的gin框架项目代码,简单写了一套自己的框架,希望以后可以用在以后的测试中

背景:模拟项目的设备(device)的入库和查询

先看我的基本框架:

在这里插入图片描述

controller:是我的接口
dao:是db的操作
model:封装的数据模型
server:是我的组路由服务
middlewear:中间件

步骤:

1.models

package models

import(
	"aiotdevice/dao"
)
type Resp struct{
	Code int
	Msg string
	Data dao.DeviceInfo
}

2…数据库服务

package dao

import (
	"github.com/jinzhu/gorm"
	"fmt"
	_ "github.com/jinzhu/gorm/dialects/mysql"

)


type DeviceInfo struct{
	Mac string `gorm:column:mac`
	Sn string `gorm:column:sn`
	Model string `gorm:column:model`
	Device_id string `gorm:column:device_id`
}

var dataBase = "root:123456@unix(/var/run/mysqld/mysqld.sock)/"

func openDb() *gorm.DB {
	db, err := gorm.Open("mysql", dataBase+"?charset=utf8&parseTime=True&loc=Local")
	//defer db.Close()
	if err != nil {
		fmt.Println(err)
		panic("连接数据库失败")
	}
	db.SingularTable(true)
	db.LogMode(false)
	return db
}
func (D *DeviceInfo)InsertDB() {
	DB :=openDb()
	defer DB.Close()
	DB.Exec("insert into concurrent_test.device set mac=?,sn=?,model=?,device_id=?",D.Mac,D.Sn,D.Model,D.Device_id )
	if DB.Error != nil {
		fmt.Println(DB.Error)
		panic("insert db fail")
	}
}

func (D *DeviceInfo)GetdevByDeviceid() DeviceInfo{
	// 删除数据
	db:=openDb()
	var Devices DeviceInfo
	sql := "select mac,sn,device_id,model from concurrent_test.device where device_id="+"\""+D.Device_id+"\""
	fmt.Println(sql)
	db.Raw(sql).Scan(&Devices)
	db.Close()
	fmt.Println(Devices)
	return Devices
}
func (D *DeviceInfo)GetdevByMac() DeviceInfo{
	// 删除数据
	db:=openDb()
	var Devices DeviceInfo
	sql := "select mac,sn,device_id,model from concurrent_test.device where mac="+"\""+D.Mac+"\""
	fmt.Println(sql)
	db.Raw(sql).Scan(&Devices)
	db.Close()
	fmt.Println(Devices)
	fmt.Println(sql)

	return Devices
}
func (D *DeviceInfo)GetdevBySn() DeviceInfo{
	// 删除数据
	db:=openDb()
	var Devices DeviceInfo
	sql := "select mac,sn,device_id,model from concurrent_test.device where sn="+"\""+D.Sn+"\""
	fmt.Println(sql)
	db.Raw(sql).Scan(&Devices)
	db.Close()
	fmt.Println(Devices)
	return Devices
}

3.接口


 package controller

 import (
	 "github.com/gin-gonic/gin"
	//  "net/http"
	 "aiotdevice/dao"
)


//get postform and url param
 func Adddeviceapi(c *gin.Context){
    mac := c.PostForm("mac")
	sn := c.PostForm("sn")
	model := c.PostForm("model")
    device_id := c.PostForm("device_id")
    if mac == "" && sn =="" && model =="" && device_id ==""{
        c.JSON(300, gin.H{"code":30000,"msg":"need parameter"})
    }else{
		dev:=dao.DeviceInfo{
			Mac : mac,
			Sn:sn,
			Model:model,
			Device_id:device_id,
		}
		dev.InsertDB()
		c.JSON(200, gin.H{"code":10000,"msg":"OK"})
	}
}

注意看源码“ type H map[string]interface{}” H是一个map

package controller

import (
	"github.com/gin-gonic/gin"
	// "net/http"
	"aiotdevice/dao"
	"aiotdevice/models"



)

// type Resp struct{
// 	Code int
// 	Msg string
// 	Data dao.DeviceInfo
// }

func Getdeviceapi(c *gin.Context){
    mac := c.Query("mac")
    sn := c.Query("sn")
	model  := c.Query("model")
	device_id  := c.Query("device_id")

	dev:=dao.DeviceInfo{
		Mac : mac,
		Sn:sn,
		Model:model,
		Device_id:device_id,
	}
	var temp dao.DeviceInfo

	if dev.Mac == "" && dev.Sn =="" &&  dev.Device_id ==""{
        c.JSON(300, gin.H{"code":30000,"msg":"need parameter"})
    }else{
		if dev.Mac !=""{
			temp=dev.GetdevByMac()
			resp := models.Resp{
				Code:10000,
				Msg:"ok",
				Data:temp,
			}
			c.JSON(200, gin.H{"code":resp.Code,"msg":resp.Msg,"data":resp.Data})
		}
		if dev.Sn !=""{
			temp=dev.GetdevBySn()
			resp := models.Resp{
				Code:10000,
				Msg:"ok",
				Data:temp,
			}
			c.JSON(200, gin.H{"code":resp.Code,"msg":resp.Msg,"data":resp.Data})
		}
		if dev.Device_id !=""{
			temp=dev.GetdevByDeviceid()
			resp := models.Resp{
				Code:10000,
				Msg:"ok",
				Data:temp,
			}
			c.JSON(200, gin.H{"code":resp.Code,"msg":resp.Msg,"data":resp.Data})
		}
	}
}

注意接收参数的姿势:
form 过来的用PostForm()
query 过来的用Query()
url 的param用Param()
file 文件过来的用 FormFile()

4.组服务

package server

import (


	 "aiotdevice/controller"
	mw "aiotdevice/middlewear"
	"github.com/gin-gonic/gin"
)
func DeviceServer() {
	root := "aiot/v1"
	// Engin
	gin.SetMode(gin.ReleaseMode)
	router := gin.Default() //new()*Engine

	router.Use(mw.Cors())//中间件在组路由之前启动

	_index := router.Group(root)
	{
		_index.GET("/device", controller.Getdeviceapi)  
		_index.POST("/device", controller.Adddeviceapi)
	}
	// // 指定地址和端口号
	// apidoc.RouterInfos(router, root, "dev")
	// // _ = router.Run(":9111")
	// _ = router.Run()


	go router.Run()
	// check.Check()
}

5.中间件:

package middlewear

import (
	"github.com/gin-gonic/gin"
	"strings"
	"fmt"
    "net/http"
)


func Cors() gin.HandlerFunc {
    return func(c *gin.Context) {
        method := c.Request.Method      //请求方法
        origin := c.Request.Header.Get("Origin")        //请求头部
        var headerKeys []string                             // 声明请求头keys
        for k, _ := range c.Request.Header {
            headerKeys = append(headerKeys, k)
        }
        headerStr := strings.Join(headerKeys, ", ")
        if headerStr != "" {
            headerStr = fmt.Sprintf("access-control-allow-origin, access-control-allow-headers, %s", headerStr)
        } else {
            headerStr = "access-control-allow-origin, access-control-allow-headers"
        }
        if origin != "" {
            c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
            c.Header("Access-Control-Allow-Origin", "*")        // 这是允许访问所有域
            c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")      //服务器支持的所有跨域请求的方法,为了避免浏览次请求的多次'预检'请求
            //  header的类型
            c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,X_Requested_With,Accept, Origin, Host, Connection, Accept-Encoding, Accept-Language,DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Pragma")
            //              允许跨域设置                                                                                                      可以返回其他子段
            c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers,Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma,FooBar")      // 跨域关键设置 让浏览器可以解析
            c.Header("Access-Control-Max-Age", "172800")        // 缓存请求信息 单位为秒
            c.Header("Access-Control-Allow-Credentials", "false")       //  跨域请求是否需要带cookie信息 默认设置为true
            c.Set("content-type", "application/json")       // 设置返回格式是json
        }
 
        //放行所有OPTIONS方法
        if method == "OPTIONS" {
            c.JSON(http.StatusOK, "Options Request!")
        }
        // 处理请求
        c.Next()        //  处理请求
    }
}

6.main函数

package main

import (
	// "aiotdevice/dao"
	"aiotdevice/server"
	"time"

)

func main(){


	server.DeviceServer()
	for {
		time.Sleep(3*time.Second)
	}
}


测试:

1.get:

在这里插入图片描述

2.post:

在这里插入图片描述

实际项目中要远远复杂于上面的代码,接口的数据非空验证,参数检查,数据库验证;还要达到性能的要求;用户多的业务要支持线程安全、多并发;等等。都需要大量的代码,实际需要结合业务进行开发, 欢迎指正

参考:https://studygolang.com/articles/14503
https://blog.csdn.net/love666666shen/article/details/88901785

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值