印度包网
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

1024 lines
21 KiB

package util
import (
"bufio"
"container/list"
"fmt"
"io"
"math"
"math/rand"
"net/http"
"os"
"reflect"
"regexp"
"strconv"
"strings"
"time"
"github.com/liangdas/mqant/log"
"github.com/mitchellh/mapstructure"
)
// FormatFloat 取小数点后n位小数,四舍五入
func FormatFloat(num float64, decimal int) string {
if math.Trunc(num) == num || decimal == 0 {
return fmt.Sprintf("%.f", math.Trunc(num))
}
format := "%." + strconv.Itoa(decimal) + "f"
return fmt.Sprintf(format, num)
}
// RoundFloat 取小数点后n位非零小数
func RoundFloat(num float64, decimal int) string {
// 默认乘1
d := float64(1)
if decimal > 0 {
// 10的N次方
d = math.Pow10(decimal)
}
// math.trunc作用就是返回浮点数的整数部分
// 再除回去,小数点后无效的0也就不存在了
return strconv.FormatFloat(math.Trunc(num*d)/d, 'f', -1, 64)
}
// Decimal 保留x位小数,返回float64
func Decimal(value float64, deci int) float64 {
value, _ = strconv.ParseFloat(fmt.Sprintf("%."+strconv.Itoa(deci)+"f", value), 64)
return value
}
func GetInt(data interface{}) int {
switch data := data.(type) {
case int:
return data
case int64:
return int(data)
case float32:
return int(data)
case float64:
return int(data)
case string:
ret, _ := strconv.Atoi(data)
return ret
default:
return 0
}
}
func GetInt64(data interface{}) int64 {
switch data := data.(type) {
case int:
return int64(data)
case int64:
return data
case float32:
return int64(data)
case float64:
return int64(data)
case string:
ret, _ := strconv.ParseInt(data, 10, 64)
return ret
default:
return 0
}
}
// CheckFileIsExist 判断文件是否存在
func CheckFileIsExist(filename string) bool {
var exist = true
if _, err := os.Stat(filename); os.IsNotExist(err) {
exist = false
}
return exist
}
func StructToMap(obj interface{}, tag string) map[string]interface{} {
t := reflect.TypeOf(obj)
v := reflect.ValueOf(obj)
if v.Kind() == reflect.Ptr {
t = t.Elem()
v = v.Elem()
}
var result = make(map[string]interface{})
for i := 0; i < t.NumField(); i++ {
tagName := t.Field(i).Tag.Get(tag)
if tagName != "" && tagName != "-" {
result[tagName] = v.Field(i).Interface()
}
}
return result
}
func StructToMapJson(obj interface{}) map[string]interface{} {
t := reflect.TypeOf(obj)
v := reflect.ValueOf(obj)
if t.Kind() == reflect.Ptr {
t = t.Elem()
v = v.Elem()
}
var result = make(map[string]interface{})
for i := 0; i < t.NumField(); i++ {
if v.Field(i).Kind() == reflect.Ptr && v.Field(i).IsNil() {
continue
}
tagName := t.Field(i).Tag.Get("json")
if tagName != "" && tagName != "-" && !v.Field(i).IsZero() {
result[tagName] = v.Field(i).Interface()
}
}
return result
}
// StructToMapJsonAll 非空字段也包括
func StructToMapJsonAll(obj interface{}) map[string]interface{} {
t := reflect.TypeOf(obj)
v := reflect.ValueOf(obj)
if t.Kind() == reflect.Ptr {
t = t.Elem()
v = v.Elem()
}
var result = make(map[string]interface{})
for i := 0; i < t.NumField(); i++ {
if v.Field(i).Kind() == reflect.Ptr && v.Field(i).IsNil() {
continue
}
tagName := t.Field(i).Tag.Get("json")
if tagName != "" && tagName != "-" {
result[tagName] = v.Field(i).Interface()
}
}
return result
}
func Map2Struct(obj map[string]interface{}, result interface{}) error {
return mapstructure.Decode(obj, result)
}
// Go 用协程处理f
func Go(f func()) {
go func() {
defer Recover()
f()
}()
}
// RandomLetters 随机26位不重复的字符串
func RandomLetters() string {
a := rand.Perm(26)
s := []byte{}
for _, v := range a {
s = append(s, byte(97+v))
}
return string(s)
}
var (
characters52 = [52]byte{
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
}
)
func GenerateRandomString(size int) string {
raw := make([]byte, size)
for i := 0; i < size; i++ {
raw[i] = characters52[rand.Intn(52)]
}
return string(raw)
}
// StrFirstToUpper 首字母大写
func StrFirstToUpper(str string) string {
if len(str) < 1 {
return ""
}
strArry := []byte(str)
if strArry[0] >= 97 && strArry[0] <= 122 {
strArry[0] -= 32
}
return string(strArry)
}
// DecodeRedisMap 解析map到目标t中,目前只实现了部分方法,如果需要解析更复杂结构需实现
func DecodeRedisMap(m map[string]string, t interface{}) (err error) {
val := reflect.ValueOf(t).Elem()
for i := 0; i < val.NumField(); i++ {
f := val.Type().Field(i)
fi := val.Field(i)
name := f.Name
if s, ok := m[name]; ok {
switch f.Type.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
ret, err := strconv.ParseInt(s, 10, 64)
if err != nil {
return err
}
fi.SetInt(ret)
case reflect.Float32, reflect.Float64:
ret, err := strconv.ParseFloat(s, 64)
if err != nil {
return err
}
fi.SetFloat(ret)
case reflect.String:
fi.SetString(s)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
ret, err := strconv.ParseUint(s, 10, 64)
if err != nil {
return err
}
fi.SetUint(ret)
case reflect.Bool:
ret, err := strconv.ParseBool(s)
if err != nil {
return err
}
fi.SetBool(ret)
default:
fmt.Println(t)
continue
}
}
}
return nil
}
/*
判断文件或文件夹是否存在
如果返回的错误为nil,说明文件或文件夹存在
如果返回的错误类型使用os.IsNotExist()判断为true,说明文件或文件夹不存在
如果返回的错误为其它类型,则不确定是否在存在
*/
func PathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
// CheckPath 判断目录是否存在,不存在自动创建
func CheckPath(path string) error {
b, err := PathExists(path)
if err != nil {
return err
}
if b {
return fmt.Errorf("path %s 存在\n", path)
}
err = os.Mkdir(path, os.ModePerm)
if err != nil {
return err
}
return nil
}
// SavePic 下载并保存图片
func SavePic(imgPath, imgUrl, fileName string) error {
res, err := http.Get(imgUrl)
if err != nil {
log.Error("err:%v", err)
return err
}
defer res.Body.Close()
// 获得get请求响应的reader对象
reader := bufio.NewReaderSize(res.Body, 32*1024)
path := imgPath + string(os.PathSeparator) + fileName + ".png"
if ok, _ := PathExists(path); ok {
if err := os.Remove(path); err != nil {
log.Error("err:%v", err)
return err
}
}
file, err := os.Create(path)
if err != nil {
log.Error("err:%v", err)
return err
}
defer file.Close()
// 获得文件的writer对象
writer := bufio.NewWriter(file)
if _, err := io.Copy(writer, reader); err != nil {
log.Error("err:%v", err)
return err
}
return nil
}
// GetSimpleRandomString 获取纯英文大写的随机n位字符串
func GetSimpleRandomString(n int) string {
ret := []byte{}
for i := 0; i < n; i++ {
tmp := rand.Intn(26)
ret = append(ret, byte(tmp+65))
}
return string(ret)
}
var tokenMap = map[string]string{
"1": "G",
"2": "J",
"3": "M",
"4": "S",
"5": "Q",
"6": "B",
"7": "E",
"8": "F",
"9": "I",
"0": "Z",
}
// RandomToken 生成token
func RandomToken(uid int) string {
ran := GetSimpleRandomString(10)
str := strconv.Itoa(uid)
for _, v := range str {
ran += tokenMap[string(v)]
}
return ran
}
// NewOrderID 新生成一个订单id
func NewOrderID(uid int) string {
orderID := ""
str := strconv.Itoa(uid)
for _, v := range str {
orderID += tokenMap[string(v)]
}
return orderID + strconv.FormatInt(time.Now().Unix(), 10)
}
// SliceInt2Int32 数组转换
func SliceInt2Int32(c []int) []uint32 {
ret := []uint32{}
for _, v := range c {
ret = append(ret, uint32(v))
}
return ret
}
// SliceInt322Int 数组转换
func SliceInt322Int(c []uint32) []int {
ret := []int{}
for _, v := range c {
ret = append(ret, int(v))
}
return ret
}
// SliceInt2Int64 数组转换
func SliceInt2Int64(c []int) []int64 {
ret := []int64{}
for _, v := range c {
ret = append(ret, int64(v))
}
return ret
}
// RemoveSlice 根据b中的元素,从a中剔除,相当于两个slice做差
func RemoveSlice(a, b []int) []int {
ret := []int{}
dm := map[int]int{}
for _, v := range b {
dm[v]++
}
for _, v := range a {
if num, ok := dm[v]; ok {
num--
if num == 0 {
delete(dm, v)
} else {
dm[v] = num
}
continue
} else {
ret = append(ret, v)
}
}
return ret
}
// RemoveOne 从a中剔除b
func RemoveOne(a []int, b int) []int {
ret := []int{}
count := 0
for _, v := range a {
if v == b && count == 0 {
count++
continue
}
ret = append(ret, v)
}
return ret
}
// SliceContain a中是否包含b
func SliceContain(a []int, b int) bool {
for _, v := range a {
if v == b {
return true
}
}
return false
}
// SliceContainInt64 a中是否包含b
func SliceContainInt64(a []int64, b int64) bool {
for _, v := range a {
if v == b {
return true
}
}
return false
}
func TrimHiddenCharacter(originStr string) string {
srcRunes := []rune(originStr)
dstRunes := make([]rune, 0, len(srcRunes))
for _, c := range srcRunes {
if c >= 0 && c <= 31 {
continue
}
if c == 127 {
continue
}
dstRunes = append(dstRunes, c)
}
return string(dstRunes)
}
func IsEqualSlice(a, b []int) bool {
dm := map[int]int{}
for _, v := range a {
dm[v]++
}
for _, v := range b {
dm[v]--
}
for _, v := range dm {
if v != 0 {
return false
}
}
return true
}
// GetRandSection 获取区间随机值
func GetRandSection(a, b int) int {
if a >= b {
return a
}
return a + rand.Intn(b-a)
}
// CopySameStruct 将b中的非空字段复制到相同的结构体a中
func CopySameStruct(a, b interface{}) bool {
typa := reflect.TypeOf(a)
typb := reflect.TypeOf(b)
if typa != typb {
return false
}
if typa.Kind() != reflect.Ptr {
return false
}
vala := reflect.ValueOf(a).Elem()
valb := reflect.ValueOf(b).Elem()
// typaE := typa.Elem()
// typbE := typb.Elem()
for i := 0; i < vala.NumField(); i++ {
if valb.Field(i).IsZero() {
continue
}
vala.Field(i).Set(valb.Field(i))
}
return true
}
// 字符串去重
func RemoveDuplication(arr []string) []string {
set := make(map[string]struct{}, len(arr))
j := 0
for _, v := range arr {
_, ok := set[v]
if ok {
continue
}
set[v] = struct{}{}
arr[j] = v
j++
}
return arr[:j]
}
// Abs 取绝对值
func Abs(a int64) int64 {
if a < 0 {
a = -a
}
return a
}
func CleanList(l *list.List) {
e := l.Front()
if e == nil {
return
}
for {
next := e.Next()
l.Remove(e)
if next == nil {
break
}
e = next
}
}
func CheckPhone(phone string) string {
ok, _ := regexp.MatchString("[1-9]{2}[2-9][0-9]{7,8}", phone)
if !ok {
phone = ""
for i := 0; i < 2; i++ {
phone += fmt.Sprintf("%d", rand.Intn(9)+1)
}
phone += fmt.Sprintf("%d", rand.Intn(8)+2)
tmp := rand.Intn(2)
count := 7
if tmp == 0 {
count = 8
}
for i := 0; i < count; i++ {
phone += fmt.Sprintf("%d", rand.Intn(10))
}
}
return phone
}
func CheckCPF(cpf string) string {
if IsCPF(cpf) {
return cpf
}
num := [11]int{}
for i := 0; i < 9; i++ {
num[i] = rand.Intn(9) + 1
}
s1 := 0
for i := 0; i < 9; i++ {
s1 += (10 - i) * num[i]
}
m1 := s1 % 11
if m1 < 2 {
num[9] = 0
} else {
num[9] = 11 - m1
}
s2 := 0
for i := 0; i < 10; i++ {
s2 += num[i] * (11 - i)
}
m2 := s2 % 11
if m2 < 2 {
num[10] = 0
} else {
num[10] = 11 - m2
}
s := ""
for _, v := range num {
s += fmt.Sprintf("%d", v)
}
return s
}
func IsCPF(cpf string) bool {
cpf = strings.ReplaceAll(cpf, ".", "")
cpf = strings.ReplaceAll(cpf, "-", "")
num := StringToInt(cpf)
if len(num) != 11 {
return false
}
s1 := 0
for i := 0; i < len(num)-2; i++ {
s1 += (10 - i) * num[i]
}
m1 := s1 % 11
y := num[9]
if m1 < 2 && y != 0 {
return false
}
if m1 >= 2 && y != (11-m1) {
return false
}
z := num[10]
s2 := 0
for i := 0; i < len(num)-1; i++ {
s2 += num[i] * (11 - i)
}
m2 := s2 % 11
if m2 < 2 && z != 0 {
return false
}
if m2 >= 2 && z != 11-m2 {
return false
}
return true
}
func IndexTryCallback(f func() error, cb func()) {
Go(func() {
for i := 0; i <= 6; i++ {
if i > 0 {
next := time.Duration(i*i) * time.Minute
time.Sleep(next)
}
err := f()
if err == nil {
break
}
log.Error("err:%v next:%v", err, i)
if i == 6 {
cb()
}
}
})
}
func IndexTry(f func() error) {
Go(func() {
for i := 0; i <= 6; i++ {
if i > 0 {
next := time.Duration(i*i) * time.Minute
time.Sleep(next)
}
err := f()
if err == nil {
break
}
log.Error("err:%v next:%v", err, i)
}
})
}
func IndexTryS(f func() error) {
Go(func() {
for i := 0; i <= 6; i++ {
if i > 0 {
next := time.Duration(i*i) * time.Second
time.Sleep(next)
}
err := f()
if err == nil {
break
}
log.Error("err:%v next:%v", err, i)
}
})
}
// 获取下一个整点5分钟时间戳
func GetNext5MinUnix() int64 {
now := time.Now()
zero := GetZeroTime(now)
h, m, _ := now.Clock()
m -= m % 5
last := zero.Add(time.Duration(h) * time.Hour).Add(time.Duration(m) * time.Minute)
return last.Add(5 * time.Minute).Unix()
}
// stringsToInt 数字字符串转数字数组
func StringToInt(s string) []int {
b := []byte(s)
ret := []int{}
for _, v := range b {
if v < 48 || v > 57 {
return nil
}
ret = append(ret, int(v)-48)
}
return ret
}
func ZhToUnicode(raw string) (string, error) {
str, err := strconv.Unquote(strings.Replace(strconv.Quote(raw), `\\u`, `\u`, -1))
if err != nil {
return "", err
}
return str, nil
}
// IsSingle 判断数字是不是单数
func IsSingle(n int) bool {
return n/2*2 != n
}
// GetIntFromString 从字符串s中提取出所有的int
func GetIntFromString(s string) int {
ret := []rune{}
for _, v := range s {
if v < 48 || v > 57 {
continue
}
ret = append(ret, v)
}
tmp := string(ret)
number, err := strconv.Atoi(tmp)
if err != nil {
log.Error("err:%v", err)
return 0
}
return number
}
func FormatUserName(name string) (fn string, ln string) {
if len(name) == 0 {
return
}
name1 := strings.Split(strings.TrimSpace(name), " ")
name2 := []string{}
for _, v := range name1 {
if len(v) == 0 {
continue
}
name2 = append(name2, v)
}
if len(name2) > 1 {
for i, v := range name2 {
if i == len(name2)-1 {
break
}
fn += v
}
ln = name2[len(name2)-1]
} else if len(name2) == 1 {
fn = name2[0]
}
return
}
// FormatNumberBrazil 格式化数字为巴西格式(例如:1234.56 -> "1.234,56"),小数点后全为零时去除小数部分
func FormatNumberBrazil(number float64) string {
// 首先,使用fmt.Sprintf格式化数字,这里使用"%.2f"保证即使是整数也会带有".00"
usFormatted := fmt.Sprintf("%.2f", number)
// 如果小数部分为.00,则去除它
// if strings.HasSuffix(usFormatted, ".00") {
// usFormatted = usFormatted[:len(usFormatted)-3]
// }
usFormatted = strings.TrimSuffix(usFormatted, ".00")
// 将点替换为逗号,作为小数点
step1 := strings.ReplaceAll(usFormatted, ".", ",")
// 分割字符串为整数部分和可能的小数部分
parts := strings.Split(step1, ",")
// 替换整数部分中的千位分隔符
integerPart := parts[0]
var sb strings.Builder
for i, r := range integerPart {
if i > 0 && (len(integerPart)-i)%3 == 0 {
sb.WriteRune('.')
}
sb.WriteRune(r)
}
// 如果有小数部分,且不是"00",将其添加回去
if len(parts) > 1 && parts[1] != "00" {
sb.WriteRune(',')
sb.WriteString(parts[1])
}
return sb.String()
}
func CountDecimals(value float64) int {
// 将浮点数转换为字符串
text := fmt.Sprintf("%v", value)
// 查找小数点位置
pointIndex := strings.Index(text, ".")
if pointIndex == -1 {
// 没有找到小数点,说明没有小数部分
return 0
}
// 去除小数点后面尾随的0
trimmed := strings.TrimRight(text[pointIndex+1:], "0")
// 返回小数部分的长度
return len(trimmed)
}
// 根据权重,从数组中随机一个元素
// name 权重字段名(该字段值必须为整型)
func RandomOneEleFromSlice(slice interface{}, name string) int {
ref := reflect.ValueOf(slice)
var total int64
for i := 0; i < ref.Len(); i++ {
tmp := ref.Index(i)
if tmp.Kind() == reflect.Pointer {
tmp = tmp.Elem()
}
total += tmp.FieldByName(name).Int()
}
ran := rand.Int63n(total)
var rans int64
for i := 0; i < ref.Len(); i++ {
tmp := ref.Index(i)
if tmp.Kind() == reflect.Pointer {
tmp = tmp.Elem()
}
rans += tmp.FieldByName(name).Int()
if ran < rans {
return i
}
}
return 0
}
func RandBetween64(min, max int64) int64 {
return rand.Int63n(max-min+1) + min
}
func RandBetween(min, max int) int {
return rand.Intn(max-min+1) + min
}
// HashMarshal 用于将结构体序列化为Redis哈希
func HashMarshal(v interface{}) (map[string]interface{}, error) {
result := make(map[string]interface{})
vType := reflect.TypeOf(v)
vValue := reflect.ValueOf(v)
if vType.Kind() != reflect.Struct {
return nil, fmt.Errorf("HashMarshal: expected a struct type, got %v", vType.Kind())
}
for i := 0; i < vType.NumField(); i++ {
field := vType.Field(i)
fieldValue := vValue.Field(i)
redisTag := field.Tag.Get("redis")
if redisTag == "" || redisTag == "-" {
continue
}
var value interface{}
switch fieldValue.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
value = fieldValue.Int()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
value = fieldValue.Uint()
case reflect.Float32, reflect.Float64:
value = fieldValue.Float()
case reflect.String:
value = fieldValue.String()
case reflect.Bool:
value = fieldValue.Bool()
case reflect.Struct:
if t, ok := fieldValue.Interface().(time.Time); ok {
value = t.Format(time.RFC3339)
} else {
return nil, fmt.Errorf("HashMarshal: unsupported struct type %v for field %s", fieldValue.Kind(), field.Name)
}
default:
return nil, fmt.Errorf("HashMarshal: unsupported type %v for field %s", fieldValue.Kind(), field.Name)
}
result[redisTag] = value
}
return result, nil
}
// HashUnmarshal 用于从Redis哈希反序列化为结构体
func HashUnmarshal(data map[string]string, v interface{}) error {
vType := reflect.TypeOf(v).Elem()
vValue := reflect.ValueOf(v).Elem()
if vType.Kind() != reflect.Struct {
return fmt.Errorf("HashUnmarshal: expected a struct type, got %v", vType.Kind())
}
for i := 0; i < vType.NumField(); i++ {
field := vType.Field(i)
fieldValue := vValue.Field(i)
redisTag := field.Tag.Get("redis")
if redisTag == "" || redisTag == "-" {
continue
}
strValue, ok := data[redisTag]
if !ok {
continue
}
switch fieldValue.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
intValue, err := strconv.ParseInt(strValue, 10, 64)
if err != nil {
return err
}
fieldValue.SetInt(intValue)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
uintValue, err := strconv.ParseUint(strValue, 10, 64)
if err != nil {
return err
}
fieldValue.SetUint(uintValue)
case reflect.Float32, reflect.Float64:
floatValue, err := strconv.ParseFloat(strValue, 64)
if err != nil {
return err
}
fieldValue.SetFloat(floatValue)
case reflect.String:
fieldValue.SetString(strValue)
case reflect.Bool:
boolValue, err := strconv.ParseBool(strValue)
if err != nil {
return err
}
fieldValue.SetBool(boolValue)
case reflect.Struct:
if fieldValue.Type() == reflect.TypeOf(time.Time{}) {
t, err := time.Parse(time.RFC3339, strValue)
if err != nil {
return err
}
fieldValue.Set(reflect.ValueOf(t))
} else {
return fmt.Errorf("HashUnmarshal: unsupported struct type %v for field %s", fieldValue.Kind(), field.Name)
}
default:
return fmt.Errorf("HashUnmarshal: unsupported type %v for field %s", fieldValue.Kind(), field.Name)
}
}
return nil
}
func Int64SliceToStringSlice(int64Slice []int64) []string {
stringSlice := make([]string, len(int64Slice))
for i, num := range int64Slice {
stringSlice[i] = strconv.FormatInt(num, 10)
}
return stringSlice
}
func StringToInt64Slice(s, sep string) ([]int64, error) {
// 使用分隔符拆分字符串
parts := strings.Split(s, sep)
// 创建一个空的 []int64 切片用于存储转换后的数字
int64Slice := make([]int64, len(parts))
// 遍历拆分后的字符串部分并转换为 int64
for i, part := range parts {
num, err := strconv.ParseInt(part, 10, 64)
if err != nil {
return nil, err // 如果转换失败,返回错误
}
int64Slice[i] = num
}
return int64Slice, nil
}
// 通过总数Count分成一个递增数列
func GenerateSequence(N, M int64) ([]int64, error) {
length := int64(5)
// 初步生成一个递增数列 [M, M+1, ..., M+5]
sequence := make([]int64, length)
for i := int64(0); i < length; i++ {
sequence[i] = M + i
}
// 计算初步生成数列的总和
sumInitial := (2*M + length - 1) * length / 2
// 如果初步生成数列的总和已经大于 N,则无法生成
if sumInitial > N {
return nil, fmt.Errorf("无法生成满足条件的数列")
}
// 计算剩余需要分配的值
remaining := N - sumInitial
// 将剩余的值均匀分配到数列中,从后往前加值,保持递增
for i := length - 1; i >= 0 && remaining > 0; i-- {
sequence[i] += remaining
remaining = 0
}
return sequence, nil
}