提交 183e061b authored 作者: mooncake9527's avatar mooncake9527

update

上级 62016f9a
...@@ -175,15 +175,15 @@ func Logging(opts ...Option) gin.HandlerFunc { ...@@ -175,15 +175,15 @@ func Logging(opts ...Option) gin.HandlerFunc {
reqID := "" reqID := ""
if o.requestIDFrom == 1 { if o.requestIDFrom == 1 {
if v, isExist := c.Get(ctxUtil.ContextRequestIDKey); isExist { if v, isExist := c.Get(ctxUtil.ContextTraceIDKey); isExist {
if requestID, ok := v.(string); ok { if requestID, ok := v.(string); ok {
reqID = requestID reqID = requestID
fields = append(fields, zap.String(ctxUtil.ContextRequestIDKey, reqID)) fields = append(fields, zap.String(ctxUtil.ContextTraceIDKey, reqID))
} }
} }
} else if o.requestIDFrom == 2 { } else if o.requestIDFrom == 2 {
reqID = c.Request.Header.Get(ctxUtil.HeaderXRequestIDKey) reqID = c.Request.Header.Get(ctxUtil.HeaderXRequestIDKey)
fields = append(fields, zap.String(ctxUtil.ContextRequestIDKey, reqID)) fields = append(fields, zap.String(ctxUtil.ContextTraceIDKey, reqID))
} }
o.log.Info("<<<<<<<<<req", fields...) o.log.Info("<<<<<<<<<req", fields...)
...@@ -211,7 +211,7 @@ func Logging(opts ...Option) gin.HandlerFunc { ...@@ -211,7 +211,7 @@ func Logging(opts ...Option) gin.HandlerFunc {
zap.ByteString("body", getResponseBody(newWriter.body, o.maxLength)), zap.ByteString("body", getResponseBody(newWriter.body, o.maxLength)),
} }
if reqID != "" { if reqID != "" {
fields = append(fields, zap.String(ctxUtil.ContextRequestIDKey, reqID)) fields = append(fields, zap.String(ctxUtil.ContextTraceIDKey, reqID))
} }
o.log.Info(">>>>>>>>>rsp", fields...) o.log.Info(">>>>>>>>>rsp", fields...)
} }
...@@ -233,7 +233,7 @@ func SimpleLog(opts ...Option) gin.HandlerFunc { ...@@ -233,7 +233,7 @@ func SimpleLog(opts ...Option) gin.HandlerFunc {
reqID := "" reqID := ""
if o.requestIDFrom == 1 { if o.requestIDFrom == 1 {
if v, isExist := c.Get(ctxUtil.ContextRequestIDKey); isExist { if v, isExist := c.Get(ctxUtil.ContextTraceIDKey); isExist {
if requestID, ok := v.(string); ok { if requestID, ok := v.(string); ok {
reqID = requestID reqID = requestID
} }
...@@ -254,7 +254,7 @@ func SimpleLog(opts ...Option) gin.HandlerFunc { ...@@ -254,7 +254,7 @@ func SimpleLog(opts ...Option) gin.HandlerFunc {
zap.Int("size", c.Writer.Size()), zap.Int("size", c.Writer.Size()),
} }
if reqID != "" { if reqID != "" {
fields = append(fields, zap.String(ctxUtil.ContextRequestIDKey, reqID)) fields = append(fields, zap.String(ctxUtil.ContextTraceIDKey, reqID))
} }
o.log.Info("Gin msg", fields...) o.log.Info("Gin msg", fields...)
} }
......
...@@ -44,7 +44,7 @@ func runLogHTTPServer() string { ...@@ -44,7 +44,7 @@ func runLogHTTPServer() string {
//)) //))
helloFun := func(c *gin.Context) { helloFun := func(c *gin.Context) {
logger.Info("test request id", ctxUtil.GCtxRequestIDField(c)) logger.Info("test request id", ctxUtil.GinTraceIDField(c))
response.Success(c, "hello world") response.Success(c, "hello world")
} }
......
package middleware package middleware
import ( import (
ctxUtil "gitlab.wanzhuangkj.com/tush/xpkg/gin/xctx"
"net/http" "net/http"
ctxUtil "gitlab.wanzhuangkj.com/tush/xpkg/gin/xctx"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"go.uber.org/zap" "go.uber.org/zap"
) )
...@@ -16,7 +17,7 @@ func CustomRecoveryWithLogger(logger *zap.Logger) gin.HandlerFunc { ...@@ -16,7 +17,7 @@ func CustomRecoveryWithLogger(logger *zap.Logger) gin.HandlerFunc {
zap.String("client_ip", c.ClientIP()), zap.String("client_ip", c.ClientIP()),
zap.Any("error", err), zap.Any("error", err),
zap.Stack("stack"), zap.Stack("stack"),
ctxUtil.GCtxRequestIDField(c), ctxUtil.GinTraceIDField(c),
) )
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{ c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
"code": 500, "code": 500,
......
...@@ -2,9 +2,10 @@ package middleware ...@@ -2,9 +2,10 @@ package middleware
import ( import (
"context" "context"
ctxUtil "gitlab.wanzhuangkj.com/tush/xpkg/gin/xctx"
"net/http" "net/http"
ctxUtil "gitlab.wanzhuangkj.com/tush/xpkg/gin/xctx"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"go.uber.org/zap" "go.uber.org/zap"
) )
...@@ -19,7 +20,7 @@ type requestIDOptions struct { ...@@ -19,7 +20,7 @@ type requestIDOptions struct {
func defaultRequestIDOptions() *requestIDOptions { func defaultRequestIDOptions() *requestIDOptions {
return &requestIDOptions{ return &requestIDOptions{
contextRequestIDKey: ctxUtil.ContextRequestIDKey, contextRequestIDKey: ctxUtil.ContextTraceIDKey,
headerXRequestIDKey: ctxUtil.HeaderXRequestIDKey, headerXRequestIDKey: ctxUtil.HeaderXRequestIDKey,
} }
} }
...@@ -31,8 +32,8 @@ func (o *requestIDOptions) apply(opts ...RequestIDOption) { ...@@ -31,8 +32,8 @@ func (o *requestIDOptions) apply(opts ...RequestIDOption) {
} }
func (o *requestIDOptions) setRequestIDKey() { func (o *requestIDOptions) setRequestIDKey() {
if o.contextRequestIDKey != ctxUtil.ContextRequestIDKey { if o.contextRequestIDKey != ctxUtil.ContextTraceIDKey {
ctxUtil.ContextRequestIDKey = o.contextRequestIDKey ctxUtil.ContextTraceIDKey = o.contextRequestIDKey
} }
if o.headerXRequestIDKey != ctxUtil.HeaderXRequestIDKey { if o.headerXRequestIDKey != ctxUtil.HeaderXRequestIDKey {
ctxUtil.HeaderXRequestIDKey = o.headerXRequestIDKey ctxUtil.HeaderXRequestIDKey = o.headerXRequestIDKey
...@@ -63,7 +64,7 @@ func WithHeaderRequestIDKey(key string) RequestIDOption { ...@@ -63,7 +64,7 @@ func WithHeaderRequestIDKey(key string) RequestIDOption {
type CtxKeyString string type CtxKeyString string
// RequestIDKey request_id // RequestIDKey request_id
var RequestIDKey = CtxKeyString(ctxUtil.ContextRequestIDKey) var RequestIDKey = CtxKeyString(ctxUtil.ContextTraceIDKey)
// ------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
...@@ -85,7 +86,7 @@ func RequestID(opts ...RequestIDOption) gin.HandlerFunc { ...@@ -85,7 +86,7 @@ func RequestID(opts ...RequestIDOption) gin.HandlerFunc {
} }
// Expose it for use in the application // Expose it for use in the application
c.Set(ctxUtil.ContextRequestIDKey, requestID) c.Set(ctxUtil.ContextTraceIDKey, requestID)
// Set X-Request-Id header // Set X-Request-Id header
c.Writer.Header().Set(ctxUtil.HeaderXRequestIDKey, requestID) c.Writer.Header().Set(ctxUtil.HeaderXRequestIDKey, requestID)
...@@ -111,7 +112,7 @@ var RequestHeaderKey = "request_header_key" ...@@ -111,7 +112,7 @@ var RequestHeaderKey = "request_header_key"
// WrapCtx wrap context, put the Keys and Header of gin.Context into context // WrapCtx wrap context, put the Keys and Header of gin.Context into context
func WrapCtx(c *gin.Context) context.Context { func WrapCtx(c *gin.Context) context.Context {
ctx := context.WithValue(c.Request.Context(), ctxUtil.ContextRequestIDKey, c.GetString(ctxUtil.ContextRequestIDKey)) //nolint ctx := context.WithValue(c.Request.Context(), ctxUtil.ContextTraceIDKey, c.GetString(ctxUtil.ContextTraceIDKey)) //nolint
for k, v := range c.Keys { for k, v := range c.Keys {
ctx = context.WithValue(ctx, k, v) //nolint ctx = context.WithValue(ctx, k, v) //nolint
} }
......
...@@ -58,7 +58,7 @@ func TestFieldRequestIDFromContext(t *testing.T) { ...@@ -58,7 +58,7 @@ func TestFieldRequestIDFromContext(t *testing.T) {
c.Set("foo", "bar") c.Set("foo", "bar")
ctx := WrapCtx(c) ctx := WrapCtx(c)
t.Log(ctx.Value(ctxUtil.ContextRequestIDKey)) t.Log(ctx.Value(ctxUtil.ContextTraceIDKey))
t.Log(GetFromCtx(ctx, "foo")) t.Log(GetFromCtx(ctx, "foo"))
t.Log(ctxUtil.CtxTraceIDField(ctx)) t.Log(ctxUtil.CtxTraceIDField(ctx))
t.Log(GetFromCtx(ctx, "not-exist")) t.Log(GetFromCtx(ctx, "not-exist"))
...@@ -71,7 +71,7 @@ func TestFieldRequestIDFromContext(t *testing.T) { ...@@ -71,7 +71,7 @@ func TestFieldRequestIDFromContext(t *testing.T) {
cctx := c cctx := c
c2, ctx2 := AdaptCtx(cctx) c2, ctx2 := AdaptCtx(cctx)
t.Log(ctxUtil.CtxRequestID(c2)) t.Log(ctxUtil.CtxRequestID(c2))
t.Log(ctx2.Value(ctxUtil.ContextRequestIDKey)) t.Log(ctx2.Value(ctxUtil.ContextTraceIDKey))
}) })
_, err := http.Get(requestAddr + "/ping") _, err := http.Get(requestAddr + "/ping")
...@@ -106,8 +106,8 @@ func TestRequestIDKeyOptions(t *testing.T) { ...@@ -106,8 +106,8 @@ func TestRequestIDKeyOptions(t *testing.T) {
o.apply(opts...) o.apply(opts...)
o.setRequestIDKey() o.setRequestIDKey()
t.Log(ctxUtil.ContextRequestIDKey, ctxUtil.HeaderXRequestIDKey) t.Log(ctxUtil.ContextTraceIDKey, ctxUtil.HeaderXRequestIDKey)
assert.Equal(t, "my_req_id", ctxUtil.ContextRequestIDKey) assert.Equal(t, "my_req_id", ctxUtil.ContextTraceIDKey)
assert.Equal(t, "My-X-Req-Id", ctxUtil.HeaderXRequestIDKey) assert.Equal(t, "My-X-Req-Id", ctxUtil.HeaderXRequestIDKey)
} }
...@@ -178,10 +178,10 @@ func Error(c *gin.Context, err error) { ...@@ -178,10 +178,10 @@ func Error(c *gin.Context, err error) {
msg = err.Error() msg = err.Error()
if xerr, ok := err.(*xerror.Error); ok { if xerr, ok := err.(*xerror.Error); ok {
if !errcode.IsSysDefinedError(xerr.Code()) { if !errcode.IsSysDefinedError(xerr.Code()) {
logger.Error("api failed.", logger.Err(err), ctxUtil.GCtxRequestIDField(c)) logger.Error("api failed.", logger.Err(err), ctxUtil.GinTraceIDField(c))
} }
} else { } else {
logger.Error("api failed.", logger.Err(err), ctxUtil.GCtxRequestIDField(c)) logger.Error("api failed.", logger.Err(err), ctxUtil.GinTraceIDField(c))
} }
} }
// 使用respJSONWith200函数返回错误信息。 // 使用respJSONWith200函数返回错误信息。
......
...@@ -2,6 +2,7 @@ package xctx ...@@ -2,6 +2,7 @@ package xctx
import ( import (
"context" "context"
"errors"
xsf "gitlab.wanzhuangkj.com/tush/xpkg/utils/xsf" xsf "gitlab.wanzhuangkj.com/tush/xpkg/utils/xsf"
...@@ -13,26 +14,31 @@ import ( ...@@ -13,26 +14,31 @@ import (
var ( var (
GinContextKey = "gin_context" GinContextKey = "gin_context"
// ContextRequestIDKey request id for context ContextTraceIDKey = "traceID"
ContextRequestIDKey = "traceID" KeyConfigFile = "config_file"
KeyConfigFile = "config_file" KeyConfigCenter = "config_center"
KeyConfigCenter = "config_center"
// HeaderXRequestIDKey header request id key // HeaderXRequestIDKey header request id key
HeaderXRequestIDKey = "X-Request-ID" HeaderXRequestIDKey = "X-Request-ID"
KeyTid = "tid" KeyTid = "tid"
KeyIP = "ip" KeyIP = "IP"
KeyUID = "uid" KeyUID = "userId"
KeyShopID = "shopID" KeyUType = "userType"
KeyUName = "uname" KeyCompanyID = "companyId"
KeyToken = "token" KeyShopID = "shopID"
KeyUser = "user" KeyUName = "uname"
KeyToken = "token"
KeyUser = "user"
) )
// GCtxRequestID get request id from gin.Context var (
func GCtxRequestID(c *gin.Context) string { ErrorGinContextNotFound = errors.New("gin context not found")
if v, isExist := c.Get(ContextRequestIDKey); isExist { )
// GetGinCtxTraceID get request id from gin.Context
func GetGinCtxTraceID(c *gin.Context) string {
if v, isExist := c.Get(ContextTraceIDKey); isExist {
if requestID, ok := v.(string); ok { if requestID, ok := v.(string); ok {
return requestID return requestID
} }
...@@ -40,14 +46,14 @@ func GCtxRequestID(c *gin.Context) string { ...@@ -40,14 +46,14 @@ func GCtxRequestID(c *gin.Context) string {
return "" return ""
} }
// GCtxRequestIDField get request id field from gin.Context // GinTraceIDField get request id field from gin.Context
func GCtxRequestIDField(c *gin.Context) zap.Field { func GinTraceIDField(c *gin.Context) zap.Field {
return zap.String(ContextRequestIDKey, GCtxRequestID(c)) return zap.String(ContextTraceIDKey, GetGinCtxTraceID(c))
} }
// CtxRequestID get request id from context.Context // CtxRequestID get request id from context.Context
func CtxRequestID(c context.Context) string { func CtxRequestID(c context.Context) string {
v := c.Value(ContextRequestIDKey) v := c.Value(ContextTraceIDKey)
if str, ok := v.(string); ok { if str, ok := v.(string); ok {
return str return str
} }
...@@ -72,7 +78,7 @@ func CtxGetGinCtx(c context.Context) *gin.Context { ...@@ -72,7 +78,7 @@ func CtxGetGinCtx(c context.Context) *gin.Context {
// CtxTraceIDField get request id field from context.Context // CtxTraceIDField get request id field from context.Context
func CtxTraceIDField(c context.Context) zap.Field { func CtxTraceIDField(c context.Context) zap.Field {
return zap.String(ContextRequestIDKey, CtxRequestID(c)) return zap.String(ContextTraceIDKey, CtxRequestID(c))
} }
func GetGinUserID(c *gin.Context) xsf.ID { func GetGinUserID(c *gin.Context) xsf.ID {
...@@ -162,10 +168,48 @@ func GetIP(ctx context.Context) string { ...@@ -162,10 +168,48 @@ func GetIP(ctx context.Context) string {
} }
func WrapCtx(c *gin.Context) context.Context { func WrapCtx(c *gin.Context) context.Context {
ctx := context.WithValue(c.Request.Context(), ContextRequestIDKey, c.GetString(ContextRequestIDKey)) //nolint ctx := context.WithValue(c.Request.Context(), ContextTraceIDKey, c.GetString(ContextTraceIDKey)) //nolint
for k, v := range c.Keys { for k, v := range c.Keys {
ctx = context.WithValue(ctx, k, v) //nolint ctx = context.WithValue(ctx, k, v) //nolint
} }
ctx = context.WithValue(ctx, GinContextKey, c) //nolint ctx = context.WithValue(ctx, GinContextKey, c) //nolint
return ctx return ctx
} }
func ToGinCtx(ctx context.Context) (*gin.Context, error) {
if c, ok := ctx.Value(GinContextKey).(*gin.Context); ok {
return c, nil
}
return nil, ErrorGinContextNotFound
}
func GetCtxUID(c context.Context) uint {
uid := c.Value(KeyUID)
if uid != nil {
if v, ok := uid.(string); ok {
return cast.ToUint(v)
}
}
return 0
}
func GetCtxUType(c context.Context) int {
val := c.Value(KeyUType)
if val != nil {
if v, ok := val.(string); ok {
return cast.ToInt(v)
}
}
return 0
}
func GetCtxCompanyID(c context.Context) uint {
val := c.Value(KeyCompanyID)
if val != nil {
v, ok := val.(string)
if ok {
return cast.ToUint(v)
}
}
return 0
}
...@@ -13,9 +13,9 @@ import ( ...@@ -13,9 +13,9 @@ import (
"strings" "strings"
"time" "time"
ctxUtil "gitlab.wanzhuangkj.com/tush/xpkg/gin/xctx" "gitlab.wanzhuangkj.com/tush/xpkg/gin/xctx"
"gitlab.wanzhuangkj.com/tush/xpkg/logger"
"gitlab.wanzhuangkj.com/tush/xpkg/utils/xjson" "gitlab.wanzhuangkj.com/tush/xpkg/utils/xjson"
"gitlab.wanzhuangkj.com/tush/xpkg/logger"
"gitlab.wanzhuangkj.com/tush/xpkg/xerrors/xerror" "gitlab.wanzhuangkj.com/tush/xpkg/xerrors/xerror"
"github.com/duke-git/lancet/v2/retry" "github.com/duke-git/lancet/v2/retry"
...@@ -250,6 +250,7 @@ func (req *Request) push(ctx context.Context) (*Response, error) { ...@@ -250,6 +250,7 @@ func (req *Request) push(ctx context.Context) (*Response, error) {
buf = bytes.NewBufferString(req.body) buf = bytes.NewBufferString(req.body)
} }
logger.Info("httpcli req", logger.String("body", buf.String()), xctx.CtxTraceIDField(ctx))
return req.send(ctx, buf, buf) return req.send(ctx, buf, buf)
} }
...@@ -285,6 +286,7 @@ func getRequestBody(buf *bytes.Buffer, maxLen int) []byte { ...@@ -285,6 +286,7 @@ func getRequestBody(buf *bytes.Buffer, maxLen int) []byte {
} }
func (req *Request) send(ctx context.Context, body io.Reader, buf *bytes.Buffer) (*Response, error) { func (req *Request) send(ctx context.Context, body io.Reader, buf *bytes.Buffer) (*Response, error) {
logger.Info("httpcli req", logger.String("url", req.url), xctx.CtxTraceIDField(ctx))
req.request, req.err = http.NewRequest(req.method, req.url, body) req.request, req.err = http.NewRequest(req.method, req.url, body)
if req.err != nil { if req.err != nil {
return nil, req.err return nil, req.err
...@@ -300,7 +302,7 @@ func (req *Request) send(ctx context.Context, body io.Reader, buf *bytes.Buffer) ...@@ -300,7 +302,7 @@ func (req *Request) send(ctx context.Context, body io.Reader, buf *bytes.Buffer)
} }
} }
req.request.Header.Add(ctxUtil.HeaderXRequestIDKey, ctxUtil.CtxRequestID(ctx)) req.request.Header.Add(xctx.HeaderXRequestIDKey, xctx.CtxRequestID(ctx))
if req.timeout < 1 { if req.timeout < 1 {
req.timeout = defaultTimeout req.timeout = defaultTimeout
...@@ -313,34 +315,28 @@ func (req *Request) send(ctx context.Context, body io.Reader, buf *bytes.Buffer) ...@@ -313,34 +315,28 @@ func (req *Request) send(ctx context.Context, body io.Reader, buf *bytes.Buffer)
ctx, cancel := context.WithTimeout(ctx, time.Second*20) ctx, cancel := context.WithTimeout(ctx, time.Second*20)
defer cancel() defer cancel()
err := retry.Retry(func() error { err := retry.Retry(func() error {
logger.Info("http call req", logger.String("req", req.ReqString(ctx)), ctxUtil.CtxTraceIDField(ctx)) response, err := client.Do(req.request)
var response *http.Response if err != nil {
response, resp.err = client.Do(req.request) logger.Info("httpcli fail", logger.Any("err", err), xctx.CtxTraceIDField(ctx))
if resp.err != nil { return xerror.New(err.Error())
return xerror.New(resp.err.Error())
} }
resp.Status = response.Status resp.Status = response.Status
resp.StatusCode = response.StatusCode resp.StatusCode = response.StatusCode
for k, v := range response.Header { for k, v := range response.Header {
resp.Header[k] = v resp.Header[k] = v
} }
logger.Info("http call rsp", logger.Any("status", resp.Status), logger.Any("statusCode", resp.StatusCode), logger.Any("header", response.Header), ctxUtil.CtxTraceIDField(ctx))
if resp.err != nil {
logger.Info("http call", logger.Any("err", resp.err), ctxUtil.CtxTraceIDField(ctx))
return resp.err
}
defer response.Body.Close() defer response.Body.Close()
body, err := io.ReadAll(response.Body) body, err := io.ReadAll(response.Body)
if err != nil { if err != nil {
return xerror.New(err.Error()) return xerror.New(err.Error())
} }
logger.Info("http call rsp", logger.Any("rsp body", bytes.NewBuffer(body).String()), ctxUtil.CtxTraceIDField(ctx)) logger.Info("httpcli rsp", logger.Any("body", bytes.NewBuffer(body).String()), xctx.CtxTraceIDField(ctx))
resp.Body = io.NopCloser(bytes.NewBuffer(body)) resp.Body = io.NopCloser(bytes.NewBuffer(body))
return nil return nil
}, retry.RetryWithLinearBackoff(time.Second), retry.Context(ctx)) }, retry.RetryWithLinearBackoff(time.Second), retry.Context(ctx))
if err != nil { if err != nil {
err = xerror.New(err.Error()) err = xerror.New(err.Error())
logger.Error("http fail", logger.Any("err", err), ctxUtil.CtxTraceIDField(ctx)) logger.Error("httpcli fail", logger.Any("err", err), xctx.CtxTraceIDField(ctx))
} }
req.response = resp req.response = resp
...@@ -590,5 +586,12 @@ type StdResult struct { ...@@ -590,5 +586,12 @@ type StdResult struct {
Data interface{} `json:"data,omitempty"` Data interface{} `json:"data,omitempty"`
} }
// StdResult standard return data
type StdResult2 struct {
Code int `json:"code"`
Msg string `json:"message"`
Data interface{} `json:"data,omitempty"`
}
// KV string:interface{} // KV string:interface{}
type KV = map[string]interface{} type KV = map[string]interface{}
...@@ -14,9 +14,9 @@ import ( ...@@ -14,9 +14,9 @@ import (
"strings" "strings"
"time" "time"
"gopkg.in/natefinch/lumberjack.v2"
"go.uber.org/zap" "go.uber.org/zap"
"go.uber.org/zap/zapcore" "go.uber.org/zap/zapcore"
"gopkg.in/natefinch/lumberjack.v2"
) )
const ( const (
...@@ -213,3 +213,12 @@ func (w *ZapWriter) Write(p []byte) (n int, err error) { ...@@ -213,3 +213,12 @@ func (w *ZapWriter) Write(p []byte) (n int, err error) {
} }
return len(p), nil return len(p), nil
} }
type ConfLog struct {
Level string
Path string
Max_size int
Max_backups int
Max_days int
Compress bool
}
...@@ -2,6 +2,8 @@ package xjson ...@@ -2,6 +2,8 @@ package xjson
import ( import (
"encoding/json" "encoding/json"
"gitlab.wanzhuangkj.com/tush/xpkg/xerrors/xerror"
) )
func ToJsonString(v any) string { func ToJsonString(v any) string {
...@@ -15,3 +17,11 @@ func ToJsonBytes(v any) []byte { ...@@ -15,3 +17,11 @@ func ToJsonBytes(v any) []byte {
bytes, _ := json.Marshal(v) bytes, _ := json.Marshal(v)
return bytes return bytes
} }
func Unmarshal(data []byte, v any) error {
err := json.Unmarshal(data, v)
if err != nil {
return xerror.New(err.Error())
}
return nil
}
...@@ -247,3 +247,32 @@ func CompareSlice[T IIDTable, BizSlice ~[]*T](ids []xsf.ID, bizSlice BizSlice, e ...@@ -247,3 +247,32 @@ func CompareSlice[T IIDTable, BizSlice ~[]*T](ids []xsf.ID, bizSlice BizSlice, e
} }
return nil return nil
} }
func ArrayUnique[T comparable](array []T) []T {
mp := make(map[T]struct{})
idx := 0
for _, value := range array {
if _, ok := mp[value]; ok {
continue
}
array[idx] = value
idx = idx + 1
mp[value] = struct{}{}
}
return array[:idx]
}
type IId interface {
GetID() uint
}
func GetIds[T IId](rs []*T) []uint {
if len(rs) == 0 {
return nil
}
set := xset.NewSet[uint]()
for _, r := range rs {
set.Add((*r).GetID())
}
return set.ToList()
}
...@@ -4,6 +4,17 @@ import ( ...@@ -4,6 +4,17 @@ import (
"strings" "strings"
) )
func CamelToUnderscore(s string) string {
var builder strings.Builder
for i, c := range s {
if i > 0 && c >= 'A' && c <= 'Z' {
builder.WriteByte('_')
}
builder.WriteRune(c)
}
return strings.ToLower(builder.String())
}
func UnderscoreToCamel(s string, isUpperFirst bool) string { func UnderscoreToCamel(s string, isUpperFirst bool) string {
var builder strings.Builder var builder strings.Builder
words := strings.Split(s, "_") words := strings.Split(s, "_")
......
...@@ -163,3 +163,215 @@ func ParseExtendedDuration(s string) (time.Duration, error) { ...@@ -163,3 +163,215 @@ func ParseExtendedDuration(s string) (time.Duration, error) {
return total, nil return total, nil
} }
const (
Layout_YYYY = "2006"
Layout_YYYYMM = "2006-01"
Layout_YYYYMMDD = "2006-01-02"
Layout_YYYYMMDD2 = "2006/01/02"
Layout_YYYYMMDD3 = "20060102"
Layout_YYYYMMDDHHmmSS = "2006-01-02 15:04:05"
)
var (
LocBeiJing, _ = time.LoadLocation("Asia/Shanghai")
)
func (x DateTime) Format(layout string) string {
return x.Time().Format(layout)
}
func (x DateTime) FormatYYYYMMDDHHmmSS() string {
return x.Time().Format(Layout_YYYYMMDDHHmmSS)
}
// const TimeFormat = "2006-01-02 15:04:05"
// // Value insert timestamp into mysql need this function.
// func (t DateTime) Value() (driver.Value, error) {
// var zeroTime time.Time
// if time.Time(t).UnixNano() == zeroTime.UnixNano() {
// return nil, nil
// }
// return time.Time(t), nil
// }
// // Scan value of time.Time
// func (t *DateTime) Scan(v interface{}) error {
// value, ok := v.(time.Time)
// if ok {
// *t = DateTime(value)
// return nil
// }
// return fmt.Errorf("can not convert %v to timestamp", v)
// }
func (x DateTime) Date() DateTime {
y, m, d := x.Time().Date()
trimmedTime := time.Date(y, m, d, 0, 0, 0, 0, x.Time().Location())
return NewDateTime(trimmedTime)
}
func (x DateTime) WeekStart() DateTime {
return x.WeekEnd().AddDate(0, 0, -6)
}
func (x DateTime) WeekEnd() DateTime {
weekday := int(x.Time().Weekday())
if weekday == 0 {
weekday = 7
}
return x.AddDate(0, 0, +7-weekday)
}
func (t0 DateTime) MonthStart() DateTime {
year, month, _ := t0.Time().Date()
t1 := time.Date(year, month, 1, 0, 0, 0, 0, t0.Time().Location())
return DateTime(t1)
}
func (t0 DateTime) MonthEnd() DateTime {
year, month, _ := t0.Time().Date()
t1 := time.Date(year, month+1, 0, 0, 0, 0, 0, t0.Time().Location())
return DateTime(t1)
}
func (t DateTime) AddDate(y, m, d int) DateTime {
return DateTime(t.Time().AddDate(y, m, d))
}
// WeekDay 1-7 周一到周日
func (x DateTime) WeekDay() int {
return ((int(x.Time().Weekday()) + 6) % 7) + 1
}
// 1-31 1号到31号
func (x DateTime) Day() int {
return int(x.Time().Day())
}
// 1-12 1月到12月
func (x DateTime) Month() int {
return int(x.Time().Month())
}
// 1970年到现在第几年
func (x DateTime) Year() int {
return int(x.Time().Year())
}
func (x DateTime) After(t1 DateTime) bool {
return x.Time().After(t1.Time())
}
// 转为北京时间
func (x DateTime) LocalBeiJing() DateTime {
return DateTime(x.Time().In(LocBeiJing))
}
func (x DateTime) Local() DateTime {
return DateTime(x.Time().In(time.Local))
}
func (x DateTime) Quarter() int {
return (int(x.Time().Month())-1)/3 + 1
}
func ParseYYYYMMDD(value string) DateTime {
t, err := time.Parse(Layout_YYYYMMDD, value)
if err != nil {
return DateTime{}
}
return DateTime(t)
}
func ParseYYYYMMDDHHmmSS(value string) DateTime {
t, err := time.Parse(Layout_YYYYMMDDHHmmSS, value)
if err != nil {
return DateTime{}
}
return DateTime(t)
}
func ParseTime(layout, value string) (DateTime, error) {
t, err := time.Parse(layout, value)
if err != nil {
return DateTime{}, err
}
return DateTime(t), nil
}
func IsSameDay(t1, t2 DateTime) bool {
t1Local := t1.Local()
t2Local := t2.Local()
return t1Local.Year() == t2Local.Year() &&
t1Local.Month() == t2Local.Month() &&
t1Local.Day() == t2Local.Day()
}
// 是否同一周
func IsSameWeek(t0, t1 DateTime) bool {
y1, w1 := t0.Time().Local().ISOWeek()
y2, w2 := t1.Time().Local().ISOWeek()
return y1 == y2 && w1 == w2
}
func NotSameWeek(t0, t1 DateTime) bool {
return !IsSameWeek(t0, t1)
}
// 是否同一个月
func IsSameMonth(t0, t1 DateTime) bool {
return t0.Month() == t1.Month()
}
func NotSameMonth(t0, t1 DateTime) bool {
return !IsSameMonth(t0, t1)
}
// 是否同一季度
func IsSameQuarter(t0, t1 DateTime) bool {
return t0.Quarter() == t1.Quarter()
}
func NotSameSeason(t0, t1 DateTime) bool {
return !IsSameQuarter(t0, t1)
}
// 是否同一年
func IsSameYear(t0, t1 DateTime) bool {
return t0.Time().Year() == t1.Time().Year()
}
func NotSameYear(t0, t1 DateTime) bool {
return !IsSameYear(t0, t1)
}
func DayBeforeYesterday() DateTime {
return DateTime(time.Now().AddDate(0, 0, -2))
}
func Yesterday() DateTime {
return DateTime(time.Now().AddDate(0, 0, -1))
}
func Today() DateTime {
return DateTime(time.Now())
}
func (t0 DateTime) PreviousQuarter(n int) DateTime {
month := t0.Month()
quarterStartMonth := time.Month((int(month)-1)/3*3 + 1)
currentQuarterStart := time.Date(
t0.Year(), quarterStartMonth, 1,
0, 0, 0, 0, t0.Time().Location(),
)
return DateTime(currentQuarterStart.AddDate(0, -3*n, 0))
}
func (t0 DateTime) FormatYYYYQT() string {
month := t0.Month()
quarter := (int(month)-1)/3 + 1
return fmt.Sprintf("%s_%d", t0.Format(Layout_YYYY), quarter)
}
func DaysBetween(t0, t1 DateTime) int {
t2 := time.Date(t0.Year(), t0.Time().Month(), t0.Day(), 0, 0, 0, 0, t0.Time().Location())
t3 := time.Date(t1.Year(), t1.Time().Month(), t1.Day(), 0, 0, 0, 0, t1.Time().Location())
diff := t2.Sub(t3)
days := int(diff.Hours() / 24)
return days
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论