基于(robfig_cron开发一个小工具)
1 2 3
| go get github.com/robfig/cron/v3@v3.0.0
import "github.com/robfig/cron/v3"
|
util
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
| package util
import ( "github.com/pkg/errors" cron "github.com/robfig/cron/v3" "sync" )
type Crontab struct { inner *cron.Cron ids map[string]cron.EntryID mutex sync.Mutex }
func NewCrontab() *Crontab { return &Crontab{ inner: cron.New(), ids: make(map[string]cron.EntryID), } }
func (c *Crontab) IDs() []string { c.mutex.Lock() defer c.mutex.Unlock() validIDs := make([]string, 0, len(c.ids)) invalidIDs := make([]string, 0) for sid, eid := range c.ids { if e := c.inner.Entry(eid); e.ID != eid { invalidIDs = append(invalidIDs, sid) continue } validIDs = append(validIDs, sid) } for _, id := range invalidIDs { delete(c.ids, id) } return validIDs }
func (c *Crontab) Start() { c.inner.Start() }
func (c *Crontab) Stop() { c.inner.Stop() }
func (c *Crontab) DelByID(id string) { c.mutex.Lock() defer c.mutex.Unlock()
eid, ok := c.ids[id] if !ok { return } c.inner.Remove(eid) delete(c.ids, id) }
func (c *Crontab) AddByID(id string, spec string, cmd cron.Job) error { c.mutex.Lock() defer c.mutex.Unlock()
if _, ok := c.ids[id]; ok { return errors.Errorf("crontab id exists") } eid, err := c.inner.AddJob(spec, cmd) if err != nil { return err } c.ids[id] = eid return nil }
func (c *Crontab) AddByFunc(id string, spec string, f func()) error { c.mutex.Lock() defer c.mutex.Unlock()
if _, ok := c.ids[id]; ok { return errors.Errorf("crontab id exists") } eid, err := c.inner.AddFunc(spec, f) if err != nil { return err } c.ids[id] = eid return nil }
func (c *Crontab) IsExists(jid string) bool { _, exist := c.ids[jid] return exist }
|
使用
1 2 3 4 5 6 7 8
| func main() { crontab := util.NewCrontab() crontab.AddByFunc(accAlert.ID, "0 */12 * * *", func() { fmt.Print("测试!!!") }) crontab.Start() select {} }
|
结合泛型和reflect写一个groupBy的工具类
1.18出来了,把之前一堆groupBy的代码拿出来用泛型改一下,效率可能略有下降,但是小频率使用,效果还行
**注:**这里的T必须是struct,而且key必须是string
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| func GroupByMap[T interface{}](values []*T, key string) map[string][]*T { mapObj := make(map[string][]*T) for _, groupKey := range removeRepeatedElement(values, key) { arr := filter(values, key, groupKey) mapObj[groupKey] = arr } return mapObj }
func filter[T interface{}](arr []*T, key, keyAsVal string) (newArr []*T) { newArr = make([]*T, 0) for _, item := range arr { itemVal := reflect.ValueOf(item).Elem().FieldByName(key).String() if itemVal == keyAsVal { newArr = append(newArr, item) } } return newArr }
func removeRepeatedElement[T interface{}](arr []*T, key string) (newArr []string) { newArr = make([]string, 0) for i := 0; i < len(arr); i++ { repeat := false ikeyAsVal := reflect.ValueOf(arr[i]).Elem().FieldByName(key).String() for j := i + 1; j < len(arr); j++ { jkeyAsVal := reflect.ValueOf(arr[j]).Elem().FieldByName(key).String() if ikeyAsVal == jkeyAsVal { repeat = true break } } if !repeat { newArr = append(newArr, ikeyAsVal) } } return newArr }
|
统一结果响应,统一异常处理
定义统一响应体(包含code, msg, data和WithData / WithMsg方法)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| package config
import ( "encoding/json" "net/http" )
var ( OK = response(http.StatusOK, "ok") )
type Response struct { Code int `json:"code"` Msg string `json:"msg"` Data interface{} `json:"data"` }
func (res *Response) WithMsg(message string) Response { return Response{ Code: res.Code, Msg: message, Data: res.Data, } }
func (res *Response) WithData(data interface{}) Response { return Response{ Code: res.Code, Msg: res.Msg, Data: data, } }
func (res *Response) ToString() string { err := &struct { Code int `json:"code"` Msg string `json:"msg"` Data interface{} `json:"data"` }{ Code: res.Code, Msg: res.Msg, Data: res.Data, } raw, _ := json.Marshal(err) return string(raw) }
func response(code int, msg string) *Response { return &Response{ Code: code, Msg: msg, Data: nil, } }
|
使用
1 2 3 4
| func load(c *gin.Context) error { c.JSON(http.StatusOK, config.OK.WithData(...)) return nil }
|
定义响应错误的结构体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package config
import ( "github.com/gin-gonic/gin" )
type APIException struct { *Response }
func (e *APIException) Error() string { return e.Msg }
func newAPIException(code int, msg string) *APIException { return &APIException{ &Response{ Code: code, Msg: msg, }, } }
type HandlerFunc func(c *gin.Context) error
|
异常处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| package config
import ( "github.com/gin-gonic/gin" "net/http" )
func Wrapper(handler HandlerFunc) func(c *gin.Context) { return func(c *gin.Context) { var ( err error ) err = handler(c) if err != nil { var apiException *APIException if h, ok := err.(*APIException); ok { apiException = h } else if e, ok := err.(error); ok { if gin.Mode() == "debug" { apiException = ServerErrorWithMsg(e.Error()) } else { apiException = UnknownError(e.Error()) } } else { apiException = ServerError() } c.JSON(http.StatusOK, apiException) return } } }
func ServerError() *APIException { return newAPIException(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) }
func ServerErrorWithMsg(msg string) *APIException { return newAPIException(http.StatusInternalServerError, msg) }
func NotFound() *APIException { return newAPIException(http.StatusNotFound, http.StatusText(http.StatusNotFound)) }
func UnknownError(message string) *APIException { return newAPIException(http.StatusForbidden, message) }
func ParameterError(message string) *APIException { return newAPIException(http.StatusBadRequest, message) }
func HandleNotFound(c *gin.Context) { handleErr := NotFound() c.JSON(handleErr.Code, handleErr) }
|
使用
1 2 3 4 5 6
| func Route(e *gin.RouterGroup) { e.POST("/", config.Wrapper(load)) }
func load(c *gin.Context) error { }
|