processor_business_logic.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. package area_graph
  2. import (
  3. "errors"
  4. "eta/eta_api/models/data_manage"
  5. "eta/eta_api/utils"
  6. "github.com/shopspring/decimal"
  7. "math"
  8. "sort"
  9. "time"
  10. )
  11. type InterpolateStrategy struct{}
  12. // Deal 空值填充:插值法填充
  13. func (i *InterpolateStrategy) Deal(tmpConfig data_manage.AreaExtraConf, edbDataList []*data_manage.ChartEdbInfoMapping, standardIndexMap map[string]*data_manage.EdbDataList, startDate string, endDate string) (err error) {
  14. for _, v := range edbDataList {
  15. if v.EdbInfoId != tmpConfig.StandardEdbInfoId {
  16. if dataList, ok := v.DataList.([]*data_manage.EdbDataList); ok {
  17. // 存放补充数据
  18. var replenishDataList []*data_manage.EdbDataList
  19. // 处理从 startDate 到第一个数据的日期补充
  20. if len(dataList) > 0 {
  21. firstData := dataList[0]
  22. // 将 startDate 到第一个数据日期之间的自然日填充补充数据,值为 0
  23. startDataTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  24. firstDataTime, _ := time.ParseInLocation(utils.FormatDate, firstData.DataTime, time.Local)
  25. // 计算两个日期之间的天数差
  26. if !startDataTime.Equal(firstDataTime) {
  27. for startDataTime.Before(firstDataTime) {
  28. // 补充数据
  29. nextDay := startDataTime.Format(utils.FormatDate)
  30. // 生成补充数据,值为 0
  31. replenishIndexData := data_manage.EdbDataList{
  32. EdbInfoId: v.EdbInfoId,
  33. DataTime: nextDay,
  34. DataTimestamp: startDataTime.UnixMilli(),
  35. Value: 0,
  36. }
  37. // 将补充数据加入补充数据列表
  38. replenishDataList = append(replenishDataList, &replenishIndexData)
  39. // 更新 startDataTime 到下一个日期
  40. startDataTime = startDataTime.AddDate(0, 0, 1)
  41. }
  42. }
  43. }
  44. // 插值法补充数据
  45. var startEdbInfoData *data_manage.EdbDataList
  46. for index := 0; index < len(dataList)-1; index++ {
  47. // 获取当前数据和下一个数据
  48. beforeIndexData := dataList[index]
  49. afterIndexData := dataList[index+1]
  50. if startEdbInfoData == nil {
  51. startEdbInfoData = beforeIndexData
  52. continue
  53. }
  54. // 获取两条数据之间相差的天数
  55. startDataTime, _ := time.ParseInLocation(utils.FormatDate, startEdbInfoData.DataTime, time.Local)
  56. currDataTime, _ := time.ParseInLocation(utils.FormatDate, afterIndexData.DataTime, time.Local)
  57. betweenHour := int(currDataTime.Sub(startDataTime).Hours())
  58. betweenDay := betweenHour / 24
  59. // 如果相差一天,那么过滤
  60. if betweenDay <= 1 {
  61. startEdbInfoData = afterIndexData
  62. continue
  63. }
  64. // 生成线性方程式
  65. var a, b float64
  66. {
  67. coordinateData := make([]utils.Coordinate, 0)
  68. tmpCoordinate1 := utils.Coordinate{
  69. X: 1,
  70. Y: startEdbInfoData.Value,
  71. }
  72. coordinateData = append(coordinateData, tmpCoordinate1)
  73. tmpCoordinate2 := utils.Coordinate{
  74. X: float64(betweenDay) + 1,
  75. Y: afterIndexData.Value,
  76. }
  77. coordinateData = append(coordinateData, tmpCoordinate2)
  78. a, b = utils.GetLinearResult(coordinateData)
  79. if math.IsNaN(a) || math.IsNaN(b) {
  80. err = errors.New("线性方程公式生成失败")
  81. return
  82. }
  83. }
  84. // 插值补充数据
  85. for i := 1; i < betweenDay; i++ {
  86. tmpDataTime := startDataTime.AddDate(0, 0, i)
  87. aDecimal := decimal.NewFromFloat(a)
  88. xDecimal := decimal.NewFromInt(int64(i) + 1)
  89. bDecimal := decimal.NewFromFloat(b)
  90. val, _ := aDecimal.Mul(xDecimal).Add(bDecimal).Round(4).Float64()
  91. nextDay := tmpDataTime.Format(utils.FormatDate)
  92. replenishIndexData := data_manage.EdbDataList{
  93. EdbDataId: afterIndexData.EdbDataId,
  94. DataTime: nextDay,
  95. DataTimestamp: tmpDataTime.UnixMilli(),
  96. Value: val,
  97. }
  98. // 将补充数据加入补充数据列表
  99. replenishDataList = append(replenishDataList, &replenishIndexData)
  100. }
  101. startEdbInfoData = afterIndexData
  102. }
  103. // 处理从最后一个数据到 endDate 的日期补充
  104. if len(dataList) > 0 {
  105. lastData := dataList[len(dataList)-1]
  106. // 将最后一个数据日期到 endDate 之间的自然日填充补充数据,值为 0
  107. lastDataTime, _ := time.ParseInLocation(utils.FormatDate, lastData.DataTime, time.Local)
  108. endDataTime, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
  109. // 如果 lastDataTime 不等于 endDate,进行补充
  110. if !lastDataTime.Equal(endDataTime) {
  111. // 补充数据直到 endDate
  112. for lastDataTime.Before(endDataTime) {
  113. // 补充数据
  114. addDate := lastDataTime.AddDate(0, 0, 1)
  115. nextDay := addDate.Format(utils.FormatDate)
  116. // 生成补充数据,值为 0
  117. replenishIndexData := data_manage.EdbDataList{
  118. EdbInfoId: v.EdbInfoId,
  119. DataTime: nextDay,
  120. DataTimestamp: addDate.UnixMilli(),
  121. Value: 0,
  122. }
  123. // 将补充数据加入补充数据列表
  124. replenishDataList = append(replenishDataList, &replenishIndexData)
  125. // 更新 lastDataTime 到下一个日期
  126. lastDataTime = addDate
  127. }
  128. }
  129. }
  130. dataList = append(dataList, replenishDataList...)
  131. // 根据基准指标筛选出符合数据
  132. var resultDataList []*data_manage.EdbDataList
  133. for _, dataObject := range dataList {
  134. if _, ok := standardIndexMap[dataObject.DataTime]; ok {
  135. // 存在才保留
  136. resultDataList = append(resultDataList, dataObject)
  137. }
  138. }
  139. // 排序
  140. sort.Slice(resultDataList, func(i, j int) bool {
  141. return resultDataList[i].DataTimestamp < resultDataList[j].DataTimestamp
  142. })
  143. v.DataList = resultDataList
  144. }
  145. }
  146. }
  147. return nil
  148. }
  149. type FillWithPreviousStrategy struct{}
  150. // Deal 空值填充:前值填充
  151. func (f *FillWithPreviousStrategy) Deal(tmpConfig data_manage.AreaExtraConf, edbDataList []*data_manage.ChartEdbInfoMapping, standardIndexMap map[string]*data_manage.EdbDataList, startDate string, endDate string) (err error) {
  152. // 按自然日补充,再根据基准指标取对应数据
  153. for _, v := range edbDataList {
  154. if v.EdbInfoId != tmpConfig.StandardEdbInfoId {
  155. if dataList, ok := v.DataList.([]*data_manage.EdbDataList); ok {
  156. // 存放补充数据
  157. var replenishDataList []*data_manage.EdbDataList
  158. // 处理从 startDate 到第一个数据的日期补充
  159. if len(dataList) > 0 {
  160. firstData := dataList[0]
  161. // 将 startDate 到第一个数据日期之间的自然日填充补充数据,值为 0
  162. startDataTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  163. firstDataTime, _ := time.ParseInLocation(utils.FormatDate, firstData.DataTime, time.Local)
  164. // 计算两个日期之间的天数差
  165. if !startDataTime.Equal(firstDataTime) {
  166. for startDataTime.Before(firstDataTime) {
  167. // 补充数据
  168. nextDay := startDataTime.Format(utils.FormatDate)
  169. // 生成补充数据,值为 0
  170. replenishIndexData := data_manage.EdbDataList{
  171. EdbInfoId: v.EdbInfoId,
  172. DataTime: nextDay,
  173. DataTimestamp: startDataTime.UnixMilli(),
  174. Value: 0,
  175. }
  176. // 将补充数据加入补充数据列表
  177. replenishDataList = append(replenishDataList, &replenishIndexData)
  178. // 更新 startDataTime 到下一个日期
  179. startDataTime = startDataTime.AddDate(0, 0, 1)
  180. }
  181. }
  182. }
  183. // 处理指标中空值数据
  184. for index := 0; index < len(dataList)-1; index++ {
  185. // 获取当前数据和下一个数据
  186. beforeIndexData := dataList[index]
  187. afterIndexData := dataList[index+1]
  188. for utils.IsMoreThanOneDay(beforeIndexData.DataTime, afterIndexData.DataTime) {
  189. // 创建补充数据
  190. nextDay := utils.GetNextDay(beforeIndexData.DataTime)
  191. toTime := utils.StringToTime(nextDay)
  192. replenishIndexData := data_manage.EdbDataList{
  193. EdbInfoId: v.EdbInfoId,
  194. DataTime: nextDay,
  195. DataTimestamp: toTime.UnixMilli(),
  196. Value: beforeIndexData.Value,
  197. }
  198. // 将补充数据加入补充数据列表
  199. replenishDataList = append(replenishDataList, &replenishIndexData)
  200. // 更新 beforeIndexData 为新创建的补充数据
  201. beforeIndexData = &replenishIndexData
  202. }
  203. }
  204. // 处理从最后一个数据到 endDate 的日期补充
  205. if len(dataList) > 0 {
  206. lastData := dataList[len(dataList)-1]
  207. // 将最后一个数据日期到 endDate 之间的自然日填充补充数据,值为 0
  208. lastDataTime, _ := time.ParseInLocation(utils.FormatDate, lastData.DataTime, time.Local)
  209. endDataTime, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
  210. // 如果 lastDataTime 不等于 endDate,进行补充
  211. if !lastDataTime.Equal(endDataTime) {
  212. // 补充数据直到 endDate
  213. for lastDataTime.Before(endDataTime) {
  214. // 补充数据
  215. addDate := lastDataTime.AddDate(0, 0, 1)
  216. nextDay := addDate.Format(utils.FormatDate)
  217. // 生成补充数据,值为 0
  218. replenishIndexData := data_manage.EdbDataList{
  219. EdbInfoId: v.EdbInfoId,
  220. DataTime: nextDay,
  221. DataTimestamp: addDate.UnixMilli(),
  222. Value: 0,
  223. }
  224. // 将补充数据加入补充数据列表
  225. replenishDataList = append(replenishDataList, &replenishIndexData)
  226. // 更新 lastDataTime 到下一个日期
  227. lastDataTime = addDate
  228. }
  229. }
  230. }
  231. dataList = append(dataList, replenishDataList...)
  232. // 根据基准指标筛选出符合数据
  233. var resultDataList []*data_manage.EdbDataList
  234. for _, dataObject := range dataList {
  235. _, ok = standardIndexMap[dataObject.DataTime]
  236. if ok {
  237. // 存在才保留
  238. resultDataList = append(resultDataList, dataObject)
  239. }
  240. }
  241. // 排序
  242. sort.Slice(resultDataList, func(i, j int) bool {
  243. return resultDataList[i].DataTimestamp < resultDataList[j].DataTimestamp
  244. })
  245. v.DataList = resultDataList
  246. }
  247. }
  248. }
  249. return nil
  250. }
  251. type FillWithNextStrategy struct{}
  252. // Deal 空值填充:后值填充
  253. func (f *FillWithNextStrategy) Deal(tmpConfig data_manage.AreaExtraConf, edbDataList []*data_manage.ChartEdbInfoMapping, standardIndexMap map[string]*data_manage.EdbDataList, startDate string, endDate string) (err error) {
  254. // 按自然日补充,再根据基准指标取对应数据
  255. for _, v := range edbDataList {
  256. if v.EdbInfoId != tmpConfig.StandardEdbInfoId {
  257. if dataList, ok := v.DataList.([]*data_manage.EdbDataList); ok {
  258. // 存放补充数据
  259. var replenishDataList []*data_manage.EdbDataList
  260. // 处理从 startDate 到第一个数据的日期补充
  261. if len(dataList) > 0 {
  262. firstData := dataList[0]
  263. // 将 startDate 到第一个数据日期之间的自然日填充补充数据,值为 0
  264. startDataTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  265. firstDataTime, _ := time.ParseInLocation(utils.FormatDate, firstData.DataTime, time.Local)
  266. // 计算两个日期之间的天数差
  267. if !startDataTime.Equal(firstDataTime) {
  268. for !startDataTime.After(firstDataTime) {
  269. // 补充数据
  270. nextDay := startDataTime.Format(utils.FormatDate)
  271. // 生成补充数据,值为 0
  272. replenishIndexData := data_manage.EdbDataList{
  273. EdbInfoId: v.EdbInfoId,
  274. DataTime: nextDay,
  275. DataTimestamp: startDataTime.UnixMilli(),
  276. Value: 0,
  277. }
  278. // 将补充数据加入补充数据列表
  279. replenishDataList = append(replenishDataList, &replenishIndexData)
  280. // 更新 startDataTime 到下一个日期
  281. startDataTime = startDataTime.AddDate(0, 0, 1)
  282. }
  283. }
  284. }
  285. // 处理从最后一个数据到 endDate 的日期补充
  286. if len(dataList) > 0 {
  287. lastData := dataList[len(dataList)-1]
  288. // 将最后一个数据日期到 endDate 之间的自然日填充补充数据,值为 0
  289. lastDataTime, _ := time.ParseInLocation(utils.FormatDate, lastData.DataTime, time.Local)
  290. endDataTime, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
  291. // 如果 lastDataTime 不等于 endDate,进行补充
  292. if !lastDataTime.Equal(endDataTime) {
  293. // 补充数据直到 endDate
  294. for lastDataTime.Before(endDataTime) {
  295. // 补充数据
  296. addDate := lastDataTime.AddDate(0, 0, 1)
  297. nextDay := addDate.Format(utils.FormatDate)
  298. // 生成补充数据,值为 0
  299. replenishIndexData := data_manage.EdbDataList{
  300. EdbInfoId: v.EdbInfoId,
  301. DataTime: nextDay,
  302. DataTimestamp: addDate.UnixMilli(),
  303. Value: 0,
  304. }
  305. // 将补充数据加入补充数据列表
  306. replenishDataList = append(replenishDataList, &replenishIndexData)
  307. // 更新 lastDataTime 到下一个日期
  308. lastDataTime = addDate
  309. }
  310. }
  311. }
  312. // 将切片数据倒序
  313. reverseSlice(dataList)
  314. // 处理指标中空值数据
  315. for index := 0; index < len(dataList)-1; index++ {
  316. // 获取当前数据和下一个数据
  317. beforeIndexData := dataList[index]
  318. afterIndexData := dataList[index+1]
  319. for utils.IsMoreThanOneDay(afterIndexData.DataTime, beforeIndexData.DataTime) {
  320. // 创建补充数据
  321. nextDay := utils.GetNextDay(afterIndexData.DataTime)
  322. toTime := utils.StringToTime(nextDay)
  323. replenishIndexData := data_manage.EdbDataList{
  324. EdbInfoId: v.EdbInfoId,
  325. DataTime: nextDay,
  326. DataTimestamp: toTime.UnixMilli(),
  327. Value: afterIndexData.Value,
  328. }
  329. // 将补充数据加入补充数据列表
  330. replenishDataList = append(replenishDataList, &replenishIndexData)
  331. // 更新 beforeIndexData 为新创建的补充数据
  332. afterIndexData = &replenishIndexData
  333. }
  334. }
  335. dataList = append(dataList, replenishDataList...)
  336. // 根据基准指标筛选出符合数据
  337. var resultDataList []*data_manage.EdbDataList
  338. for _, dataObject := range dataList {
  339. _, ok = standardIndexMap[dataObject.DataTime]
  340. if ok {
  341. // 存在才保留
  342. resultDataList = append(resultDataList, dataObject)
  343. }
  344. }
  345. // 排序
  346. sort.Slice(resultDataList, func(i, j int) bool {
  347. return resultDataList[i].DataTimestamp < resultDataList[j].DataTimestamp
  348. })
  349. v.DataList = resultDataList
  350. }
  351. }
  352. }
  353. return nil
  354. }
  355. type SetToZeroStrategy struct{}
  356. // Deal 空值填充:设为0
  357. func (s *SetToZeroStrategy) Deal(tmpConfig data_manage.AreaExtraConf, edbDataList []*data_manage.ChartEdbInfoMapping, standardIndexMap map[string]*data_manage.EdbDataList, startDate string, endDate string) (err error) {
  358. // 按自然日补充,再根据基准指标取对应数据
  359. for _, v := range edbDataList {
  360. if v.EdbInfoId != tmpConfig.StandardEdbInfoId {
  361. if dataList, ok := v.DataList.([]*data_manage.EdbDataList); ok {
  362. // 存放补充数据
  363. var replenishDataList []*data_manage.EdbDataList
  364. // 处理从 startDate 到第一个数据的日期补充
  365. if len(dataList) > 0 {
  366. firstData := dataList[0]
  367. // 将 startDate 到第一个数据日期之间的自然日填充补充数据,值为 0
  368. startDataTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
  369. firstDataTime, _ := time.ParseInLocation(utils.FormatDate, firstData.DataTime, time.Local)
  370. // 计算两个日期之间的天数差
  371. if !startDataTime.Equal(firstDataTime) {
  372. for startDataTime.Before(firstDataTime) {
  373. // 补充数据
  374. nextDay := startDataTime.Format(utils.FormatDate)
  375. // 生成补充数据,值为 0
  376. replenishIndexData := data_manage.EdbDataList{
  377. EdbInfoId: v.EdbInfoId,
  378. DataTime: nextDay,
  379. DataTimestamp: startDataTime.UnixMilli(),
  380. Value: 0,
  381. }
  382. // 将补充数据加入补充数据列表
  383. replenishDataList = append(replenishDataList, &replenishIndexData)
  384. // 更新 startDataTime 到下一个日期
  385. startDataTime = startDataTime.AddDate(0, 0, 1)
  386. }
  387. }
  388. }
  389. // 处理指标中空值数据
  390. for index := 0; index < len(dataList)-1; index++ {
  391. // 获取当前数据和下一个数据
  392. beforeIndexData := dataList[index]
  393. afterIndexData := dataList[index+1]
  394. for utils.IsMoreThanOneDay(beforeIndexData.DataTime, afterIndexData.DataTime) {
  395. // 创建补充数据
  396. nextDay := utils.GetNextDay(beforeIndexData.DataTime)
  397. toTime := utils.StringToTime(nextDay)
  398. replenishIndexData := data_manage.EdbDataList{
  399. EdbInfoId: v.EdbInfoId,
  400. DataTime: nextDay,
  401. DataTimestamp: toTime.UnixMilli(),
  402. Value: 0,
  403. }
  404. // 将补充数据加入补充数据列表
  405. replenishDataList = append(replenishDataList, &replenishIndexData)
  406. // 更新 beforeIndexData 为新创建的补充数据
  407. beforeIndexData = &replenishIndexData
  408. }
  409. }
  410. // 处理从最后一个数据到 endDate 的日期补充
  411. if len(dataList) > 0 {
  412. lastData := dataList[len(dataList)-1]
  413. // 将最后一个数据日期到 endDate 之间的自然日填充补充数据,值为 0
  414. lastDataTime, _ := time.ParseInLocation(utils.FormatDate, lastData.DataTime, time.Local)
  415. endDataTime, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
  416. // 如果 lastDataTime 不等于 endDate,进行补充
  417. if !lastDataTime.Equal(endDataTime) {
  418. // 补充数据直到 endDate
  419. for lastDataTime.Before(endDataTime) {
  420. // 补充数据
  421. addDate := lastDataTime.AddDate(0, 0, 1)
  422. nextDay := addDate.Format(utils.FormatDate)
  423. // 生成补充数据,值为 0
  424. replenishIndexData := data_manage.EdbDataList{
  425. EdbInfoId: v.EdbInfoId,
  426. DataTime: nextDay,
  427. DataTimestamp: addDate.UnixMilli(),
  428. Value: 0,
  429. }
  430. // 将补充数据加入补充数据列表
  431. replenishDataList = append(replenishDataList, &replenishIndexData)
  432. // 更新 lastDataTime 到下一个日期
  433. lastDataTime = addDate
  434. }
  435. }
  436. }
  437. dataList = append(dataList, replenishDataList...)
  438. // 根据基准指标筛选出符合数据
  439. var resultDataList []*data_manage.EdbDataList
  440. for _, dataObject := range dataList {
  441. _, ok = standardIndexMap[dataObject.DataTime]
  442. if ok {
  443. // 存在才保留
  444. resultDataList = append(resultDataList, dataObject)
  445. }
  446. }
  447. // 排序
  448. sort.Slice(resultDataList, func(i, j int) bool {
  449. return resultDataList[i].DataTimestamp < resultDataList[j].DataTimestamp
  450. })
  451. v.DataList = resultDataList
  452. }
  453. }
  454. }
  455. return nil
  456. }
  457. type DeleteDateStrategy struct{}
  458. // Deal 删除日期
  459. func (d *DeleteDateStrategy) Deal(tmpConfig data_manage.AreaExtraConf, edbDataList []*data_manage.ChartEdbInfoMapping, standardIndexMap map[string]*data_manage.EdbDataList, startDate string, endDate string) error {
  460. // 取所有指标的时间交集
  461. // 创建一个 map 来保存每个时间点的出现次数
  462. timeMap := make(map[string]int)
  463. for _, v := range edbDataList {
  464. if dataList, ok := v.DataList.([]*data_manage.EdbDataList); ok {
  465. // 遍历所有的 dataList,为每个 DataTime 增加一个计数
  466. for _, dataObject := range dataList {
  467. timeMap[dataObject.DataTime]++
  468. }
  469. }
  470. }
  471. for _, v := range edbDataList {
  472. if dataList, ok := v.DataList.([]*data_manage.EdbDataList); ok {
  473. // 遍历所有的 dataList,保留所有时间点在所有指标中都存在的数据
  474. var resultDataList []*data_manage.EdbDataList
  475. for _, dataObject := range dataList {
  476. if timeMap[dataObject.DataTime] == len(edbDataList) {
  477. // 如果该时间点在所有指标中都存在,加入到结果列表
  478. resultDataList = append(resultDataList, dataObject)
  479. }
  480. }
  481. // 将符合条件的数据重新赋值回 v.DataList
  482. v.DataList = resultDataList
  483. }
  484. }
  485. return nil
  486. }
  487. // 将列表颠倒
  488. func reverseSlice(dataList []*data_manage.EdbDataList) {
  489. // 使用双指针法,前后两个指针向中间逼近
  490. for i, j := 0, len(dataList)-1; i < j; i, j = i+1, j-1 {
  491. // 交换位置
  492. dataList[i], dataList[j] = dataList[j], dataList[i]
  493. }
  494. }