common.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709
  1. package common
  2. import (
  3. date4 "app.yhyue.com/moapp/jybase/date"
  4. "app.yhyue.com/moapp/jybase/encrypt"
  5. "crypto/md5"
  6. cryptoRand "crypto/rand"
  7. "encoding/hex"
  8. "encoding/json"
  9. "encoding/xml"
  10. "fmt"
  11. "github.com/dchest/captcha"
  12. "io"
  13. "log"
  14. "math"
  15. "math/big"
  16. mathRand "math/rand"
  17. "net/url"
  18. "reflect"
  19. "regexp"
  20. "runtime"
  21. "sort"
  22. "strconv"
  23. "strings"
  24. "time"
  25. )
  26. const (
  27. tmp = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345678900"
  28. )
  29. //短地址加密
  30. func EncodeArticleId(keys ...string) string {
  31. kstr := strings.Join(keys, ",")
  32. return encrypt.SE.EncodeString(kstr)
  33. }
  34. //短地址解密
  35. func DecodeArticleId(id string) []string {
  36. return strings.Split(encrypt.SE.DecodeString(id), ",")
  37. }
  38. //短地址加密,二次加密带校验和
  39. func EncodeArticleId2ByCheck(keys ...string) string {
  40. kstr := strings.Join(keys, ",")
  41. kstr = encrypt.SE.EncodeStringByCheck(kstr)
  42. return url.QueryEscape("ABC" + encrypt.SE2.EncodeStringByCheck(kstr))
  43. }
  44. //短地址解密,二次解密带校验和
  45. func DecodeArticleId2ByCheck(id string) []string {
  46. if !strings.Contains(id, "+") { //新加密算法解密
  47. id, _ = url.QueryUnescape(id)
  48. }
  49. if id[:3] == "ABC" { //前三位为ABC是新加密数据
  50. kstr := encrypt.SE2.DecodeStringByCheck(id[3:])
  51. return strings.Split(encrypt.SE.DecodeStringByCheck(kstr), ",")
  52. } else { //历史数据
  53. rep := DecodeArticleId(id)
  54. oldpushid := "58f87a9561a0721f157bc74d" //剑鱼1.9发版前最后一次推送信息id
  55. if rep[0] > oldpushid {
  56. return []string{""}
  57. } else {
  58. return rep
  59. }
  60. }
  61. }
  62. func Uuid(length int) string {
  63. ret := []string{}
  64. r := mathRand.New(mathRand.NewSource(time.Now().UnixNano()))
  65. for i := 0; i < length; i++ {
  66. index := r.Intn(62)
  67. ret = append(ret, tmp[index:index+1])
  68. }
  69. return strings.Join(ret, "")
  70. }
  71. //计算字符串和值
  72. func Sumstring(code string) (sum int) {
  73. tmp := []rune(code)
  74. for _, v := range tmp {
  75. sum = sum + int(v)
  76. }
  77. return
  78. }
  79. //获取随机数
  80. func GetRandom(n int) string {
  81. var idChars = []byte("0123456789")
  82. b := captcha.RandomDigits(n)
  83. for i, c := range b {
  84. b[i] = idChars[c]
  85. }
  86. return string(b)
  87. }
  88. //获取复杂的随机数
  89. func GetLetterRandom(length int, flag ...bool) string {
  90. var idChars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
  91. var mod byte = 52
  92. if len(flag) > 0 && flag[0] {
  93. idChars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
  94. mod = 26
  95. }
  96. b := make([]byte, length)
  97. maxrb := byte(256 - (256 % int(mod)))
  98. i := 0
  99. EXIT:
  100. for {
  101. r := make([]byte, length+(length/4))
  102. if _, err := io.ReadFull(cryptoRand.Reader, r); err != nil {
  103. panic("captcha: error reading random source: " + err.Error())
  104. }
  105. for _, c := range r {
  106. if c > maxrb {
  107. continue
  108. }
  109. b[i] = c % mod
  110. i++
  111. if i == length {
  112. break EXIT
  113. }
  114. }
  115. }
  116. for i, c := range b {
  117. b[i] = idChars[c]
  118. }
  119. return string(b)
  120. }
  121. /*获取复杂的随机数,数字和字母的组合
  122. * c > 2 数字的个数和字母的个数随机分配
  123. * n 数字的个数
  124. * l 字母的个数
  125. */
  126. func GetComplexRandom(c, n, l int) string {
  127. if c < 2 && (n < 1 || l < 1) {
  128. return "--"
  129. }
  130. r := mathRand.New(mathRand.NewSource(time.Now().UnixNano()))
  131. myCommonMethod := func(flag bool) int {
  132. if flag {
  133. return r.Intn(c-1) + 1
  134. } else {
  135. return r.Intn(c)
  136. }
  137. }
  138. if c >= 2 {
  139. n = myCommonMethod(true)
  140. l = c - n
  141. } else {
  142. c = l + n
  143. }
  144. value := GetRandom(n) + GetLetterRandom(l)
  145. var array = strings.Split(value, "")
  146. for i := 0; i < c/2; i++ {
  147. r1 := myCommonMethod(false)
  148. r2 := myCommonMethod(false)
  149. o := array[r1]
  150. array[r1] = array[r2]
  151. array[r2] = o
  152. }
  153. return strings.Join(array, "")
  154. }
  155. /*隐藏部分账号
  156. *返回手机号:150...70765 邮箱:...shenjun@vip.qq.com
  157. */
  158. func EncryCode(value string) string {
  159. if len(value) == 0 {
  160. return value
  161. } else if strings.Contains(value, "@") {
  162. start := strings.Index(value, "@") / 2
  163. if start == 0 {
  164. start++
  165. }
  166. value = "...." + string(value[start:])
  167. } else {
  168. value = string(value[0:3]) + "..." + string(value[len(value)-4:])
  169. }
  170. return value
  171. }
  172. //生成32位md5字串
  173. func GetMd5String(s string) string {
  174. h := md5.New()
  175. h.Write([]byte(s))
  176. return hex.EncodeToString(h.Sum(nil))
  177. }
  178. //obj(string,M)转M,查询用到
  179. func ObjToMap(obj interface{}) *map[string]interface{} {
  180. data := make(map[string]interface{})
  181. if s, ok := obj.(string); ok {
  182. json.Unmarshal([]byte(strings.Replace(s, "'", "\"", -1)), &data)
  183. } else if s1, ok1 := obj.(map[string]interface{}); ok1 {
  184. data = s1
  185. } else if s1, ok1 := obj.(*map[string]interface{}); ok1 {
  186. return s1
  187. } else {
  188. data = nil
  189. }
  190. return &data
  191. }
  192. /*UTC类型时间转字符串
  193. *flag==true,日期格式yyyy-mm-dd hh:mm:ss
  194. *flag==false,日期格式yyyy-mm-dd
  195. */
  196. func LongToDate(date interface{}, flag bool) string {
  197. var int64Date int64
  198. if l1, ok1 := date.(float64); ok1 {
  199. int64Date = int64(l1)
  200. } else if l2, ok2 := date.(int64); ok2 {
  201. int64Date = l2
  202. } else if l3, ok3 := date.(int); ok3 {
  203. int64Date = int64(l3)
  204. }
  205. t := time.Unix(int64Date, 0)
  206. if flag {
  207. return t.Format("2006-01-02 15:04:05")
  208. } else {
  209. return t.Format("2006-01-02")
  210. }
  211. }
  212. func IntAll(num interface{}) int {
  213. return IntAllDef(num, 0)
  214. }
  215. func Int64All(num interface{}) int64 {
  216. if i, ok := num.(int64); ok {
  217. return int64(i)
  218. } else if i0, ok0 := num.(int32); ok0 {
  219. return int64(i0)
  220. } else if i1, ok1 := num.(float64); ok1 {
  221. return int64(i1)
  222. } else if i2, ok2 := num.(int); ok2 {
  223. return int64(i2)
  224. } else if i3, ok3 := num.(float32); ok3 {
  225. return int64(i3)
  226. } else if i4, ok4 := num.(string); ok4 {
  227. i64, _ := strconv.ParseInt(i4, 10, 64)
  228. //in, _ := strconv.Atoi(i4)
  229. return i64
  230. } else if i5, ok5 := num.(int16); ok5 {
  231. return int64(i5)
  232. } else if i6, ok6 := num.(int8); ok6 {
  233. return int64(i6)
  234. } else if i7, ok7 := num.(*big.Int); ok7 {
  235. in, _ := strconv.ParseInt(fmt.Sprint(i7), 10, 64)
  236. return int64(in)
  237. } else if i8, ok8 := num.(*big.Float); ok8 {
  238. in, _ := strconv.ParseInt(fmt.Sprint(i8), 10, 64)
  239. return int64(in)
  240. } else {
  241. return 0
  242. }
  243. }
  244. func Float64All(num interface{}) float64 {
  245. if i, ok := num.(float64); ok {
  246. return float64(i)
  247. } else if i0, ok0 := num.(int32); ok0 {
  248. return float64(i0)
  249. } else if i1, ok1 := num.(int64); ok1 {
  250. return float64(i1)
  251. } else if i2, ok2 := num.(int); ok2 {
  252. return float64(i2)
  253. } else if i3, ok3 := num.(float32); ok3 {
  254. return float64(i3)
  255. } else if i4, ok4 := num.(string); ok4 {
  256. in, _ := strconv.ParseFloat(i4, 64)
  257. return in
  258. } else if i5, ok5 := num.(int16); ok5 {
  259. return float64(i5)
  260. } else if i6, ok6 := num.(int8); ok6 {
  261. return float64(i6)
  262. } else if i6, ok6 := num.(uint); ok6 {
  263. return float64(i6)
  264. } else if i6, ok6 := num.(uint8); ok6 {
  265. return float64(i6)
  266. } else if i6, ok6 := num.(uint16); ok6 {
  267. return float64(i6)
  268. } else if i6, ok6 := num.(uint32); ok6 {
  269. return float64(i6)
  270. } else if i6, ok6 := num.(uint64); ok6 {
  271. return float64(i6)
  272. } else if i7, ok7 := num.(*big.Float); ok7 {
  273. in, _ := strconv.ParseFloat(fmt.Sprint(i7), 64)
  274. return float64(in)
  275. } else if i8, ok8 := num.(*big.Int); ok8 {
  276. in, _ := strconv.ParseFloat(fmt.Sprint(i8), 64)
  277. return float64(in)
  278. } else {
  279. return 0
  280. }
  281. }
  282. func IntAllDef(num interface{}, defaultNum int) int {
  283. if i, ok := num.(int); ok {
  284. return int(i)
  285. } else if i0, ok0 := num.(int32); ok0 {
  286. return int(i0)
  287. } else if i1, ok1 := num.(float64); ok1 {
  288. return int(i1)
  289. } else if i2, ok2 := num.(int64); ok2 {
  290. return int(i2)
  291. } else if i3, ok3 := num.(float32); ok3 {
  292. return int(i3)
  293. } else if i4, ok4 := num.(string); ok4 {
  294. in, _ := strconv.Atoi(i4)
  295. return int(in)
  296. } else if i5, ok5 := num.(int16); ok5 {
  297. return int(i5)
  298. } else if i6, ok6 := num.(int8); ok6 {
  299. return int(i6)
  300. } else if i7, ok7 := num.(*big.Int); ok7 {
  301. in, _ := strconv.Atoi(fmt.Sprint(i7))
  302. return int(in)
  303. } else if i8, ok8 := num.(*big.Float); ok8 {
  304. in, _ := strconv.Atoi(fmt.Sprint(i8))
  305. return int(in)
  306. } else {
  307. return defaultNum
  308. }
  309. }
  310. func ObjToString(old interface{}) string {
  311. if nil == old {
  312. return ""
  313. } else {
  314. r, _ := old.(string)
  315. return r
  316. }
  317. }
  318. func ObjToStringDef(old interface{}, defaultstr string) string {
  319. if nil == old {
  320. return defaultstr
  321. } else {
  322. r, _ := old.(string)
  323. if r == "" {
  324. return defaultstr
  325. }
  326. return r
  327. }
  328. }
  329. //对象数组转成string数组
  330. func ObjArrToStringArr(old []interface{}) []string {
  331. if old != nil {
  332. new := make([]string, len(old))
  333. for i, v := range old {
  334. new[i], _ = v.(string)
  335. }
  336. return new
  337. } else {
  338. return nil
  339. }
  340. }
  341. //对象数组转成map数组
  342. func ObjArrToMapArr(old []interface{}) []map[string]interface{} {
  343. if old != nil {
  344. new := make([]map[string]interface{}, len(old))
  345. for i, v := range old {
  346. new[i], _ = v.(map[string]interface{})
  347. }
  348. return new
  349. } else {
  350. return nil
  351. }
  352. }
  353. //map数组转成对象数组
  354. func MapArrToObjArr(old []map[string]interface{}) []interface{} {
  355. if old != nil {
  356. new := make([]interface{}, len(old))
  357. for i, v := range old {
  358. new[i] = v
  359. }
  360. return new
  361. } else {
  362. return nil
  363. }
  364. }
  365. func SubstrByByte(str string, length int) string {
  366. bs := []byte(str)[:length]
  367. bl := 0
  368. for i := len(bs) - 1; i >= 0; i-- {
  369. switch {
  370. case bs[i] >= 0 && bs[i] <= 127:
  371. return string(bs[:i+1])
  372. case bs[i] >= 128 && bs[i] <= 191:
  373. bl++
  374. case bs[i] >= 192 && bs[i] <= 253:
  375. cl := 0
  376. switch {
  377. case bs[i]&252 == 252:
  378. cl = 6
  379. case bs[i]&248 == 248:
  380. cl = 5
  381. case bs[i]&240 == 240:
  382. cl = 4
  383. case bs[i]&224 == 224:
  384. cl = 3
  385. default:
  386. cl = 2
  387. }
  388. if bl+1 == cl {
  389. return string(bs[:i+cl])
  390. }
  391. return string(bs[:i])
  392. }
  393. }
  394. return ""
  395. }
  396. func SubString(str string, begin, length int) (substr string) {
  397. // 将字符串的转换成[]rune
  398. rs := []rune(str)
  399. lth := len(rs)
  400. // 简单的越界判断
  401. if begin < 0 {
  402. begin = 0
  403. }
  404. if begin >= lth {
  405. begin = lth
  406. }
  407. end := begin + length
  408. if end > lth {
  409. end = lth
  410. }
  411. // 返回子串
  412. return string(rs[begin:end])
  413. }
  414. //捕获异常
  415. func Try(fun func(), handler func(interface{})) {
  416. defer func() {
  417. if err := recover(); err != nil {
  418. for skip := 1; ; skip++ {
  419. _, file, line, ok := runtime.Caller(skip)
  420. if !ok {
  421. break
  422. }
  423. go log.Printf("%v,%v\n", file, line)
  424. }
  425. handler(err)
  426. }
  427. }()
  428. fun()
  429. }
  430. //3目运算
  431. func If(b bool, to, fo interface{}) interface{} {
  432. if b {
  433. return to
  434. } else {
  435. return fo
  436. }
  437. }
  438. //HashCode值
  439. func HashCode(uid string) int {
  440. var h uint32 = 0
  441. rs := []rune(uid)
  442. for i := 0; i < len(rs); i++ {
  443. h = 31*h + uint32(rs[i])
  444. }
  445. return int(h)
  446. }
  447. //获取离n天的秒差
  448. func GetDayStartSecond(n int) int64 {
  449. now := time.Now()
  450. tom := time.Date(now.Year(), now.Month(), now.Day()+n, 0, 0, 0, 0, time.Local)
  451. return tom.Unix()
  452. }
  453. func InterfaceArrTointArr(arr []interface{}) []int {
  454. tmp := make([]int, 0)
  455. for _, v := range arr {
  456. tmp = append(tmp, int(v.(float64)))
  457. }
  458. return tmp
  459. }
  460. func InterfaceArrToint64Arr(arr []interface{}) []int64 {
  461. tmp := make([]int64, 0)
  462. for _, v := range arr {
  463. tmp = append(tmp, int64(v.(float64)))
  464. }
  465. return tmp
  466. }
  467. func GetSubDay(t1 int64) int {
  468. tt1 := time.Unix(t1, 0)
  469. tt2 := time.Now()
  470. nt1 := time.Date(tt1.Year(), tt1.Month(), tt1.Day(), 0, 0, 0, 0, time.Local)
  471. nt2 := time.Date(tt2.Year(), tt2.Month(), tt2.Day(), 0, 0, 0, 0, time.Local)
  472. return int((nt1.Unix() - nt2.Unix()) / 86400)
  473. }
  474. func StartWith(value, str string) bool {
  475. ok, _ := regexp.MatchString("^"+str, value)
  476. return ok
  477. }
  478. func EndWith(value, str string) bool {
  479. ok, _ := regexp.MatchString(str+"$", value)
  480. return ok
  481. }
  482. //出错拦截
  483. func Catch() {
  484. if r := recover(); r != nil {
  485. log.Println(r)
  486. for skip := 0; ; skip++ {
  487. _, file, line, ok := runtime.Caller(skip)
  488. if !ok {
  489. break
  490. }
  491. go log.Printf("%v,%v\n", file, line)
  492. }
  493. }
  494. }
  495. func ConvertFileSize(s int) string {
  496. size := float64(s)
  497. var kb float64 = 1024
  498. var mb float64 = kb * 1024
  499. var gb float64 = mb * 1024
  500. if size >= gb {
  501. return fmt.Sprintf("%.1f GB", float64(size/gb))
  502. } else if size >= mb {
  503. f := float64(size / mb)
  504. if f > 100 {
  505. return fmt.Sprintf("%.0f MB", f)
  506. }
  507. return fmt.Sprintf("%.1f MB", f)
  508. } else if size >= kb {
  509. f := float64(size / kb)
  510. if f > 100 {
  511. return fmt.Sprintf("%.0f KB", f)
  512. }
  513. return fmt.Sprintf("%.1f KB", f)
  514. }
  515. return fmt.Sprintf("%d B", s)
  516. }
  517. //MD5签名
  518. func WxSign(format string, param ...interface{}) string {
  519. data := fmt.Sprintf(format, param...)
  520. h := md5.New()
  521. h.Write([]byte(data))
  522. sign := strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
  523. return sign
  524. }
  525. //计算时差
  526. func TimeDiff(date time.Time) string {
  527. var date1 = date //开始时间
  528. var date2 = time.Now() //结束时间
  529. var date3 = date2.Unix() - date1.Unix() //时间差的毫秒数
  530. //计算出相差天数
  531. var days = math.Floor(float64(date3 / (24 * 3600)))
  532. //计算出小时数
  533. var leave1 = date3 % (24 * 3600) //计算天数后剩余的毫秒数
  534. var hours = math.Floor(float64(leave1 / (3600)))
  535. //计算相差分钟数
  536. var leave2 = leave1 % (3600) //计算小时数后剩余的毫秒数
  537. var minutes = math.Floor(float64(leave2 / (60)))
  538. //计算相差秒数
  539. var td = "30秒前"
  540. if days > 0 {
  541. if days > 10 {
  542. if date1.Year() < date2.Year() {
  543. td = date4.FormatDate(&date, date4.Date_Short_Layout)
  544. } else {
  545. td = date4.FormatDate(&date, date4.Date_Small_Layout)
  546. }
  547. } else {
  548. td = fmt.Sprint(days) + "天前"
  549. }
  550. } else if hours > 0 {
  551. td = fmt.Sprint(hours) + "小时前"
  552. } else if minutes > 0 {
  553. td = fmt.Sprint(minutes) + "分钟前"
  554. }
  555. return td
  556. }
  557. func FloatFormat(tmp float64, n int) float64 {
  558. fs := fmt.Sprintf("%."+fmt.Sprint(n)+"f", tmp)
  559. f, _ := strconv.ParseFloat(fs, 64)
  560. return f
  561. }
  562. //生成微信支付的签名
  563. func CreateWxSign(afterStr string, obj interface{}, filter ...string) string {
  564. filter = append(filter, "sign", "xml")
  565. keys := []string{}
  566. m := make(map[string]string)
  567. t := reflect.TypeOf(obj)
  568. v := reflect.ValueOf(obj)
  569. k := t.Kind()
  570. if t.Kind() == reflect.Ptr {
  571. t = t.Elem()
  572. k = t.Kind()
  573. v = v.Elem()
  574. }
  575. if k == reflect.Map {
  576. for _, key := range v.MapKeys() {
  577. keys = append(keys, key.String())
  578. m[key.String()] = fmt.Sprint(v.MapIndex(key).Interface())
  579. }
  580. } else if k == reflect.Struct {
  581. for n := 0; n < t.NumField(); n++ {
  582. tagName := t.Field(n).Tag.Get("xml")
  583. if tagName == "" {
  584. tagName = t.Field(n).Tag.Get("json")
  585. }
  586. if tagName == "" {
  587. tagName = t.Field(n).Name
  588. }
  589. keys = append(keys, tagName)
  590. m[tagName] = fmt.Sprint(v.Field(n))
  591. }
  592. }
  593. sort.Strings(keys)
  594. vs := []string{}
  595. L:
  596. for _, v := range keys {
  597. for _, f := range filter {
  598. if f == v {
  599. continue L
  600. }
  601. }
  602. if strings.TrimSpace(m[v]) == "" {
  603. continue
  604. }
  605. vs = append(vs, fmt.Sprintf("%s=%s", v, m[v]))
  606. }
  607. return WxSign(strings.Join(vs, "&") + afterStr)
  608. }
  609. //简单的xml转map,只有一个层级,没有多层嵌套
  610. func XmlToMap(input string) map[string]string {
  611. var t xml.Token
  612. var err error
  613. inputReader := strings.NewReader(input)
  614. decoder := xml.NewDecoder(inputReader)
  615. isStart := false
  616. nodeName := ""
  617. m := make(map[string]string)
  618. for t, err = decoder.Token(); err == nil; t, err = decoder.Token() {
  619. switch token := t.(type) {
  620. // 处理元素开始(标签)
  621. case xml.StartElement:
  622. isStart = true
  623. nodeName = token.Name.Local
  624. // 处理元素结束(标签)
  625. case xml.EndElement:
  626. isStart = false
  627. // 处理字符数据(这里就是元素的文本)
  628. case xml.CharData:
  629. if isStart {
  630. m[nodeName] = string([]byte(token))
  631. }
  632. default:
  633. // ...
  634. }
  635. }
  636. return m
  637. }
  638. func SimpleCrontab(flag bool, c string, f func()) {
  639. array := strings.Split(c, ":")
  640. if len(array) != 2 {
  641. log.Fatalln("定时任务参数错误!", c)
  642. }
  643. if flag {
  644. go f()
  645. }
  646. now := time.Now()
  647. t := time.Date(now.Year(), now.Month(), now.Day(), IntAll(array[0]), IntAll(array[1]), 0, 0, time.Local)
  648. if t.Before(now) {
  649. t = t.AddDate(0, 0, 1)
  650. }
  651. sub := t.Sub(now)
  652. log.Println(c, "run after", sub)
  653. timer := time.NewTimer(sub)
  654. for {
  655. select {
  656. case <-timer.C:
  657. go f()
  658. log.Println(c, "run after", 24*time.Hour)
  659. timer.Reset(24 * time.Hour)
  660. }
  661. }
  662. }
  663. //v保留n为小数,n后的四舍五入
  664. func RetainDecimal(v float64, n int) float64 {
  665. n10 := math.Pow10(n)
  666. return math.Trunc((v+0.5/n10)*n10) / n10
  667. }