Commit 5d705c4b by zhengqiuyun

Initial commit

parent 9ed335f6
package PagePlus
import (
"fmt"
"git.168cad.top/rym-open-source/rym-go-sdk/exception"
"git.168cad.top/rym-open-source/rym-go-sdk/page"
"git.168cad.top/rym-open-source/rym-go-sdk/util"
"gorm.io/gorm"
)
func Page(params []page.Param, pageNum int, pageSize int, m interface{}, data interface{}, orderBy string, db *gorm.DB) *page.Data {
var page = page.Data{}
page.PageSize = util.If(pageSize == 0, 10, pageSize)
page.PageNum = util.If(pageNum == 0, 1, pageNum)
tx := db.Session(&gorm.Session{PrepareStmt: true})
countTx := tx.Model(&m).Select("count(1)")
if params != nil {
for _, p := range params {
countTx.Where(p.Column+" "+p.Op+" ?", p.Value)
}
}
resultCount := countTx.Scan(&page.Total)
if resultCount.Error != nil {
exception.ThrowsErr(resultCount.Error)
}
if page.Total > 0 {
dataTx := tx.Model(&m).Offset((page.PageNum - 1) * page.PageSize).Limit(page.PageSize).Order(orderBy)
if params != nil {
for _, p := range params {
dataTx.Where(p.Column+" "+p.Op+" ?", p.Value)
}
}
resultList := dataTx.Find(&data)
if resultList.Error != nil {
exception.ThrowsErr(resultList.Error)
}
page.List = data
}
return &page
}
func PageSql(db *gorm.DB, data interface{}, pageNum int, pageSize int, sql string, sqlParams []interface{}) *page.Data {
var page = page.Data{}
page.PageSize = util.If(pageSize == 0, 10, pageSize)
page.PageNum = util.If(pageNum == 0, 1, pageNum)
tx := db.Session(&gorm.Session{PrepareStmt: false})
countTx := tx.Raw(fmt.Sprintf("select count(1) from (%s) _tmp_", sql), sqlParams...)
resultCount := countTx.Scan(&page.Total)
if resultCount.Error != nil {
exception.ThrowsErr(resultCount.Error)
}
if page.Total > 0 {
sql = fmt.Sprintf("%s limit ?,? ", sql)
sqlParams = append(sqlParams, (page.PageNum-1)*page.PageSize)
sqlParams = append(sqlParams, page.PageSize)
dataTx := tx.Raw(sql, sqlParams...)
resultList := dataTx.Scan(&data)
if resultList.Error != nil {
exception.ThrowsErr(resultList.Error)
}
}
page.List = data
return &page
}
package GoroutineExecutor
import (
"git.168cad.top/rym-open-source/rym-go-sdk/exception/catch"
)
func do(f func()) {
defer catch.ExceptionCatch(nil)
f()
}
func SynDo(f func()) {
go do(f)
}
package conf
import (
"git.168cad.top/rym-open-source/rym-go-sdk/util"
)
type Config struct {
ServerName string
Env string
HttpPort int
LogLevel string
LogColorful bool
LogResponseLength int
LogShowSql bool
Redis RedisConf
Elasticsearch EsConf
Mysql MysqlConf
}
func BaseConfig(conf Config) {
ServerName = conf.ServerName
Env = conf.Env
HttpPort = conf.HttpPort
if util.IsEmpty(&conf.LogLevel) {
LogLevel = "DEBUG"
} else {
LogLevel = conf.LogLevel
}
LogColorful = conf.LogColorful
LogResponseLength = conf.LogResponseLength
LogShowSql = conf.LogShowSql
Es = conf.Elasticsearch
Redis = conf.Redis
MySql = conf.Mysql
}
// Base conf
var ServerName string
var Env string
var HttpPort int
// log conf
var LogLevel = "DEBUG"
var LogColorful = false
var LogResponseLength int
var LogShowSql = true
var LogIndexNamePrefix = ""
// Redis conf
type RedisConf struct {
RedisHost string
RedisPort int
RedisPwd string
RedisDb int
ReadTimeout int //取超时间 单位秒 默认值为3秒
WriteTimeout int // 写入超时时间 单位秒 默认与读超时时间一致
PoolSize int //最大连接数 默认cpu数*10
MinIdleConns int //最小空闲连接数
}
var Redis = RedisConf{}
// ES conf
type EsConf struct {
ServerHost string
ServerPort int
Sniff bool
}
var Es = EsConf{}
// Mysql conf
type MysqlConf struct {
Host string
Port int
User string
Password string
NameSpace string
MaxIdleConns int
MaxOpenConns int
}
var MySql = MysqlConf{}
package YorN
const (
Y string = "1"
N string = "0"
)
package es
const indexNamePrefix = "manage_client_log"
package es
import (
"context"
"fmt"
"git.168cad.top/rym-open-source/rym-go-sdk/conf"
"git.168cad.top/rym-open-source/rym-go-sdk/log"
"github.com/olivere/elastic/v7"
_log "log"
"os"
)
func TestLog() {
log.Info("Es 测试")
}
var client *elastic.Client
func Init() {
host := fmt.Sprintf("http://%s:%d", conf.Es.ServerHost, conf.Es.ServerPort)
var err error
errorLog := _log.New(os.Stdout, "APP", _log.LstdFlags)
client, err = elastic.NewClient(elastic.SetSniff(conf.Es.Sniff), elastic.SetErrorLog(errorLog), elastic.SetURL(host))
if err != nil {
log.Error(fmt.Sprintf("Elasticsearch connect error:%s", err.Error()))
} else {
info, code, err := client.Ping(host).Do(context.Background())
if err != nil {
panic(err)
}
log.Info(fmt.Sprintf("Elasticsearch connect %d", code))
log.Info(fmt.Sprintf("Elasticsearch version %s", info.Version.Number))
}
}
func getRedisClient() *elastic.Client {
return client
}
package es
import (
"context"
"encoding/json"
"fmt"
"git.168cad.top/rym-open-source/rym-go-sdk/conf"
"git.168cad.top/rym-open-source/rym-go-sdk/exception"
"git.168cad.top/rym-open-source/rym-go-sdk/log"
"git.168cad.top/rym-open-source/rym-go-sdk/util"
"github.com/olivere/elastic/v7"
"sort"
"time"
)
func getCurrentIndex() string {
if conf.LogIndexNamePrefix == "" {
return indexNamePrefix + util.FormatDates(time.Now())
} else {
return conf.LogIndexNamePrefix + util.FormatDates(time.Now())
}
}
type ServerLogModel struct {
ServerName string `json:"serverName"`
Env string `json:"env"`
TimeStamp int64 `json:"timeStamp"`
ThreadNo string `json:"threadNo"`
ServerIp string `json:"serverIp"`
ClientIp string `json:"clientIp"`
Token string `json:"token"`
CustomerId uint32 `json:"customerId"`
ClientSource string `json:"clientSource"`
Url string `json:"url"`
Method string `json:"method"`
Request string `json:"request"`
Response string `json:"response"`
DealTimes int64 `json:"dealTimes"`
}
func InsertEsLog(logInfo interface{}) {
indexName := getCurrentIndex()
put, err := getRedisClient().Index().
Index(indexName).
BodyJson(logInfo).
Do(context.Background())
if err != nil {
log.Error(fmt.Sprintf("insert es log fail:%s", err.Error()))
} else {
log.Debug(fmt.Sprintf("insert es log success:%s", put.Id))
}
}
func GroupField(indexName, field string, size, minCount int, excludeValues []string) []byte {
if size == 0 {
size = 30
}
aggregationQuery := elastic.NewTermsAggregation().Field(field).MinDocCount(minCount).Size(size)
for _, excludeValue := range excludeValues {
aggregationQuery.ExcludeValues(excludeValue)
}
if log.IsDebug() {
source, _ := aggregationQuery.Source()
queryByte, _ := json.Marshal(source)
log.Info(fmt.Sprintf("查询条件:%s", string(queryByte)))
}
res, err := getRedisClient().Search(indexName).
Aggregation("group_field", aggregationQuery).
From(0).
Size(0).
Do(context.Background())
if err != nil {
exception.ThrowsErr(err)
}
bs, err := json.Marshal(res.Aggregations)
if err != nil {
exception.ThrowsErr(err)
}
return bs
}
func QueryLogs(indexName, filed, value string, from, size int) interface{} {
if from <= 0 {
from = 0
}
if size <= 0 {
size = 10
}
query := elastic.NewBoolQuery().Must(elastic.NewTermQuery(filed, value))
res, err := getRedisClient().Search(indexName).Query(query).
From(from).
Size(size).
Do(context.Background())
if err != nil {
exception.ThrowsErr(err)
}
return res
}
type IndexInfo struct {
Name string `json:"name"`
Count int `json:"count"`
Size string `json:"size"`
}
func AllIndex() interface{} {
res, err := getRedisClient().CatIndices().Do(context.Background())
if err != nil {
exception.ThrowsErr(err)
}
var keys []string
var sizeMap = make(map[string]IndexInfo)
for _, row := range res {
keys = append(keys, row.Index)
sizeMap[row.Index] = IndexInfo{row.Index, row.DocsCount, row.StoreSize}
}
sort.Strings(keys)
data := make([]IndexInfo, len(keys))
for i, key := range keys {
data[i] = sizeMap[key]
}
return data
}
func DeleteIndex(indexName string) interface{} {
res, err := getRedisClient().DeleteIndex(indexName).
Do(context.Background())
if err != nil {
exception.ThrowsErr(err)
}
return res
}
package es
import (
"context"
"fmt"
"git.168cad.top/rym-open-source/rym-go-sdk/conf"
"git.168cad.top/rym-open-source/rym-go-sdk/log"
"github.com/olivere/elastic/v7"
_log "log"
"os"
"testing"
)
func init() {
conf.Es = conf.EsConf{
//ServerHost: "to-chengdu-office.168cad.top",
//ServerPort: 50037,
ServerHost: "192.168.1.124",
ServerPort: 9200,
Sniff: true,
}
}
func TestName(t *testing.T) {
host := fmt.Sprintf("http://%s:%d", conf.Es.ServerHost, conf.Es.ServerPort)
var err error
errorLog := _log.New(os.Stdout, "APP", _log.LstdFlags)
client, err := elastic.NewClient(elastic.SetSniff(conf.Es.Sniff), elastic.SetErrorLog(errorLog), elastic.SetURL(host))
if err != nil {
log.Error(err.Error())
}
info, code, err := client.Ping(host).Do(context.Background())
if err != nil {
panic(err)
}
log.Info(fmt.Sprintf("Elasticsearch connect %d", code))
log.Info(fmt.Sprintf("Elasticsearch version %s", info.Version.Number))
}
package exception
import (
"github.com/go-playground/validator/v10"
"reflect"
"strings"
)
func ThrowsErr(err error) {
panic(err)
}
func ThrowsValid(err error, r interface{}) {
if err != nil {
switch err.(type) {
case validator.ValidationErrors:
e := (err).(validator.ValidationErrors)
errMsg := getError(e, r)
panic(DError{Code: "REQUEST_PARAMS_ERR", Err: errMsg})
break
default:
ThrowsErr(err)
break
}
}
}
// 自定义错误消息
func getError(errs validator.ValidationErrors, r interface{}) string {
s := reflect.TypeOf(r)
for _, fieldError := range errs {
filed, _ := s.FieldByName(fieldError.Field())
// 获取统一错误消息
errText := filed.Tag.Get("msg")
if errText != "" {
return errText
}
jsonTag := filed.Tag.Get("json")
fieldName := ""
if jsonTag == "" {
fieldName = fieldError.Field()
} else {
fieldName = strings.Split(jsonTag, ",")[0]
}
return fieldName + " " + fieldError.Tag()
}
return ""
}
type DError struct {
Err string
Code string
}
func ThrowsErrS(code, err string) {
panic(DError{Code: code, Err: err})
}
func AssertThrowableErr(throwable bool, err error) {
if throwable {
ThrowsErr(err)
}
}
func AssertThrowable(throwable bool, code, err string) {
if throwable {
ThrowsErrS(code, err)
}
}
package catch
import (
"fmt"
"git.168cad.top/rym-open-source/rym-go-sdk/exception"
"git.168cad.top/rym-open-source/rym-go-sdk/getWay"
"git.168cad.top/rym-open-source/rym-go-sdk/log"
"github.com/gin-gonic/gin"
"runtime"
)
func ExceptionCatch(c *gin.Context) {
err := recover() //获取异常
if err != nil {
switch err.(type) {
case exception.DError:
e := (err).(exception.DError)
if c == nil {
log.Errorf("%s-%s", e.Code, e.Err)
} else {
getWay.FailAndMsg(c, e.Code, e.Err)
}
break
case error:
e := (err).(error)
if c == nil {
log.Error(e.Error())
} else {
getWay.FailAndMsg(c, "SYSTEM.ERROR", e.Error())
}
printStack()
break
case string:
e := (err).(string)
if c == nil {
log.Error(e)
} else {
getWay.FailAndMsg(c, "SYSTEM.ERROR", e)
}
printStack()
break
default:
if c != nil {
getWay.FailAndMsg(c, "SYSTEM.ERROR", "系统繁忙...")
}
printStack()
break
}
}
}
func printStack() {
var buf [1024]byte
n := runtime.Stack(buf[:], true)
fmt.Println(string(buf[:]), n)
}
package catch
import (
"errors"
"testing"
)
func TestExceptionCatch(t *testing.T) {
defer ExceptionCatch(nil)
panic(errors.New("错误"))
}
package getWay
import "github.com/gin-gonic/gin"
type Error struct {
Code State
SubCode string
SubMsg string
}
type SError struct {
Code State
SubCode string
SubMsg string
}
func ExceptionGetWayCatch(c *gin.Context) {
err := recover() //获取异常
if err != nil {
switch err.(type) {
case Error:
e := (err).(Error)
FailGetWay(c, e.Code, e.SubCode, e.SubMsg)
break
case SError:
e := (err).(SError)
SuccessGetWay(c, e.Code, e.SubCode, e.SubMsg)
break
}
}
}
func ThrowsGetWayErr(code State, subCode, subMsg string) {
panic(Error{Code: code, SubCode: subCode, SubMsg: subMsg})
}
func ThrowsGetWaySErr(code State, subCode, subMsg string) {
panic(SError{Code: code, SubCode: subCode, SubMsg: subMsg})
}
func AssertThrowsGetWayErr(throwable bool, code State, subCode, subMsg string) {
if throwable {
ThrowsGetWayErr(code, subCode, subMsg)
}
}
func AssertThrowsGetWaySErr(throwable bool, code State, subCode, subMsg string) {
if throwable {
ThrowsGetWaySErr(code, subCode, subMsg)
}
}
package getWay
import (
"git.168cad.top/rym-open-source/rym-go-sdk/util"
"github.com/gin-gonic/gin"
)
const (
headerKeyToken = "token"
headerKeyPlatform = "platform"
headerKeyAppId = "appId"
headerKeyTimeStamp = "timeStamp"
headerKeySign = "sign"
)
const headerKeyClientSource = "clientSource"
func GetToken(c *gin.Context) string {
return c.GetHeader(headerKeyToken)
}
func SetToken(v string, c *gin.Context) {
c.Header(headerKeyToken, v)
}
func GetAppId(c *gin.Context) string {
return c.GetHeader(headerKeyAppId)
}
func GetTimeStamp(c *gin.Context) string {
return c.GetHeader(headerKeyTimeStamp)
}
func GetSign(c *gin.Context) string {
return c.GetHeader(headerKeySign)
}
func GetPlatform(c *gin.Context) string {
platformCode := c.GetHeader(headerKeyPlatform)
return platformCode
}
func GetClientSource(c *gin.Context) string {
h := c.GetHeader(headerKeyClientSource)
if h == "" {
return util.GetInterfaceToString(clientSource{
AppId: GetAppId(c),
TimeStamp: GetTimeStamp(c),
Sign: GetSign(c),
Platform: GetPlatform(c),
})
}
return h
}
type clientSource struct {
AppId string `json:"appId"`
TimeStamp string `json:"timeStamp"`
Sign string `json:"sign"`
Platform string `json:"platform"`
}
package getWay
import (
"encoding/json"
"fmt"
"git.168cad.top/rym-open-source/rym-go-sdk/log"
"github.com/gin-gonic/gin"
"net"
"time"
)
func GetCurrentUserId(c *gin.Context) (uint32, bool) {
userId, b := c.Get(CurrentUserIdKey)
if b {
transUserId := userId.(uint32)
return transUserId, b
}
return 0, b
}
type UserInfo struct {
Id uint32
Account string
Name string
}
func GetCurrentUser(c *gin.Context) *UserInfo {
var userInfo = UserInfo{}
adminResponse, b := c.Get(CurrentUserKey)
if b {
admin := adminResponse.(Admin)
userInfo.Name = admin.Name
userInfo.Account = admin.LoginAccount
userInfo.Id = admin.Id
}
return &userInfo
}
type AdminResponse struct {
code int
msg string
Admin Admin
}
type Admin struct {
Id uint32
Name string
LoginAccount string
}
const requestBodyKey = "requestBody"
func BindRequestBody(c *gin.Context, param interface{}) error {
err := c.ShouldBindJSON(param)
if err != nil {
return err
}
bytes, err := json.Marshal(param)
c.Set(requestBodyKey, string(bytes))
return err
}
func GetParams(c *gin.Context) string {
rd := ""
params := c.Request.URL.Query().Encode()
if params != "" {
rd += params
}
ad := c.GetString(requestBodyKey)
if ad != "" {
rd += ad
}
return rd
}
func GetServerIP() string {
addrs, err := net.InterfaceAddrs()
if err != nil {
return ""
}
for _, addr := range addrs {
ipAddr, ok := addr.(*net.IPNet)
if !ok {
continue
}
if ipAddr.IP.IsLoopback() {
continue
}
if !ipAddr.IP.IsGlobalUnicast() {
continue
}
return ipAddr.IP.String()
}
return ""
}
func GetClientIP(c *gin.Context) string {
ip := c.ClientIP()
return ip
}
func GetURL(c *gin.Context) string {
url := c.Request.URL.Path
return url
}
func GetMethod(c *gin.Context) string {
method := c.Request.Method
return method
}
func SetStartTime(c *gin.Context) {
c.Set(StartTimeKey, time.Now().UnixNano())
logStart(c)
}
func GetStartTime(c *gin.Context) int64 {
startTime := c.GetInt64(StartTimeKey)
return startTime
}
func logStart(c *gin.Context) {
log.Info(fmt.Sprintf("开始 %s %s %s %s", GetMethod(c), GetURL(c), GetToken(c), GetClientIP(c)))
}
package getWay
import (
"encoding/json"
"fmt"
"git.168cad.top/rym-open-source/rym-go-sdk/conf"
"git.168cad.top/rym-open-source/rym-go-sdk/es"
"git.168cad.top/rym-open-source/rym-go-sdk/log"
db "git.168cad.top/rym-open-source/rym-go-sdk/mysqlrym"
"git.168cad.top/rym-open-source/rym-go-sdk/redis"
"git.168cad.top/rym-open-source/rym-go-sdk/util"
"github.com/gin-gonic/gin"
"net/http"
"time"
)
type ServerResponse struct {
Code State `json:"code"` //0为成功,其他都是失败
Msg string `json:"msg,omitempty"` //非1000情况下的错误描述
SubCode string `json:"subCode,omitempty"`
SubMsg string `json:"subMsg,omitempty"`
}
type ServerDataResponse struct {
ServerResponse
Data interface{} `json:"data,omitempty"`
}
func response(state State) ServerResponse {
return ServerResponse{Code: state, Msg: state.String()}
}
func responseSub(state State, subCode, subMsg string) ServerResponse {
return ServerResponse{Code: state, Msg: state.String(), SubCode: subCode, SubMsg: subMsg}
}
func FailGetWay(c *gin.Context, state State, subCode, subMsg string) {
resp := responseSub(state, subCode, subMsg)
c.JSON(http.StatusBadGateway, resp)
c.Abort()
LogEnd(c, resp)
}
func SuccessGetWay(c *gin.Context, state State, subCode, subMsg string) {
resp := responseSub(state, subCode, subMsg)
c.JSON(http.StatusOK, resp)
c.Abort()
LogEnd(c, resp)
}
func FailAndMsg(c *gin.Context, subCode, subMsg string) {
db.Rollback()
resp := ServerResponse{Code: BusinessError, Msg: "业务错误", SubCode: subCode, SubMsg: subMsg}
c.JSON(http.StatusOK, resp)
c.Abort()
LogEnd(c, resp)
}
// FailAndMsgNoTx 不带事务
func FailAndMsgNoTx(c *gin.Context, subCode, subMsg string) {
resp := ServerResponse{Code: BusinessError, Msg: "业务错误", SubCode: subCode, SubMsg: subMsg}
c.JSON(http.StatusOK, resp)
c.Abort()
LogEnd(c, resp)
}
// Success 有事务的用这个
func Success(c *gin.Context) {
db.Commit()
resp := response(OK)
c.JSON(http.StatusOK, resp)
c.Abort()
LogEnd(c, resp)
}
// SuccessNoTx 不带事务提交
func SuccessNoTx(c *gin.Context) {
resp := response(OK)
c.JSON(http.StatusOK, resp)
c.Abort()
LogEnd(c, resp)
}
// SuccessData 有事务的用这个
func SuccessData(c *gin.Context, data interface{}) {
db.Commit()
resp := ServerDataResponse{response(OK), data}
c.JSON(http.StatusOK, resp)
c.Abort()
LogEnd(c, resp)
}
// SuccessDataNoTx 不带事务提交
func SuccessDataNoTx(c *gin.Context, data interface{}) {
resp := ServerDataResponse{response(OK), data}
c.JSON(http.StatusOK, resp)
c.Abort()
LogEnd(c, resp)
}
func SuccessString(c *gin.Context, data string) {
c.String(http.StatusOK, data)
c.Abort()
LogEnd(c, data)
}
func LogEnd(c *gin.Context, data interface{}) {
esSwitch := redis.SwitchOpen(redis.ES日志开关 + conf.ServerName)
startTime := GetStartTime(c)
endTime := time.Now().UnixNano()
var responseStr string
if data != nil {
dataJson, _ := json.Marshal(data)
rs := string(dataJson)
excludeUrl := []string{""}
if esSwitch {
if util.ArrayContains(excludeUrl, GetURL(c)) && len(rs) > conf.LogResponseLength {
responseStr = rs[0:conf.LogResponseLength] + "......"
} else {
responseStr = rs
}
} else {
if len(rs) > conf.LogResponseLength {
responseStr = rs[0:conf.LogResponseLength] + "......"
} else {
responseStr = rs
}
}
}
token := GetToken(c)
if esSwitch {
esLog(c, responseStr)
log.Info(fmt.Sprintf("结束,耗时%d毫秒", (endTime-startTime)/1e6))
} else {
log.Info(fmt.Sprintf("返回数据:%s", responseStr))
log.Info(fmt.Sprintf("结束,耗时%d毫秒 %s %s %s %s %s", (endTime-startTime)/1e6, GetMethod(c), GetURL(c), token, GetClientIP(c), GetParams(c)))
}
}
func esLog(c *gin.Context, response string) {
log := es.ServerLogModel{
ServerName: conf.ServerName,
Env: conf.Env,
TimeStamp: util.MilSecond(time.Now()),
ThreadNo: fmt.Sprintf("%d", util.GetGID()),
ServerIp: GetServerIP(),
ClientIp: GetClientIP(c),
Token: GetToken(c),
CustomerId: GetCurrentUser(c).Id,
ClientSource: GetClientSource(c),
Url: GetURL(c),
Method: GetMethod(c),
Request: GetParams(c),
Response: response,
DealTimes: util.MilSecond(time.Now()) - GetStartTime(c)/1e6,
}
es.InsertEsLog(log)
}
package getWay
type State int16
// iota 初始化后会自动递增
const (
BusinessError State = 1001
OK State = 1000
Illegal State = 9000
LoginFailure State = -1
)
func (t State) String() string {
switch t {
case BusinessError:
return "business error"
case OK:
return "OK"
case Illegal:
return "非法请求"
case LoginFailure:
return "登陆失效"
default:
return "unknown"
}
}
package getWay
const CurrentUserKey = "userInfo"
const CurrentUserIdKey = "userID"
const StartTimeKey = "StartTime"
module git.168cad.top/rym-open-source/rym-go-sdk
go 1.18
require (
github.com/gin-contrib/cors v1.4.0
github.com/gin-gonic/gin v1.8.1
github.com/go-playground/validator/v10 v10.11.0
github.com/go-redis/redis v6.15.9+incompatible
github.com/olivere/elastic/v7 v7.0.32
gorm.io/driver/mysql v1.2.2
gorm.io/gorm v1.22.4
)
require (
github.com/KyleBanks/depth v1.2.1 // indirect
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.6 // indirect
github.com/go-openapi/spec v0.20.4 // indirect
github.com/go-openapi/swag v0.19.15 // indirect
github.com/go-playground/locales v0.14.0 // indirect
github.com/go-playground/universal-translator v0.18.0 // indirect
github.com/go-sql-driver/mysql v1.6.0 // indirect
github.com/goccy/go-json v0.9.7 // indirect
github.com/google/go-cmp v0.5.8 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.3 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/swaggo/swag v1.8.1 // indirect
github.com/ugorji/go/codec v1.2.7 // indirect
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 // indirect
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.7 // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
require (
github.com/onsi/ginkgo v1.16.5 // indirect
github.com/onsi/gomega v1.20.0 // indirect
github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a
github.com/swaggo/gin-swagger v1.5.2
)
This diff is collapsed. Click to expand it.
package log
import (
"bytes"
"fmt"
"git.168cad.top/rym-open-source/rym-go-sdk/conf"
"runtime"
"strconv"
"strings"
"time"
)
const (
LevelDebug = "Debug"
LevelInfo = "Info"
LevelWarn = "Warn"
LevelError = "Error"
)
func DebugDo(f func()) {
if IsDebug() {
f()
}
}
func IsDebug() bool {
ok := false
switch strings.ToLower(conf.LogLevel) {
case strings.ToLower(LevelDebug):
ok = true
break
}
return ok
}
func Debugf(format string, msg ...interface{}) {
ok := false
switch strings.ToLower(conf.LogLevel) {
case strings.ToLower(LevelDebug):
ok = true
break
}
if ok {
_, file, line, _ := runtime.Caller(1)
print(LevelDebug, file, line, fmt.Sprintf(format, msg...))
}
}
func Debug(msg interface{}) {
ok := false
switch strings.ToLower(conf.LogLevel) {
case strings.ToLower(LevelDebug):
ok = true
break
}
if ok {
_, file, line, _ := runtime.Caller(1)
print(LevelDebug, file, line, msg)
}
}
func Infof(format string, msg ...interface{}) {
ok := false
switch strings.ToLower(conf.LogLevel) {
case strings.ToLower(LevelDebug):
ok = true
break
case strings.ToLower(LevelInfo):
ok = true
break
}
if ok {
_, file, line, _ := runtime.Caller(1)
print(LevelInfo, file, line, fmt.Sprintf(format, msg...))
}
}
func Info(msg interface{}) {
ok := false
switch strings.ToLower(conf.LogLevel) {
case strings.ToLower(LevelDebug):
ok = true
break
case strings.ToLower(LevelInfo):
ok = true
break
}
if ok {
_, file, line, _ := runtime.Caller(1)
print(LevelInfo, file, line, msg)
}
}
func Warnf(format string, msg ...interface{}) {
ok := false
switch strings.ToLower(conf.LogLevel) {
case strings.ToLower(LevelDebug):
ok = true
break
case strings.ToLower(LevelInfo):
ok = true
break
case strings.ToLower(LevelWarn):
ok = true
break
}
if ok {
_, file, line, _ := runtime.Caller(1)
print(LevelWarn, file, line, fmt.Sprintf(format, msg...))
}
}
func Warn(msg interface{}) {
ok := false
switch strings.ToLower(conf.LogLevel) {
case strings.ToLower(LevelDebug):
ok = true
break
case strings.ToLower(LevelInfo):
ok = true
break
case strings.ToLower(LevelWarn):
ok = true
break
}
if ok {
_, file, line, _ := runtime.Caller(1)
print(LevelWarn, file, line, msg)
}
}
func Errorf(format string, msg ...interface{}) {
ok := false
switch strings.ToLower(conf.LogLevel) {
case strings.ToLower(LevelDebug):
ok = true
break
case strings.ToLower(LevelInfo):
ok = true
break
case strings.ToLower(LevelWarn):
ok = true
break
case strings.ToLower(LevelError):
ok = true
break
}
if ok {
_, file, line, _ := runtime.Caller(1)
print(LevelError, file, line, fmt.Sprintf(format, msg...))
}
}
func Error(msg interface{}) {
ok := false
switch strings.ToLower(conf.LogLevel) {
case strings.ToLower(LevelDebug):
ok = true
break
case strings.ToLower(LevelInfo):
ok = true
break
case strings.ToLower(LevelWarn):
ok = true
break
case strings.ToLower(LevelError):
ok = true
break
}
if ok {
_, file, line, _ := runtime.Caller(1)
print(LevelError, file, line, msg)
}
}
// Colors
const (
reset = "\033[0m"
red = "\033[31m"
green = "\033[32m"
yellow = "\033[33m"
blue = "\033[34m"
magenta = "\033[35m"
cyan = "\033[36m"
white = "\033[37m"
blueBold = "\033[34;1m"
magentaBold = "\033[35;1m"
redBold = "\033[31;1m"
yellowBold = "\033[33;1m"
)
func print(tag, file string, line int, msg interface{}) {
str := "%s %s [%d] %s %d %s"
if conf.LogColorful {
switch tag {
case LevelDebug:
str = "%s %s [%d] %s %d " + green + "%s" + reset
break
case LevelInfo:
str = "%s %s [%d] %s %d " + yellow + "%s" + reset
break
case LevelWarn:
str = "%s %s [%d] %s %d " + magenta + "%s" + reset
break
case LevelError:
str = "%s %s [%d] %s %d " + red + "%s" + reset
break
}
}
file = file[strings.LastIndex(file, "/")+1:]
fmt.Println(fmt.Sprintf(str, formatDateMillTime(time.Now()), tag, getGID(), file, line, msg))
}
func formatDateMillTime(dataTime time.Time) string {
return dataTime.Format("2006-01-02 15:04:05.000000")
}
func getGID() uint64 {
b := make([]byte, 64)
b = b[:runtime.Stack(b, false)]
b = bytes.TrimPrefix(b, []byte("goroutine "))
b = b[:bytes.IndexByte(b, ' ')]
n, _ := strconv.ParseUint(string(b), 10, 64)
return n
}
package main
import (
"git.168cad.top/rym-open-source/rym-go-sdk/concurrent/GoroutineExecutor"
"git.168cad.top/rym-open-source/rym-go-sdk/conf"
"git.168cad.top/rym-open-source/rym-go-sdk/es"
"git.168cad.top/rym-open-source/rym-go-sdk/log"
"git.168cad.top/rym-open-source/rym-go-sdk/mysqlrym"
"git.168cad.top/rym-open-source/rym-go-sdk/redis"
"git.168cad.top/rym-open-source/rym-go-sdk/router"
)
func main() {
orderCode := "2020202021212"
log.Debugf("订单完成通知:%s", orderCode)
GoroutineExecutor.SynDo(func() {
panic("真的错误了")
})
log.Debug("测试")
log.Info("测试")
log.Warn("测试")
log.Error("测试")
conf.BaseConfig(conf.Config{
ServerName: "rym-framework",
Env: "dev",
HttpPort: 1024,
LogColorful: true,
})
mysqlrym.TestLog()
es.TestLog()
redis.TestLog()
c := router.InitGinEngine(true)
router.Run(c)
}
package mysqlrym
import (
"fmt"
"git.168cad.top/rym-open-source/rym-go-sdk/conf"
"git.168cad.top/rym-open-source/rym-go-sdk/log"
"git.168cad.top/rym-open-source/rym-go-sdk/util"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"os"
"sync"
"time"
"gorm.io/gorm/logger"
_log "log"
)
func TestLog() {
log.Info("Mysql 测试")
}
var customerDb *gorm.DB
var customerDbMap sync.Map
var gidNeedTX sync.Map
func SetTx() {
gid := util.GetGID()
gidNeedTX.Store(gid, 1)
}
func GetDb() *gorm.DB {
return getDb(customerDb, &customerDbMap)
}
func getDb(db *gorm.DB, dbMap *sync.Map) *gorm.DB {
gid := util.GetGID()
_, needTx := gidNeedTX.Load(gid)
if needTx {
cacheTx, ok := dbMap.Load(gid)
if ok {
return cacheTx.(*gorm.DB)
} else {
if conf.LogShowSql {
db = db.Debug()
}
tx := db.Begin()
dbMap.Store(gid, tx)
return tx
}
} else {
if conf.LogShowSql {
db = db.Debug()
}
return db
}
}
func Rollback() {
gid := util.GetGID()
_, needTx := gidNeedTX.Load(gid)
if needTx {
rollbackTx(gid, &customerDbMap)
gidNeedTX.Delete(gid)
}
}
func Commit() {
gid := util.GetGID()
_, needTx := gidNeedTX.Load(gid)
if needTx {
commitTx(gid, &customerDbMap)
gidNeedTX.Delete(gid)
}
}
func rollbackTx(gid uint64, dbMap *sync.Map) {
cacheTx, ok := dbMap.Load(gid)
if ok {
tx := cacheTx.(*gorm.DB)
tx.Rollback()
dbMap.Delete(gid)
}
}
func commitTx(gid uint64, dbMap *sync.Map) {
cacheTx, ok := dbMap.Load(gid)
if ok {
tx := cacheTx.(*gorm.DB)
tx.Commit()
dbMap.Delete(gid)
}
}
func Init() {
newLogger := logger.New(
_log.New(os.Stdout, "", _log.Lmicroseconds), // io writer(日志输出的目标,前缀和日志包含的内容——译者注)
logger.Config{
SlowThreshold: time.Second, // 慢 SQL 阈值
LogLevel: logger.Error, // 日志级别
IgnoreRecordNotFoundError: true, // 忽略ErrRecordNotFound(记录未找到)错误
Colorful: conf.LogColorful, // 是否开启彩色打印
},
)
var err error
customerDb, err = gorm.Open(mysql.Open(fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
conf.MySql.User, conf.MySql.Password, conf.MySql.Host, conf.MySql.Port, conf.MySql.NameSpace)), &gorm.Config{
PrepareStmt: true,
Logger: newLogger,
})
if err != nil {
log.Error(fmt.Sprintf("%s connect error:%s", "Mysql server", err.Error()))
} else {
sqlDB, err := customerDb.DB()
if conf.MySql.MaxIdleConns == 0 {
sqlDB.SetMaxIdleConns(10)
} else {
sqlDB.SetMaxIdleConns(conf.MySql.MaxIdleConns)
}
if conf.MySql.MaxOpenConns == 0 {
sqlDB.SetMaxOpenConns(10)
} else {
sqlDB.SetMaxOpenConns(conf.MySql.MaxOpenConns)
}
if err != nil {
log.Error(fmt.Sprintf("%s connect error:%s", "Mysql server", err.Error()))
} else {
log.Info(fmt.Sprintf("%s connect success", "Mysql server"))
}
}
}
package page
type Page struct {
PageNum int `json:"pageNum"`
PageSize int `json:"pageSize"`
Total int `json:"total"`
}
type Data struct {
Page
List interface{} `json:"list"`
}
package page
type ParamPage struct {
PageNum int `json:"pageNum"`
PageSize int `json:"pageSize"`
}
type Param struct {
Column string
Op string
Value interface{}
}
package redis
import (
"fmt"
"git.168cad.top/rym-open-source/rym-go-sdk/conf"
"git.168cad.top/rym-open-source/rym-go-sdk/const/YorN"
"git.168cad.top/rym-open-source/rym-go-sdk/log"
"github.com/go-redis/redis"
"time"
)
func TestLog() {
log.Info("Redis 测试")
}
var redisClient *redis.Client
func Init() {
redisClient = redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%d", conf.Redis.RedisHost, conf.Redis.RedisPort),
Password: conf.Redis.RedisPwd,
DB: conf.Redis.RedisDb, // redis一共16个库,指定其中一个库即可
PoolSize: conf.Redis.PoolSize, //最大连接数 默认cpu数*10
MinIdleConns: conf.Redis.MinIdleConns, //最小空闲连接数
ReadTimeout: time.Duration(conf.Redis.ReadTimeout) * time.Second, //取超时间 单位秒 默认值为3秒
WriteTimeout: time.Duration(conf.Redis.WriteTimeout) * time.Second, // 写入超时时间 单位秒 默认与读超时时间一致
})
_, err := redisClient.Ping().Result()
if err != nil {
log.Error(fmt.Sprintf("Redis connect error :%s", err.Error()))
} else {
log.Info("Redis connect success")
}
return
}
func getDb() *redis.Client {
return redisClient
}
func Incr(key string) int64 {
r := getDb().Incr(key)
return r.Val()
}
func IncrBy(key string, n int64) int64 {
r := getDb().IncrBy(key, n)
return r.Val()
}
func DecrBy(key string, n int64) int64 {
r := getDb().DecrBy(key, n)
return r.Val()
}
func Exists(key string) bool {
r := getDb().Exists(key)
return r.Val() > 0
}
//SwitchOpen 在redis中存0或1,1代表OK
func SwitchOpen(key string) bool {
r := GetString(key)
log.Debug(fmt.Sprintf("缓存[%s]数据为:%s", key, r))
return r == YorN.Y
}
func GetString(key string) string {
r := getDb().Get(key)
return r.Val()
}
func Get(key string) []byte {
r := getDb().Get(key)
rByte, err := r.Bytes()
if err != nil {
log.Warn(fmt.Sprintf("获取缓存错误:%s", err.Error()))
}
return rByte
}
func Set(k, v string) error {
e := getDb().Set(k, v, 0).Err()
if e == nil {
log.Debug(fmt.Sprintf("设置缓存成功:%s %s", k, v))
} else {
log.Debug(fmt.Sprintf("设置缓存失败:%s %s %s", k, v, e))
}
return e
}
func SetNx(k, v string, timeoutSecond int) error {
e := getDb().Set(k, v, time.Duration(timeoutSecond)*time.Second).Err()
if e == nil {
log.Debug(fmt.Sprintf("设置缓存成功:%s %s", k, v))
} else {
log.Debug(fmt.Sprintf("设置缓存失败:%s %s %s", k, v, e))
}
return e
}
func Del(ks ...string) (int64, error) {
return getDb().Del(ks...).Result()
}
func Expire(k string, t int64) bool {
b := getDb().Expire(k, time.Duration(t*1000000000))
if b.Val() {
log.Debug(fmt.Sprintf("设置缓存过期成功:%s %d", k, t))
} else {
log.Warn(fmt.Sprintf("设置缓存过期失败:%s %d", k, t))
}
return b.Val()
}
var lockScript string = `if redis.call("exists",KEYS[1]) == 0 then
local lockSrc = redis.call("setex",KEYS[1],unpack(ARGV))
if lockSrc then
return "1"
end
return "0"
end`
var unlockScript string = `if redis.call('get', KEYS[1]) == ARGV[1] then
local lockSrc = redis.call('del', KEYS[1])
if lockSrc then
return "1"
end
return "0"
end`
// Lock 抢锁。抢到锁返回true,否则false。只抢一次
// 所有参数必传,超时时间单位秒
func Lock(k, uniqueValue string, timeoutSecond int) bool {
r, _ := getDb().Eval(lockScript, []string{k}, timeoutSecond, uniqueValue).String()
if r == "1" {
return true
}
return false
}
// Unlock 解锁
// 所有参数必传
func Unlock(k, uniqueValue string) bool {
r, _ := getDb().Eval(unlockScript, []string{k}, uniqueValue).String()
if r == "1" {
return true
}
return false
}
// LockWait 抢锁,在规定的时间内直到抢锁成功或者超时失败。抢到锁返回true,否则false
// k 必须
// uniqueValue 必须
// timeoutSecond 锁自动释放时间,必须
// lockTimeoutSecond 抢锁超时时间,默认1分钟
func LockWait(k, uniqueValue string, timeoutSecond int, lockTimeoutSecond int) bool {
if lockTimeoutSecond == 0 {
lockTimeoutSecond = 60
}
loopCount := lockTimeoutSecond * 10
for i := 0; i < loopCount; i++ {
if Lock(k, uniqueValue, timeoutSecond) {
return true
}
time.Sleep(time.Duration(100) * time.Millisecond) //100ms
}
return false
}
// Hset 向一张hash表中放入数据,如果不存在将创建
func Hset(k, i, v string, timeoutSecond int) error {
e := getDb().HSet(k, i, v).Err()
if e == nil {
log.Debug(fmt.Sprintf("设置缓存成功:%s %s %s", k, i, v))
if timeoutSecond > 0 {
Expire(k, int64(timeoutSecond))
}
} else {
log.Debug(fmt.Sprintf("设置缓存失败:%s %s %s %s", k, i, v, e))
}
return e
}
// HGet 从hash中获取值
func HGet(k, i string) (string, error) {
r, e := getDb().HGet(k, i).Result()
return r, e
}
// HGetAll 从hash中获key所有的取值
func HGetAll(k string) (map[string]string, error) {
return getDb().HGetAll(k).Result()
}
// Hdel 从hash中删除
func Hdel(k string, is ...string) (int64, error) {
r, e := getDb().HDel(k, is...).Result()
return r, e
}
// HMSet 向一张hash表中放入数据,如果不存在将创建
func HMSet(k string, fields map[string]interface{}, timeoutSecond int) error {
e := getDb().HMSet(k, fields).Err()
if e == nil {
log.Debug(fmt.Sprintf("设置缓存成功:%s %s", k, fields))
if timeoutSecond > 0 {
Expire(k, int64(timeoutSecond))
}
} else {
log.Debug(fmt.Sprintf("设置缓存失败:%s %s %s", k, fields, e))
}
return e
}
func HMget(k string, is ...string) ([]interface{}, error) {
return getDb().HMGet(k, is...).Result()
}
package redis
import (
"git.168cad.top/rym-open-source/rym-go-sdk/conf"
"testing"
)
func init() {
conf.Redis = conf.RedisConf{
RedisHost: "to-chengdu-office.168cad.top",
RedisPort: 50001,
RedisPwd: "testPassevnsoo567",
RedisDb: 0,
}
}
func TestExpire(t *testing.T) {
Init()
Expire("ZQY123", 1000)
}
package redis
const (
ES日志开关 = "es:log:switch:"
)
package router
import (
"fmt"
"git.168cad.top/rym-open-source/rym-go-sdk/conf"
"git.168cad.top/rym-open-source/rym-go-sdk/log"
"git.168cad.top/rym-open-source/rym-go-sdk/router/validator"
"git.168cad.top/rym-open-source/rym-go-sdk/util"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/render"
"github.com/swaggo/files"
"github.com/swaggo/gin-swagger"
"net/http"
)
func InitGinEngine(canCors bool) *gin.Engine {
gin.SetMode(gin.ReleaseMode)
c := gin.New()
if canCors {
corsConfig := cors.DefaultConfig()
corsConfig.AllowAllOrigins = true
corsConfig.AllowHeaders = []string{"*"}
c.Use(cors.New(corsConfig))
}
//便于工具监测
c.GET("/favicon.ico", func(c *gin.Context) {
c.Render(http.StatusOK, render.String{})
})
//自定义验证器
validator.RegisterValidate()
if conf.Env == "dev" || conf.Env == "test" {
//swagger
c.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
log.Info("swagger init success")
}
return c
}
func Run(c *gin.Engine) {
portAddr := ""
arg1 := util.Args(1)
if arg1 == "" {
portAddr = fmt.Sprintf(":%d", conf.HttpPort)
} else {
portAddr = fmt.Sprintf(":%s", arg1)
}
log.Info(fmt.Sprintf("web start in port%s", portAddr))
err := c.Run(portAddr)
if err != nil {
panic(err)
}
}
package validator
import (
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/validator/v10"
)
func RegisterValidate() {
// 注册验证器
validate, ok := binding.Validator.Engine().(*validator.Validate)
if ok {
validate.RegisterValidation("NotNull", notNullValidator)
}
}
// 参数不能为空(包括不传参数及参数值为空字符串)
var notNullValidator validator.Func = func(fl validator.FieldLevel) bool {
if value, ok := fl.Field().Interface().(string); ok {
// 字段不能为空,并且不等于 admin
return value != ""
}
return true
}
package sqlOp
const Equal = "="
const Like = "like"
const IN = "in"
const LessThan = "<"
const GreatThan = ">"
const LessThanOrEqual = "<="
const GreatThanOrEqual = ">="
func DimLeft(s string) string {
return "%" + s
}
func DimRight(s string) string {
return s + "%"
}
func DimAll(s string) string {
return "%" + s + "%"
}
package util
func Addr[T any](p T) *T {
return &p
}
package util
func ArrayContains[T comparable](array []T, e T) bool {
for _, v := range array {
if v == e {
return true
}
}
return false
}
func DifferenceSet[K comparable](a1, a2 []K) (d1, d2 []K) {
var vMap = map[K]*int{}
for _, v1 := range a1 {
vMap[v1] = Addr[int](1)
}
for _, v2 := range a2 {
if vMap[v2] == nil {
vMap[v2] = Addr[int](2)
} else {
vMap[v2] = Addr[int](0)
}
}
for k, v := range vMap {
if *v == 1 {
d1 = append(d1, k)
} else if *v == 2 {
d2 = append(d2, k)
}
}
return d1, d2
}
package util
import (
"fmt"
"net/http"
"net/url"
"testing"
"time"
)
func TestArrayContainsInterface(t *testing.T) {
var areaIds []time.Time
areaIds = append(areaIds, ParseDateTime("2022-02-09 22:09:12"))
areaIds = append(areaIds, ParseDateTime("2022-03-09 22:09:12"))
areaIds = append(areaIds, ParseDateTime("2022-12-09 22:09:12"))
fmt.Println(ArrayContains[time.Time](areaIds, ParseDateTime("2022-02-10 22:09:12")))
}
func TestDifference(t *testing.T) {
a1 := []int64{1, 5, 2, 3}
a2 := []int64{2, 1, 34, 3, 3, 4}
d1, d2 := DifferenceSet[int64](a1, a2)
fmt.Println("a1与a2的差集分别是:", d1, d2)
}
var client = http.Client{
Timeout: 10 * time.Second,
}
func TestPostJSONStr(t *testing.T) {
responseData, err := PostFormStr(client, "http://ex-test-dcxy-base-manage.168cad.top/v3/operate/balance/recharge/success", "{\"orderNo\":\"BRO165119944230021\"}", nil)
if err != nil {
fmt.Printf("错误:%s\n", err.Error())
}
fmt.Printf("请求结果:%s\n", string(responseData))
}
func TestGet(t *testing.T) {
apiUrl := "https://test-go-rym-oxygen-manage-service.168cad.top/oxygen/u/price/rule/detail/info"
p := url.Values{}
p.Add("id", "1")
responseData, err := Get(client, apiUrl, p)
if err != nil {
fmt.Printf("错误:%s\n", err.Error())
}
fmt.Printf("请求结果:%s\n", string(responseData))
}
func TestGetHeader(t *testing.T) {
apiUrl := "https://test-go-rym-oxygen-manage-service.168cad.top/oxygen/u/price/rule/detail/info"
p := url.Values{}
p.Add("id", "1")
header := map[string]string{}
header["token"] = "oxygen:login:token:91c6aff9d32fb16f0404874d60466041"
responseData, err := GetHeader(client, apiUrl, p, header)
if err != nil {
fmt.Printf("错误:%s\n", err.Error())
}
fmt.Printf("请求结果:%s\n", string(responseData))
}
package util
import (
"fmt"
"git.168cad.top/rym-open-source/rym-go-sdk/exception"
"math"
"time"
)
const formatSimple0 = "2006-01-02 15:04:05.000000"
const formatSimple1 = "2006-01-02 15:04:05"
const formatSimple2 = "2006-01-02"
const formatSimple3 = "20060102"
const DayStart = "00:00:00"
const DayEnd = "23:59:59"
func FormatDate(dateTime time.Time) string {
return dateTime.Format(formatSimple2)
}
func FormatDates(dateTime time.Time) string {
return dateTime.Format(formatSimple3)
}
func FormatDateTime(dateTime time.Time) string {
return dateTime.Format(formatSimple1)
}
func FormatDateMillTime(dateTime time.Time) string {
return dateTime.Format(formatSimple0)
}
func ParseDateStart(date string) time.Time {
stamp, err := time.ParseInLocation(formatSimple1, date+" 00:00:00", time.Local)
exception.AssertThrowable(err != nil, "SYSTEM_ERR.TIME_INVALID", fmt.Sprintf("[%s]时间格式错误", date))
return stamp
}
func ParseDateTime(dateTime string) time.Time {
stamp, err := time.ParseInLocation(formatSimple1, dateTime, time.Local)
exception.AssertThrowable(err != nil, "SYSTEM_ERR.TIME_INVALID", fmt.Sprintf("[%s]时间格式错误", dateTime))
return stamp
}
func ParseDateTimeE(dateTime string, name string) time.Time {
stamp, err := time.ParseInLocation(formatSimple1, dateTime, time.Local)
exception.AssertThrowable(err != nil, "SYSTEM_ERR.TIME_INVALID", fmt.Sprintf("%s格式错误", name))
return stamp
}
func AddDate(date time.Time, d int) time.Time {
t := (int64)(d * 24 * 60 * 60)
return Add(date, t)
}
func Add(date time.Time, d int64) time.Time {
t := date.Unix()
t += d //增加秒
return time.Unix(t, 0)
}
func Start(date time.Time) time.Time {
return time.Date(date.Year(), date.Month(), date.Day(), 0, 0, 0, 0, date.Location()) // 获取当天0点时间 time类型
}
func TimeSubDays(t1, t2 time.Time) int {
if t1.Location().String() != t2.Location().String() {
return -1
}
hours := t1.Sub(t2).Hours()
t1y, t1m, t1d := t1.Date()
t2y, t2m, t2d := t2.Date()
if t1y == t2y && t1m == t2m && t1d == t2d { //同一天
return 0
} else {
return int(hours/24 + 1)
}
}
// TimeSubMinute t1比t2多多少分钟,向上取整
func TimeSubMinute(t1, t2 *time.Time) int {
if t1.Location().String() != t2.Location().String() {
return -1
}
seconds := t1.Sub(*t2).Seconds()
return int(math.Ceil(seconds / 60)) //向上取整
}
// TimeSubMinuteFloor t1比t2多多少分钟,向上取整
func TimeSubMinuteFloor(t1, t2 *time.Time) int {
if t1.Location().String() != t2.Location().String() {
return -1
}
seconds := t1.Sub(*t2).Seconds()
return int(math.Floor(seconds / 60)) //向上取整
}
func MilSecond(time time.Time) int64 {
return time.UnixNano() / 1e6
}
package util
import (
"fmt"
"github.com/shopspring/decimal"
"strconv"
)
//FormatFloat64 将多余的浮点格式化
func FormatFloat64(f float64) string {
return strconv.FormatFloat(f, 'f', -1, 64)
}
//FormatFloat32 将多余的浮点格式化
func FormatFloat32(f float32) string {
return strconv.FormatFloat(float64(f), 'f', -1, 32)
}
// AddFloat64 精度加法 a+b
func AddFloat64(a *float64, b *float64) *float64 {
//r, _ := new(big.Float).Add(new(big.Float).SetFloat64(*a), new(big.Float).SetFloat64(*b)).Float64()
r, _ := decimal.NewFromFloat(*a).Add(decimal.NewFromFloat(*b)).Float64()
return &r
}
// SubtractFloat64 精度减法 a-b
func SubtractFloat64(a *float64, b *float64) *float64 {
//r, _ := new(big.Float).Sub(new(big.Float).SetFloat64(*a), new(big.Float).SetFloat64(*b)).Float64()
r, _ := decimal.NewFromFloat(*a).Sub(decimal.NewFromFloat(*b)).Float64()
return &r
}
// MultiplyFloat64 精度乘法 axb
func MultiplyFloat64(a *float64, b *float64) *float64 {
//r, _ := new(big.Float).Mul(new(big.Float).SetFloat64(*a), new(big.Float).SetFloat64(*b)).Float64()
r, _ := decimal.NewFromFloat(*a).Mul(decimal.NewFromFloat(*b)).Float64()
return &r
}
// DivideFloat64 精度除法 a/b
func DivideFloat64(a *float64, b *float64) *float64 {
//r, _ := new(big.Float).Quo(new(big.Float).SetFloat64(*a), new(big.Float).SetFloat64(*b)).Float64()
r, _ := decimal.NewFromFloat(*a).Div(decimal.NewFromFloat(*b)).Float64()
return &r
}
func yuanToFen(t float64) int64 {
value, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", *MultiplyFloat64(&t, Addr(float64(100)))), 64)
return int64(value + 0.5)
}
func fenToYuan(t int64) float64 {
value, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", *DivideFloat64(Addr(float64(t)), Addr(float64(100)))), 64)
return value
}
package util
import (
"bytes"
"encoding/json"
"fmt"
"git.168cad.top/rym-open-source/rym-go-sdk/exception"
"github.com/gin-gonic/gin"
"io"
"io/ioutil"
"net/http"
"net/url"
"strconv"
"strings"
)
func ParamInt64(c *gin.Context, key string) int64 {
return int64(ParamInt(c, key))
}
func ParamInt32(c *gin.Context, key string) int32 {
return int32(ParamInt(c, key))
}
func ParamInt16(c *gin.Context, key string) int16 {
return int16(ParamInt(c, key))
}
func ParamInt8(c *gin.Context, key string) int8 {
return int8(ParamInt(c, key))
}
func ParamUint64(c *gin.Context, key string) uint64 {
return uint64(ParamInt(c, key))
}
func ParamUint32(c *gin.Context, key string) uint32 {
return uint32(ParamInt(c, key))
}
func ParamUint16(c *gin.Context, key string) uint16 {
return uint16(ParamInt(c, key))
}
func ParamUint8(c *gin.Context, key string) uint8 {
return uint8(ParamInt(c, key))
}
func ParamInt(c *gin.Context, key string) int {
v := Param(c, key)
i, err := strconv.Atoi(v)
if err != nil {
exception.ThrowsErrS("PARAMS_ERR", "请传入正确的数字")
}
return i
}
func Param(c *gin.Context, key string) string {
v, ok := c.GetQuery(key)
if !ok || v == "" {
exception.ThrowsErrS("PARAMS_ERR", fmt.Sprintf("%s不能为空", key))
}
return v
}
const (
ApplicationJSON = "application/json"
XmlForm = "application/x-www-form-urlencoded;charset=utf-8"
)
func Get(client http.Client, apiUrl string, params url.Values) ([]byte, error) {
url := fmt.Sprintf("%s?%s", apiUrl, params.Encode())
rep, err := client.Get(url)
if err != nil {
return nil, err
}
defer rep.Body.Close()
data, err := io.ReadAll(rep.Body)
if err != nil {
return nil, err
}
return data, nil
}
func GetHeader(client http.Client, apiUrl string, params url.Values, header map[string]string) ([]byte, error) {
url := fmt.Sprintf("%s?%s", apiUrl, params.Encode())
request, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return nil, err
}
if header != nil {
for k, v := range header {
request.Header.Add(k, v)
}
}
response, err := client.Do(request)
if err != nil {
return nil, err
}
defer response.Body.Close()
data, err := ioutil.ReadAll(response.Body)
if err != nil {
return nil, err
}
return data, nil
}
func PostFormStr(client http.Client, url string, params string, header map[string]string) ([]byte, error) {
p := StrToUrlValue(params)
requestStr := p.Encode()
buf := strings.NewReader(requestStr)
request, err := http.NewRequest(http.MethodPost, url, buf)
if err != nil {
return nil, err
}
request.Header.Add("Content-Type", XmlForm)
if header != nil {
for k, v := range header {
request.Header.Add(k, v)
}
}
response, err := client.Do(request)
if err != nil {
return nil, err
}
defer response.Body.Close()
data, err := io.ReadAll(response.Body)
if err != nil {
return nil, err
}
return data, err
}
func PostJSONStr(client http.Client, url string, params string, header map[string]string) ([]byte, error) {
request, err := http.NewRequest(http.MethodPost, url, bytes.NewBufferString(params))
if err != nil {
return nil, err
}
request.Header.Add("Content-Type", ApplicationJSON)
if header != nil {
for k, v := range header {
request.Header.Add(k, v)
}
}
response, err := client.Do(request)
if err != nil {
return nil, err
}
defer response.Body.Close()
data, err := io.ReadAll(response.Body)
if err != nil {
return nil, err
}
return data, err
}
func PostJson(client http.Client, url string, params interface{}) ([]byte, error) {
return PostJsonHeader(client, url, params, nil)
}
func PostJsonHeader(client http.Client, url string, params interface{}, header map[string]string) ([]byte, error) {
buf := bytes.NewBuffer(nil)
encoder := json.NewEncoder(buf)
if err := encoder.Encode(params); err != nil {
return nil, err
}
request, err := http.NewRequest(http.MethodPost, url, buf)
if err != nil {
return nil, err
}
request.Header.Add("Content-Type", "application/json")
if header != nil {
for k, v := range header {
request.Header.Add(k, v)
}
}
response, err := client.Do(request)
if err != nil {
return nil, err
}
defer response.Body.Close()
data, err := ioutil.ReadAll(response.Body)
if err != nil {
return nil, err
}
return data, nil
}
package util
func If[K any](isTrue bool, a, b K) K {
if isTrue {
return a
}
return b
}
func IfNull[K any](a *K, defaultValue K) K {
if a == nil {
return defaultValue
}
return *a
}
package util
import (
"encoding/json"
"net/url"
"sort"
"strconv"
)
func ToMap(obj interface{}) map[string]interface{} {
m := make(map[string]interface{})
j, _ := json.Marshal(obj)
json.Unmarshal(j, &m)
return m
}
func StrToUrlValue(obj string) url.Values {
params := StrToMap(obj)
p := url.Values{}
for k, v := range params {
p.Add(k, GetInterfaceToString(v))
}
return p
}
func GetInterfaceToString(value interface{}) string {
var key string
if value == nil {
return key
}
switch value.(type) {
case float64:
ft := value.(float64)
key = strconv.FormatFloat(ft, 'f', -1, 64)
case float32:
ft := value.(float32)
key = strconv.FormatFloat(float64(ft), 'f', -1, 64)
case int:
it := value.(int)
key = strconv.Itoa(it)
case uint:
it := value.(uint)
key = strconv.Itoa(int(it))
case int8:
it := value.(int8)
key = strconv.Itoa(int(it))
case uint8:
it := value.(uint8)
key = strconv.Itoa(int(it))
case int16:
it := value.(int16)
key = strconv.Itoa(int(it))
case uint16:
it := value.(uint16)
key = strconv.Itoa(int(it))
case int32:
it := value.(int32)
key = strconv.Itoa(int(it))
case uint32:
it := value.(uint32)
key = strconv.Itoa(int(it))
case int64:
it := value.(int64)
key = strconv.FormatInt(it, 10)
case uint64:
it := value.(uint64)
key = strconv.FormatUint(it, 10)
case string:
key = value.(string)
case []byte:
key = string(value.([]byte))
default:
newValue, _ := json.Marshal(value)
key = string(newValue)
}
return key
}
func StrToMap(obj string) map[string]interface{} {
m := make(map[string]interface{})
json.Unmarshal([]byte(obj), &m)
return m
}
func StrToMapStr(obj string) map[string]string {
m := make(map[string]string)
json.Unmarshal([]byte(obj), &m)
return m
}
func ToObject(txt string, p interface{}) error {
err := json.Unmarshal([]byte(txt), p)
if err != nil {
return err
}
return nil
}
func SortKeys(orgMap map[string]interface{}) []string {
var keys []string
for key := range orgMap {
keys = append(keys, key)
}
sort.Strings(keys)
return keys
}
package util
import (
"crypto/md5"
"encoding/hex"
)
func Md5(s string) string {
h := md5.New()
h.Write([]byte(s))
r := hex.EncodeToString(h.Sum(nil))
return r
}
package util
import (
"os"
)
func Args(i int) string {
args := os.Args
if len(args) < i+1 {
return ""
}
return args[i]
}
package util
import (
"bytes"
"runtime"
"strconv"
)
func GetGID() uint64 {
b := make([]byte, 64)
b = b[:runtime.Stack(b, false)]
b = bytes.TrimPrefix(b, []byte("goroutine "))
b = b[:bytes.IndexByte(b, ' ')]
n, _ := strconv.ParseUint(string(b), 10, 64)
return n
}
package util
import (
"math/rand"
"strings"
)
// 生成: 时间戳 + 设置前缀 + 随即字符串
const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
func FandomString(strlen int) string {
result := make([]byte, strlen)
for i := 0; i < strlen; i++ {
result[i] = alphanum[rand.Intn(len(alphanum))]
}
return string(result)
}
func IsEmpty(s *string) bool {
return s == nil || *s == ""
}
func IsNil(i interface{}) bool {
if i == nil {
return true
}
return false
}
func ContainsForSplitComma(list, item string) bool {
return containsForSplit(list, item, ",")
}
func containsForSplit(list, item, character string) bool {
if !IsEmpty(&list) {
if strings.Contains(list, character) {
return strings.Index(list, item+character) == 0 ||
strings.Contains(list, character+item+character) ||
strings.Index(list, character+item) == len(list)-len(character+item)
} else {
return list == item
}
}
return false
}
func SubStr(str string, begin, end int) {
}
package util
import (
"fmt"
"testing"
)
func TestContainsForSplitComma(t *testing.T) {
a := "15"
b := "14"
fmt.Printf("%s是否包含在[%s]中:%v", a, b, ContainsForSplitComma(b, a))
}
type DefaultCount struct {
Count *int32 `gorm:"column:count" json:"count"` // 笔数
Money *float64 `gorm:"column:money" json:"money"` // 金额(元)
}
func TestStrval(t *testing.T) {
fmt.Printf("转换内容:%s", GetInterfaceToString(3.10))
var count DefaultCount
//a := If(count.Count == nil, 12, 0)
a := IfNull(count.Count, 0)
fmt.Printf("结果:%d", a)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment