package models import ( "context" "encoding/json" "errors" "fmt" "mtp2_if/config" "mtp2_if/db" "mtp2_if/logger" "mtp2_if/rediscli" "mtp2_if/utils" "strings" "time" "github.com/go-viper/mapstructure/v2" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" ) // CycleType 周期类型 type CycleType int const ( // CycleTypeSecond 周期类型 - 秒 CycleTypeSecond CycleType = 0 // CycleTypeMinutes1 周期类型 - 1分钟 CycleTypeMinutes1 CycleType = 1 // CycleTypeMinutes5 周期类型 - 5分钟 CycleTypeMinutes5 CycleType = 2 // CycleTypeMinutes30 周期类型 - 30分钟 CycleTypeMinutes30 CycleType = 3 // CycleTypeMinutes60 周期类型 - 60分钟 CycleTypeMinutes60 CycleType = 4 // CycleTypeMinutes120 周期类型 - 2小时 CycleTypeMinutes120 CycleType = 120 // CycleTypeMinutes240 周期类型 - 4小时 CycleTypeMinutes240 CycleType = 240 // CycleTypeMinutesDay 周期类型 - 日线 CycleTypeMinutesDay CycleType = 11 // CycleTypeWeek 周期类型 - 周线 CycleTypeWeek CycleType = 12 // CycleTypeMonth 周期类型 - 月线 CycleTypeMonth CycleType = 13 // CycleTypeYear 周期类型 - 年线 CycleTypeYear CycleType = 14 // CycleTypeTik 周期类型 - Tik CycleTypeTik CycleType = 10 ) // CycleData MongoDB中历史数据模型 type CycleData struct { ID primitive.ObjectID `json:"-" bson:"_id"` // id GC string `bson:"GC"` // 商品代码 ST int `json:"-" bson:"ST"` // 时间戳 SST string `bson:"SST"` // 时间文本 Open int `bson:"Open"` // 开盘价 High int `bson:"High"` // 最高价 Low int `bson:"Low"` // 最低价 Close int `bson:"Close"` // 收盘价 TV int `bson:"TV"` // 总量 TT int `bson:"TT"` // 总金额 HV int `bson:"HV"` // 持仓量 SP int `bson:"SP"` // 结算价,日线周期(包括)以上才有 FI bool `json:"FI"` // 是否补充数据 } // TikData MongoDB中Tik数据模型 type TikData struct { ID primitive.ObjectID `json:"-" bson:"_id"` // id GC string `bson:"GC"` // 商品代码 TD int `bson:"TD"` // 交易日时间戳 AT int `bson:"AT"` // 行情时间戳 SAT string `bson:"SAT"` // 行情时间文本 PE int `bson:"PE"` // 现价 Vol int `bson:"Vol"` // 现量 TT int `bson:"TT"` // 现金额 Bid int `bson:"Bid"` // 买价 BV int `bson:"BV"` // 买量 Ask int `bson:"Ask"` // 卖价 AV int `bson:"AV"` // 卖量 HV int `bson:"HV"` // 持仓量 HI int `bson:"HI"` // 单笔持仓 TDR int `bson:"TDR"` // 交易方向 TK int `bson:"TK"` // 交易类型 OId int `bson:"OId"` // 行情序号 } // Quoteday 行情盘面 type Quoteday struct { Id int64 `mapstructure:"" xorm:"pk autoincr BIGINT(20)"` Exchangedate int64 `mapstructure:"ExchangeDate" xorm:"not null BIGINT(20)"` // 交易日 Goodscode string `mapstructure:"GoodsCode" xorm:"not null unique CHAR(10)"` // 商品代码 Exchangecode int `mapstructure:"ExchangeCode" xorm:"INT(11)"` // 交易所代码 Preclose int64 `mapstructure:"Preclose" xorm:"default 0 BIGINT(20)"` // 昨收 Opentime int64 `mapstructure:"Opentime" xorm:"BIGINT(20)"` // 开盘时间 Opened int64 `mapstructure:"Opened" xorm:"not null default 0 BIGINT(20)"` // 开盘价 Highest int64 `mapstructure:"Highest" xorm:"not null default 0 BIGINT(20)"` // 最高价 Lowest int64 `mapstructure:"Lowest" xorm:"not null default 0 BIGINT(20)"` // 最低价 Lasttime string `mapstructure:"Lasttime" xorm:"VARCHAR(20)"` // 行情时间(只有现价变化行情时间才变化) Utclasttime int64 `mapstructure:"Utclasttime" xorm:"not null BIGINT(20)"` // utc的行情时间 Last int64 `mapstructure:"Last" xorm:"not null BIGINT(20)"` // 最新价 Lastvolume int64 `mapstructure:"Lastvolume" xorm:"default 0 BIGINT(20)"` // 最新成交量 Lastturnover int64 `mapstructure:"Lastturnover" xorm:"default 0 BIGINT(20)"` // 最新成交金额 Totalbidvolume int64 `mapstructure:"Totalbidvolume" xorm:"default 0 BIGINT(20)"` // 外盘 Totalaskvolume int64 `mapstructure:"Totalaskvolume" xorm:"default 0 BIGINT(20)"` // 内盘 Totalvolume int64 `mapstructure:"Totalvolume" xorm:"default 0 BIGINT(20)"` // 总量 Totalturnover int64 `mapstructure:"Totalturnover" xorm:"default 0 BIGINT(20)"` // 总金额 Bid int64 `mapstructure:"Bid" xorm:"default 0 BIGINT(20)"` // 买1 Bid2 int64 `mapstructure:"Bid2" xorm:"default 0 BIGINT(20)"` // 买2 Bid3 int64 `mapstructure:"Bid3" xorm:"default 0 BIGINT(20)"` // 买3 Bid4 int64 `mapstructure:"Bid4" xorm:"default 0 BIGINT(20)"` // 买4 Bid5 int64 `mapstructure:"Bid5" xorm:"default 0 BIGINT(20)"` // 买5 Bidvolume int64 `mapstructure:"Bidvolume" xorm:"default 0 BIGINT(20)"` // 买量1 Bidvolume2 int64 `mapstructure:"Bidvolume2" xorm:"default 0 BIGINT(20)"` // 买量2 Bidvolume3 int64 `mapstructure:"Bidvolume3" xorm:"default 0 BIGINT(20)"` // 买量3 Bidvolume4 int64 `mapstructure:"Bidvolume4" xorm:"default 0 BIGINT(20)"` // 买量4 Bidvolume5 int64 `mapstructure:"Bidvolume5" xorm:"default 0 BIGINT(20)"` // 买量5 Ask int64 `mapstructure:"Ask" xorm:"default 0 BIGINT(20)"` // 卖1 Ask2 int64 `mapstructure:"Ask2" xorm:"default 0 BIGINT(20)"` // 卖2 Ask3 int64 `mapstructure:"Ask3" xorm:"default 0 BIGINT(20)"` // 卖3 Ask4 int64 `mapstructure:"Ask4" xorm:"default 0 BIGINT(20)"` // 卖4 Ask5 int64 `mapstructure:"Ask5" xorm:"default 0 BIGINT(20)"` // 卖5 Askvolume int64 `mapstructure:"Askvolume" xorm:"default 0 BIGINT(20)"` // 卖量1 Askvolume2 int64 `mapstructure:"Askvolume2" xorm:"default 0 BIGINT(20)"` // 卖量2 Askvolume3 int64 `mapstructure:"Askvolume3" xorm:"default 0 BIGINT(20)"` // 卖量3 Askvolume4 int64 `mapstructure:"Askvolume4" xorm:"default 0 BIGINT(20)"` // 卖量4 Askvolume5 int64 `mapstructure:"Askvolume5" xorm:"default 0 BIGINT(20)"` // 卖量5 Presettle int64 `mapstructure:"Presettle" xorm:"default 0 BIGINT(20)"` // 昨结价 Settle int64 `mapstructure:"Settle" xorm:"default 0 BIGINT(20)"` // 结算价 Preholdvolume int64 `mapstructure:"Preholdvolume" xorm:"default 0 BIGINT(20)"` // 昨持仓 Holdvolume int64 `mapstructure:"Holdvolume" xorm:"default 0 BIGINT(20)"` // 持仓 Averageprice int64 `mapstructure:"Averageprice" xorm:"default 0 BIGINT(20)"` // 均价 Orderid int64 `mapstructure:"Orderid" xorm:"default 0 BIGINT(20)"` // 序号 Limitup int64 `mapstructure:"Limitup" xorm:"default 0 BIGINT(20)"` // 涨停价 Limitdown int64 `mapstructure:"Limitdown" xorm:"default 0 BIGINT(20)"` // 跌停价 Inventory int64 `mapstructure:"Inventory" xorm:"default 0 BIGINT(20)"` // 库存 Holdincrement int64 `mapstructure:"Holdincrement" xorm:"default 0 BIGINT(20)"` // 单笔持仓 Iscleared int `mapstructure:"Iscleared" xorm:"INT(11)"` // 是否清盘标志 Issettled int `mapstructure:"Issettled" xorm:"INT(11)"` // 是否结算标志 Bidqueueinfo string `mapstructure:"Bidqueueinfo" xorm:"VARCHAR(2000)"` // 大利市买港股用 Askqueueinfo string `mapstructure:"Askqueueinfo" xorm:"VARCHAR(2000)"` // 大利市卖港股用 Bidorderid int64 `mapstructure:"Bidorderid" xorm:"BIGINT(20)"` // 买单号1 Bidorderid2 int64 `mapstructure:"Bidorderid2" xorm:"BIGINT(20)"` // 买单号2 Bidorderid3 int64 `mapstructure:"Bidorderid3" xorm:"BIGINT(20)"` // 买单号3 Bidorderid4 int64 `mapstructure:"Bidorderid4" xorm:"BIGINT(20)"` // 买单号4 Bidorderid5 int64 `mapstructure:"Bidorderid5" xorm:"BIGINT(20)"` // 买单号5 Askorderid int64 `mapstructure:"Askorderid" xorm:"BIGINT(20)"` // 卖单号1 Askorderid2 int64 `mapstructure:"Askorderid2" xorm:"BIGINT(20)"` // 卖单号2 Askorderid3 int64 `mapstructure:"Askorderid3" xorm:"BIGINT(20)"` // 卖单号3 Askorderid4 int64 `mapstructure:"Askorderid4" xorm:"BIGINT(20)"` // 卖单号4 Askorderid5 int64 `mapstructure:"Askorderid5" xorm:"BIGINT(20)"` // 卖单号5 Lastlot int64 `mapstructure:"Lastlot" xorm:"BIGINT(20)"` // 最新成交手数 Totallot int64 `mapstructure:"Totallot" xorm:"BIGINT(20)"` // 总手数 Strikeprice int64 `mapstructure:"Strikeprice" xorm:"BIGINT(20)"` // 发行价 Cleartime int64 `mapstructure:"Cleartime" xorm:"BIGINT(20)"` // 清盘时间 Calloptionpremiums int64 `mapstructure:"Calloptionpremiums" xorm:"default 0 BIGINT(20)"` // 认购期权1 Calloptionpremiums2 int64 `mapstructure:"Calloptionpremiums2" xorm:"default 0 BIGINT(20)"` // 认购期权2 Calloptionpremiums3 int64 `mapstructure:"Calloptionpremiums3" xorm:"default 0 BIGINT(20)"` // 认购期权3 Calloptionpremiums4 int64 `mapstructure:"Calloptionpremiums4" xorm:"default 0 BIGINT(20)"` // 认购期权4 Calloptionpremiums5 int64 `mapstructure:"Calloptionpremiums5" xorm:"default 0 BIGINT(20)"` // 认购期权5 Putoptionpremiums int64 `mapstructure:"Putoptionpremiums" xorm:"default 0 BIGINT(20)"` // 认沽期权1 Putoptionpremiums2 int64 `mapstructure:"Putoptionpremiums2" xorm:"default 0 BIGINT(20)"` // 认沽期权2 Putoptionpremiums3 int64 `mapstructure:"Putoptionpremiums3" xorm:"default 0 BIGINT(20)"` // 认沽期权3 Putoptionpremiums4 int64 `mapstructure:"Putoptionpremiums4" xorm:"default 0 BIGINT(20)"` // 认沽期权4 Putoptionpremiums5 int64 `mapstructure:"Putoptionpremiums5" xorm:"default 0 BIGINT(20)"` // 认沽期权5 Nontotalvolume int64 `mapstructure:"Nontotalvolume" xorm:"default 0 BIGINT(20)"` // 非交易总量 Nontotalholdervolume int64 `mapstructure:"Nontotalholdervolume" xorm:"default 0 BIGINT(20)"` // 非交易持仓量 Nontotalturnover int64 `mapstructure:"Nontotalturnover" xorm:"default 0 BIGINT(20)"` // 非交易总金额 Nontotallot int64 `mapstructure:"Nontotallot" xorm:"default 0 BIGINT(20)"` // 非交易总手数 Publictradetype string `mapstructure:"Publictradetype" xorm:"VARCHAR(2)"` // 公共交易标志类型 港股专用 Iep int64 `mapstructure:"Iep" xorm:"default 0 BIGINT(20)"` // 平衡价 港股专用 Iev int64 `mapstructure:"Iev" xorm:"default 0 BIGINT(20)"` // 平衡量 港股专用 Grepmarketprice int64 `mapstructure:"Grepmarketprice" xorm:"default 0 BIGINT(20)"` // 暗盘价 港股专用 Bid6 int64 `mapstructure:"Bid6" xorm:"default 0 BIGINT(20)"` // 买6 Bid7 int64 `mapstructure:"Bid7" xorm:"default 0 BIGINT(20)"` // 买7 Bid8 int64 `mapstructure:"Bid8" xorm:"default 0 BIGINT(20)"` // 买8 Bid9 int64 `mapstructure:"Bid9" xorm:"default 0 BIGINT(20)"` // 买9 Bid10 int64 `mapstructure:"Bid10" xorm:"default 0 BIGINT(20)"` // 买10 Bidvolume6 int64 `mapstructure:"Bidvolume6" xorm:"default 0 BIGINT(20)"` // 买量6 Bidvolume7 int64 `mapstructure:"Bidvolume7" xorm:"default 0 BIGINT(20)"` // 买量7 Bidvolume8 int64 `mapstructure:"Bidvolume8" xorm:"default 0 BIGINT(20)"` // 买量8 Bidvolume9 int64 `mapstructure:"Bidvolume9" xorm:"default 0 BIGINT(20)"` // 买量9 Bidvolume10 int64 `mapstructure:"Bidvolume10" xorm:"default 0 BIGINT(20)"` // 买量10 Ask6 int64 `mapstructure:"Ask6" xorm:"default 0 BIGINT(20)"` // 卖6 Ask7 int64 `mapstructure:"Ask7" xorm:"default 0 BIGINT(20)"` // 卖7 Ask8 int64 `mapstructure:"Ask8" xorm:"default 0 BIGINT(20)"` // 卖8 Ask9 int64 `mapstructure:"Ask9" xorm:"default 0 BIGINT(20)"` // 卖9 Ask10 int64 `mapstructure:"Ask10" xorm:"default 0 BIGINT(20)"` // 卖10 Askvolume6 int64 `mapstructure:"Askvolume6" xorm:"default 0 BIGINT(20)"` // 卖量6 Askvolume7 int64 `mapstructure:"Askvolume7" xorm:"default 0 BIGINT(20)"` // 卖量7 Askvolume8 int64 `mapstructure:"Askvolume8" xorm:"default 0 BIGINT(20)"` // 卖量8 Askvolume9 int64 `mapstructure:"Askvolume9" xorm:"default 0 BIGINT(20)"` // 卖量9 Askvolume10 int64 `mapstructure:"Askvolume10" xorm:"default 0 BIGINT(20)"` // 卖量10 Bidordervolume int64 `mapstructure:"Bidordervolume" xorm:"default 0 BIGINT(20)"` // 买单量1 Bidordervolume2 int64 `mapstructure:"Bidordervolume2" xorm:"default 0 BIGINT(20)"` // 买单量2 Bidordervolume3 int64 `mapstructure:"Bidordervolume3" xorm:"default 0 BIGINT(20)"` // 买单量3 Bidordervolume4 int64 `mapstructure:"Bidordervolume4" xorm:"default 0 BIGINT(20)"` // 买单量4 Bidordervolume5 int64 `mapstructure:"Bidordervolume5" xorm:"default 0 BIGINT(20)"` // 买单量5 Bidordervolume6 int64 `mapstructure:"Bidordervolume6" xorm:"default 0 BIGINT(20)"` // 买单量6 Bidordervolume7 int64 `mapstructure:"Bidordervolume7" xorm:"default 0 BIGINT(20)"` // 买单量7 Bidordervolume8 int64 `mapstructure:"Bidordervolume8" xorm:"default 0 BIGINT(20)"` // 买单量8 Bidordervolume9 int64 `mapstructure:"Bidordervolume9" xorm:"default 0 BIGINT(20)"` // 买单量9 Bidordervolume10 int64 `mapstructure:"Bidordervolume10" xorm:"default 0 BIGINT(20)"` // 买单量10 Askordervolume int64 `mapstructure:"Askordervolume" xorm:"default 0 BIGINT(20)"` // 卖单量1 Askordervolume2 int64 `mapstructure:"Askordervolume2" xorm:"default 0 BIGINT(20)"` // 卖单量2 Askordervolume3 int64 `mapstructure:"Askordervolume3" xorm:"default 0 BIGINT(20)"` // 卖单量3 Askordervolume4 int64 `mapstructure:"Askordervolume4" xorm:"default 0 BIGINT(20)"` // 卖单量4 Askordervolume5 int64 `mapstructure:"Askordervolume5" xorm:"default 0 BIGINT(20)"` // 卖单量5 Askordervolume6 int64 `mapstructure:"Askordervolume6" xorm:"default 0 BIGINT(20)"` // 卖单量6 Askordervolume7 int64 `mapstructure:"Askordervolume7" xorm:"default 0 BIGINT(20)"` // 卖单量7 Askordervolume8 int64 `mapstructure:"Askordervolume8" xorm:"default 0 BIGINT(20)"` // 卖单量8 Askordervolume9 int64 `mapstructure:"Askordervolume9" xorm:"default 0 BIGINT(20)"` // 卖单量9 Askordervolume10 int64 `mapstructure:"Askordervolume10" xorm:"default 0 BIGINT(20)"` // 卖单量10 } // TableName is Quoteday func (*Quoteday) TableName() string { return "quoteday" } // GetHistoryCycleDatas 获取历史数据 // 参数 cycleType CycleType 周期类型 // 参数 goodsCode string 商品代码 // 参数 startTime time.Time 开始时间(闭区间) // 参数 endTime time.Time 结束时间(闭区间) // 参数 count int 条数 // 参数 isAscForST bool 是否按时间顺序排序,默认为时间倒序排序 // 返回值 []CycleData 历史数据 // 返回值 error 错误 func GetHistoryCycleDatas(cycleType CycleType, goodsCode string, startTime, endTime *time.Time, count int, isAscForST bool) ([]CycleData, error) { db := db.GetMongoDB() // 获取目标Collection collection := "mincycle" switch cycleType { case CycleTypeTik: collection = "quotetik" case CycleTypeMinutes1: collection = "mincycle" case CycleTypeMinutes5: collection = "min5cycle" case CycleTypeMinutes30: collection = "min30cycle" case CycleTypeMinutes60: collection = "min60cycle" case CycleTypeMinutes240: collection = "min240cycle" case CycleTypeMinutesDay: collection = "daycycle" case CycleTypeWeek: collection = "weekcycle" case CycleTypeMonth: collection = "monthcycle" case CycleTypeYear: collection = "yearcycle" default: return nil, errors.New("不支持的周期类型") } c := db.Collection(collection) // 按时间排序 sort := "-ST" if isAscForST { sort = "ST" } // 查询数据 var cycleDatas []CycleData m := bson.M{"GC": goodsCode} if startTime != nil && endTime == nil { m["ST"] = bson.M{"$gte": startTime.Unix()} } else if startTime == nil && endTime != nil { m["ST"] = bson.M{"$lte": endTime.Unix()} } else if startTime != nil && endTime != nil { m["ST"] = bson.M{"$gte": startTime.Unix(), "$lte": endTime.Unix()} } query := c.Find(context.Background(), m) if count > 0 { query = query.Limit(int64(count)) } if err := query.Sort(sort).All(&cycleDatas); err != nil { return nil, err } return cycleDatas, nil } // GetHistoryTikDatas 获取历史数据 // 参数 goodsCode string 商品代码 // 参数 startTime time.Time 开始时间(闭区间) // 参数 endTime time.Time 结束时间(闭区间) // 参数 count int 条数 // 参数 isAscForST bool 是否按时间顺序排序,默认为时间倒序排序 // 返回值 []TikData Tik数据 // 返回值 error 错误 func GetHistoryTikDatas(goodsCode string, startTime, endTime *time.Time, count int, isAscForST bool) ([]TikData, error) { db := db.GetMongoDB() // 获取目标Collection collection := "quotetik" c := db.Collection(collection) // 按时间排序 sort := "-_id" if isAscForST { sort = "id" } // 查询数据 var tikDatas []TikData m := bson.M{"GC": goodsCode} if startTime != nil && endTime == nil { m["AT"] = bson.M{"$gte": startTime.Unix()} } else if startTime == nil && endTime != nil { m["AT"] = bson.M{"$lte": endTime.Unix()} } else if startTime != nil && endTime != nil { m["AT"] = bson.M{"$gte": startTime.Unix(), "$lte": endTime.Unix()} } query := c.Find(context.Background(), m) if count > 0 { query = query.Limit(int64(count)) } if err := query.Sort(sort).All(&tikDatas); err != nil { return nil, err } return tikDatas, nil } // GetQuoteDays 获取目标商品的盘面数据 // 参数 goodsCodes string 商品代码字串,以“,”分隔 // 返回 []Quoteday 盘面数据 // 返回 error error func GetQuoteDays(goodsCodes string) ([]Quoteday, error) { if config.SerCfg.MySQLCfg.Enabled == 0 { // 使用 Redis 盘面 return QueryRedisQuoteDays(goodsCodes) } engine := db.GetMySQLEngine() datas := make([]Quoteday, 0) if len(goodsCodes) > 0 { // 指定商品代码查询 // 处理商品代码, 让其可作为sql的in条件内容。 例如, 原字符串 ru2201,CU2406, => 处理成 'ru2201','CU2406' goodsCodes = strings.Trim(goodsCodes, ",") sCode := strings.Split(goodsCodes, ",") for i := range sCode { // 如果没有单引号, 则加上单引号 if !strings.Contains(sCode[i], "'") { sCode[i] = "'" + sCode[i] + "'" } } Instr := strings.Join(sCode, ",") if err := engine.Where(fmt.Sprintf("goodscode in (%s)", Instr)).Find(&datas); err != nil { return nil, err } } else { // 不指定则查所有 if err := engine.Find(&datas); err != nil { return nil, err } } return datas, nil } // SetRedisQuoteDays 将盘面数据同步到Redis func SetRedisQuoteDays() (err error) { engine := db.GetMySQLEngine() datas := make([]Quoteday, 0) if err = engine.Find(&datas); err != nil { return } b, err := json.Marshal(datas) if err != nil { return } redisCli := rediscli.GetRedisClient() err = redisCli.Set("Tourist:QuoteDay", b, 0).Err() return } // QueryRedisQuoteDays 从Redis读取盘面数据 func QueryRedisQuoteDays(goodsCodes string) (quoteDays []Quoteday, err error) { exchangeCode := "250" quoteDays = make([]Quoteday, 0) redisCli := rediscli.GetRedisClient() for _, goodsCode := range strings.Split(goodsCodes, ",") { var m map[string]string m, err = redisCli.HGetAll(fmt.Sprintf("QuoteDay:%s_%s", exchangeCode, goodsCode)).Result() if err != nil { return } if len(m) == 0 { return } var quoteDay Quoteday config := &mapstructure.DecoderConfig{ WeaklyTypedInput: true, // 启用弱类型转换,允许字符串自动转换为数字 Result: "eDay, } decoder, err := mapstructure.NewDecoder(config) if err != nil { return quoteDays, err } err = decoder.Decode(m) if err != nil { return quoteDays, err } quoteDays = append(quoteDays, quoteDay) } return } // GetRedisQuoteDays 从Redis读取盘面数据(游客) func GetRedisQuoteDays(goodsCodes []string) (quoteDays []Quoteday, err error) { redisCli := rediscli.GetRedisClient() b, err := redisCli.Get("Tourist:QuoteDay").Bytes() if err != nil { return } var datas []Quoteday if err = json.Unmarshal(b, &datas); err != nil { return } quoteDays = make([]Quoteday, 0) for _, item := range datas { if utils.InArray(len(goodsCodes), func(i int) bool { return goodsCodes[i] == item.Goodscode }) { quoteDays = append(quoteDays, item) } } return } var Done chan bool func StartSyncRedisQuoteDay() { ticker := time.NewTicker(2 * time.Second) Done = make(chan bool) go func() { for { select { case <-Done: ticker.Stop() return case <-ticker.C: // 在这里执行定时任务的代码 if err := SetRedisQuoteDays(); err != nil { logger.GetLogger().Errorf("Sync Redis failed: %s", err.Error()) } } } }() }