github.com/godaddy-x/freego@v1.0.156/utils/common.go (about) 1 package utils 2 3 /** 4 * @author shadow 5 * @createby 2018.10.10 6 */ 7 8 import ( 9 "bytes" 10 "crypto/hmac" 11 "crypto/md5" 12 "crypto/sha1" 13 "crypto/sha256" 14 "crypto/sha512" 15 "encoding/base64" 16 "encoding/gob" 17 "encoding/hex" 18 "errors" 19 "github.com/godaddy-x/freego/utils/decimal" 20 "github.com/godaddy-x/freego/utils/snowflake" 21 "github.com/google/uuid" 22 "io/ioutil" 23 "log" 24 "net" 25 "net/http" 26 "os" 27 "strconv" 28 "strings" 29 "time" 30 "unicode/utf8" 31 "unsafe" 32 ) 33 34 var ( 35 cst_sh, _ = time.LoadLocation("Asia/Shanghai") //上海 36 random_byte_sp = Str2Bytes("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^*+-_=") 37 local_secret_key = createDefaultLocalSecretKey() 38 local_token_secret_key = createLocalTokenSecretKey() 39 snowflake_node = GetSnowflakeNode(0) 40 ) 41 42 const ( 43 xforwardedfor = "X-Forwarded-For" 44 xrealip = "X-Real-IP" 45 time_fmt = "2006-01-02 15:04:05.000" 46 date_fmt = "2006-01-02" 47 OneDay = 86400000 48 OneWeek = OneDay * 7 49 TwoWeek = OneDay * 14 50 OneMonth = OneDay * 30 51 ) 52 53 func GetSnowflakeNode(n int64) *snowflake.Node { 54 node, err := snowflake.NewNode(n) 55 if err != nil { 56 panic(err) 57 } 58 return node 59 } 60 61 func GetLocalSecretKey() string { 62 return local_secret_key 63 } 64 65 func GetLocalTokenSecretKey() string { 66 return local_token_secret_key 67 } 68 69 func createDefaultLocalSecretKey() string { 70 arr := []int{65, 68, 45, 34, 67, 23, 53, 61, 12, 69, 23, 42, 24, 66, 29, 39, 10, 1, 8, 55, 60, 40, 64, 62} 71 return CreateLocalSecretKey(arr...) 72 } 73 74 func createLocalTokenSecretKey() string { 75 arr := []int{69, 63, 72, 43, 34, 68, 20, 55, 67, 19, 64, 21, 46, 62, 61, 38, 63, 13, 18, 52, 61, 44, 65, 66} 76 return CreateLocalSecretKey(arr...) 77 } 78 79 func CreateLocalSecretKey(arr ...int) string { 80 l := len(random_byte_sp) 81 var result []byte 82 for _, v := range arr { 83 if v > l { 84 panic("key arr value > random length") 85 } 86 result = append(result, random_byte_sp[v]) 87 } 88 return Bytes2Str(result) 89 } 90 91 // 对象转对象 92 func JsonToAny(src interface{}, target interface{}) error { 93 if src == nil || target == nil { 94 return errors.New("src or target is nil") 95 } 96 if data, err := JsonMarshal(src); err != nil { 97 return err 98 } else if err = JsonUnmarshal(data, target); err != nil { 99 return err 100 } 101 return nil 102 } 103 104 func MathAbs(n int64) int64 { 105 y := n >> 63 106 return (n ^ y) - y 107 } 108 109 // 截取字符串 start 起点下标 end 结束下标 110 func Substr(str string, start int, end int) string { 111 return str[start:end] 112 } 113 114 // 获取本机内网IP 115 func GetLocalIP() string { 116 addrs, err := net.InterfaceAddrs() 117 if err != nil { 118 log.Println(err) 119 return "" 120 } 121 for _, address := range addrs { // 检查ip地址判断是否回环地址 122 if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { 123 if ipnet.IP.To4() != nil { 124 return ipnet.IP.String() 125 } 126 } 127 } 128 return "" 129 } 130 131 // 判定指定字符串是否存在于原字符串 132 func HasStr(s1 string, s2 string) bool { 133 if s1 == s2 { 134 return true 135 } 136 if len(s1) > 0 && len(s2) > 0 && strings.Index(s1, s2) > -1 { 137 return true 138 } 139 return false 140 } 141 142 // 高性能拼接字符串 143 func AddStr(input ...interface{}) string { 144 if input == nil || len(input) == 0 { 145 return "" 146 } 147 var rstr bytes.Buffer 148 for _, vs := range input { 149 if v, b := vs.(string); b { 150 rstr.WriteString(v) 151 } else if v, b := vs.([]byte); b { 152 rstr.WriteString(Bytes2Str(v)) 153 } else if v, b := vs.(error); b { 154 rstr.WriteString(v.Error()) 155 } else { 156 rstr.WriteString(AnyToStr(vs)) 157 } 158 } 159 return Bytes2Str(rstr.Bytes()) 160 } 161 162 // 高性能拼接错误对象 163 func Error(input ...interface{}) error { 164 msg := AddStr(input...) 165 return errors.New(msg) 166 } 167 168 // 读取JSON格式配置文件 169 func ReadJsonConfig(conf []byte, result interface{}) error { 170 return JsonUnmarshal(conf, result) 171 } 172 173 // string to int 174 func StrToInt(str string) (int, error) { 175 b, err := strconv.Atoi(str) 176 if err != nil { 177 return 0, errors.New("string to int failed") 178 } 179 return b, nil 180 } 181 182 // string to int8 183 func StrToInt8(str string) (int8, error) { 184 b, err := strconv.ParseInt(str, 10, 64) 185 if err != nil { 186 return 0, errors.New("string to int8 failed") 187 } 188 return int8(b), nil 189 } 190 191 // string to int16 192 func StrToInt16(str string) (int16, error) { 193 b, err := strconv.ParseInt(str, 10, 64) 194 if err != nil { 195 return 0, errors.New("string to int16 failed") 196 } 197 return int16(b), nil 198 } 199 200 // string to int32 201 func StrToInt32(str string) (int32, error) { 202 b, err := strconv.ParseInt(str, 10, 64) 203 if err != nil { 204 return 0, errors.New("string to int32 failed") 205 } 206 return int32(b), nil 207 } 208 209 // string to int64 210 func StrToInt64(str string) (int64, error) { 211 b, err := strconv.ParseInt(str, 10, 64) 212 if err != nil { 213 return 0, errors.New("string to int64 failed") 214 } 215 return b, nil 216 } 217 218 // float64转int64 219 func Float64ToInt64(f float64) int64 { 220 a := decimal.NewFromFloat(f) 221 return a.IntPart() 222 } 223 224 // string to bool 225 func StrToBool(str string) (bool, error) { 226 if str == "true" { 227 return true, nil 228 } else if str == "false" { 229 return false, nil 230 } else { 231 return false, Error("not bool") 232 } 233 } 234 235 // 基础类型 int uint float string bool 236 // 复杂类型 json 237 func AnyToStr(any interface{}) string { 238 if any == nil { 239 return "" 240 } 241 if str, ok := any.(string); ok { 242 return str 243 } else if str, ok := any.([]byte); ok { 244 return Bytes2Str(str) 245 } else if str, ok := any.(int); ok { 246 return strconv.FormatInt(int64(str), 10) 247 } else if str, ok := any.(int8); ok { 248 return strconv.FormatInt(int64(str), 10) 249 } else if str, ok := any.(int16); ok { 250 return strconv.FormatInt(int64(str), 10) 251 } else if str, ok := any.(int32); ok { 252 return strconv.FormatInt(int64(str), 10) 253 } else if str, ok := any.(int64); ok { 254 return strconv.FormatInt(str, 10) 255 } else if str, ok := any.(float32); ok { 256 return strconv.FormatFloat(float64(str), 'f', 16, 64) 257 } else if str, ok := any.(float64); ok { 258 return strconv.FormatFloat(str, 'f', 16, 64) 259 } else if str, ok := any.(uint); ok { 260 return strconv.FormatUint(uint64(str), 10) 261 } else if str, ok := any.(uint8); ok { 262 return strconv.FormatUint(uint64(str), 10) 263 } else if str, ok := any.(uint16); ok { 264 return strconv.FormatUint(uint64(str), 10) 265 } else if str, ok := any.(uint32); ok { 266 return strconv.FormatUint(uint64(str), 10) 267 } else if str, ok := any.(uint64); ok { 268 return strconv.FormatUint(str, 10) 269 } else if str, ok := any.(bool); ok { 270 if str { 271 return "true" 272 } 273 return "false" 274 } else { 275 if ret, err := JsonMarshal(any); err != nil { 276 log.Println("any to json failed: ", err) 277 return "" 278 } else { 279 return Bytes2Str(ret) 280 } 281 } 282 } 283 284 // 65-96大写字母 97-122小写字母 285 func UpperFirst(str string) string { 286 var upperStr string 287 vv := []rune(str) // 后文有介绍 288 for i := 0; i < len(vv); i++ { 289 if i == 0 { 290 if vv[i] >= 97 && vv[i] <= 122 { // 小写字母范围 291 vv[i] -= 32 // string的码表相差32位 292 upperStr += string(vv[i]) 293 } else { 294 return str 295 } 296 } else { 297 upperStr += string(vv[i]) 298 } 299 } 300 return upperStr 301 } 302 303 // 65-96大写字母 97-122小写字母 304 func LowerFirst(str string) string { 305 var upperStr string 306 vv := []rune(str) // 后文有介绍 307 for i := 0; i < len(vv); i++ { 308 if i == 0 { 309 if vv[i] >= 65 && vv[i] <= 96 { // 大写字母范围 310 vv[i] += 32 // string的码表相差32位 311 upperStr += string(vv[i]) 312 } else { 313 return str 314 } 315 } else { 316 upperStr += string(vv[i]) 317 } 318 } 319 return upperStr 320 } 321 322 // NextIID 获取雪花int64 ID,默认为1024区 323 func NextIID() int64 { 324 return snowflake_node.Generate().Int64() 325 } 326 327 // NextSID 获取雪花string ID,默认为1024区 328 func NextSID() string { 329 return snowflake_node.Generate().String() 330 } 331 332 func GetUUID(replace ...bool) string { 333 uid, err := uuid.NewUUID() 334 if err != nil { 335 log.Println("uuid failed:", err) 336 } 337 if len(replace) > 0 { 338 return strings.ReplaceAll(uid.String(), "-", "") 339 } 340 return uid.String() 341 } 342 343 // 读取文件 344 func ReadFile(path string) ([]byte, error) { 345 if len(path) == 0 { 346 return nil, Error("path is nil") 347 } 348 if b, err := ioutil.ReadFile(path); err != nil { 349 return nil, Error("read file [", path, "] failed: ", err) 350 } else { 351 return b, nil 352 } 353 } 354 355 // 读取本地JSON配置文件 356 func ReadLocalJsonConfig(path string, result interface{}) error { 357 if data, err := ReadFile(path); err != nil { 358 return err 359 } else { 360 return JsonUnmarshal(data, result) 361 } 362 } 363 364 // 转换成小数 365 func StrToFloat(str string) (float64, error) { 366 if v, err := decimal.NewFromString(str); err != nil { 367 return 0, err 368 } else { 369 r, _ := v.Float64() 370 return r, nil 371 } 372 } 373 374 // MD5加密 375 func MD5(s string, useBase64 ...bool) string { 376 has := md5.Sum(Str2Bytes(s)) 377 if len(useBase64) == 0 { 378 return hex.EncodeToString(has[:]) 379 } 380 return Base64Encode(has[:]) 381 } 382 383 // HMAC-MD5加密 384 func HMAC_MD5(data, key string, useBase64 ...bool) string { 385 hmac := hmac.New(md5.New, Str2Bytes(key)) 386 hmac.Write(Str2Bytes(data)) 387 if len(useBase64) == 0 { 388 return hex.EncodeToString(hmac.Sum([]byte(nil))) 389 } 390 return Base64Encode(hmac.Sum([]byte(nil))) 391 } 392 393 // HMAC-SHA1加密 394 func HMAC_SHA1(data, key string, useBase64 ...bool) string { 395 hmac := hmac.New(sha1.New, Str2Bytes(key)) 396 hmac.Write(Str2Bytes(data)) 397 if len(useBase64) == 0 { 398 return hex.EncodeToString(hmac.Sum([]byte(nil))) 399 } 400 return Base64Encode(hmac.Sum([]byte(nil))) 401 } 402 403 // HMAC-SHA256加密 404 func HMAC_SHA256(data, key string, useBase64 ...bool) string { 405 hmac := hmac.New(sha256.New, Str2Bytes(key)) 406 hmac.Write(Str2Bytes(data)) 407 if len(useBase64) == 0 { 408 return hex.EncodeToString(hmac.Sum([]byte(nil))) 409 } 410 return Base64Encode(hmac.Sum([]byte(nil))) 411 } 412 413 func HMAC_SHA512(data, key string, useBase64 ...bool) string { 414 hmac := hmac.New(sha512.New, Str2Bytes(key)) 415 hmac.Write(Str2Bytes(data)) 416 if len(useBase64) == 0 { 417 return hex.EncodeToString(hmac.Sum([]byte(nil))) 418 } 419 return Base64Encode(hmac.Sum([]byte(nil))) 420 } 421 422 // SHA256加密 423 func SHA256(s string, useBase64 ...bool) string { 424 h := sha256.New() 425 h.Write(Str2Bytes(s)) 426 bs := h.Sum(nil) 427 if len(useBase64) == 0 { 428 return hex.EncodeToString(bs) 429 } 430 return Base64Encode(bs) 431 } 432 433 func SHA512(s string, useBase64 ...bool) string { 434 h := sha512.New() 435 h.Write(Str2Bytes(s)) 436 bs := h.Sum(nil) 437 if len(useBase64) == 0 { 438 return hex.EncodeToString(bs) 439 } 440 return Base64Encode(bs) 441 } 442 443 // SHA256加密 444 func SHA1(s string, useBase64 ...bool) string { 445 h := sha1.New() 446 h.Write(Str2Bytes(s)) 447 bs := h.Sum(nil) 448 if len(useBase64) == 0 { 449 return hex.EncodeToString(bs) 450 } 451 return Base64Encode(bs) 452 } 453 454 // default base64 - 正向 455 func Base64Encode(input interface{}) string { 456 var dataByte []byte 457 if v, b := input.(string); b { 458 dataByte = Str2Bytes(v) 459 } else if v, b := input.([]byte); b { 460 dataByte = v 461 } else { 462 return "" 463 } 464 if dataByte == nil || len(dataByte) == 0 { 465 return "" 466 } 467 return base64.StdEncoding.EncodeToString(dataByte) 468 } 469 470 // url base64 - 正向 471 //func Base64URLEncode(input interface{}) string { 472 // var dataByte []byte 473 // if v, b := input.(string); b { 474 // dataByte = Str2Bytes(v) 475 // } else if v, b := input.([]byte); b { 476 // dataByte = v 477 // } else { 478 // return "" 479 // } 480 // if dataByte == nil || len(dataByte) == 0 { 481 // return "" 482 // } 483 // return base64.URLEncoding.EncodeToString(dataByte) 484 //} 485 486 // default base64 - 逆向 487 func Base64Decode(input interface{}) []byte { 488 dataStr := "" 489 if v, b := input.(string); b { 490 dataStr = v 491 } else if v, b := input.([]byte); b { 492 dataStr = Bytes2Str(v) 493 } else { 494 return nil 495 } 496 if len(dataStr) == 0 { 497 return nil 498 } 499 if r, err := base64.StdEncoding.DecodeString(dataStr); err != nil { 500 return nil 501 } else { 502 return r 503 } 504 } 505 506 // url base64 - 逆向 507 //func Base64URLDecode(input interface{}) []byte { 508 // dataStr := "" 509 // if v, b := input.(string); b { 510 // dataStr = v 511 // } else if v, b := input.([]byte); b { 512 // dataStr = Bytes2Str(v) 513 // } else { 514 // return nil 515 // } 516 // if len(dataStr) == 0 { 517 // return nil 518 // } 519 // if r, err := base64.URLEncoding.DecodeString(dataStr); err != nil { 520 // return nil 521 // } else { 522 // return r 523 // } 524 //} 525 526 func ToJsonBase64(input interface{}) (string, error) { 527 if input == nil { 528 input = map[string]string{} 529 } 530 b, err := JsonMarshal(input) 531 if err != nil { 532 return "", err 533 } 534 return Base64Encode(b), nil 535 } 536 537 func ParseJsonBase64(input interface{}, ouput interface{}) error { 538 b := Base64Decode(input) 539 if b == nil || len(b) == 0 { 540 return Error("base64 data decode failed") 541 } 542 return JsonUnmarshal(b, ouput) 543 } 544 545 // 获取项目绝对路径 546 func GetPath() string { 547 if path, err := os.Getwd(); err != nil { 548 log.Println(err) 549 return "" 550 } else { 551 return path 552 } 553 } 554 555 // RemoteIp 返回远程客户端的 IP,如 192.168.1.1 556 func ClientIP(req *http.Request) string { 557 remoteAddr := req.RemoteAddr 558 if ip := req.Header.Get(xrealip); ip != "" { 559 remoteAddr = ip 560 } else if ip = req.Header.Get(xforwardedfor); ip != "" { 561 remoteAddr = ip 562 } else { 563 remoteAddr, _, _ = net.SplitHostPort(remoteAddr) 564 } 565 566 if remoteAddr == "::1" { 567 remoteAddr = "127.0.0.1" 568 } 569 return remoteAddr 570 } 571 572 // 字符串转字节数组 573 func Str2Bytes(s string) []byte { 574 x := (*[2]uintptr)(unsafe.Pointer(&s)) 575 h := [3]uintptr{x[0], x[1], x[1]} 576 return *(*[]byte)(unsafe.Pointer(&h)) 577 } 578 579 // 字节数组转字符串 580 func Bytes2Str(b []byte) string { 581 return *(*string)(unsafe.Pointer(&b)) 582 } 583 584 // 无限等待 585 func StartWait(msg string) { 586 log.Println(msg) 587 select {} 588 } 589 590 // 检测int数值是否在区间 591 func CheckInt(c int, vs ...int) bool { 592 for _, v := range vs { 593 if v == c { 594 return true 595 } 596 } 597 return false 598 } 599 600 // 检测int64数值是否在区间 601 func CheckInt64(c int64, vs ...int64) bool { 602 for _, v := range vs { 603 if v == c { 604 return true 605 } 606 } 607 return false 608 } 609 610 // 检测int64数值是否在区间 611 func CheckRangeInt64(c, min, max int64) bool { 612 if c >= min && c <= max { 613 return true 614 } 615 return false 616 } 617 618 // 检测int数值是否在区间 619 func CheckRangeInt(c, min, max int) bool { 620 if c >= min && c <= max { 621 return true 622 } 623 return false 624 } 625 626 // 检测string数值是否在区间 627 func CheckStr(c string, vs ...string) bool { 628 for _, v := range vs { 629 if v == c { 630 return true 631 } 632 } 633 return false 634 } 635 636 // 保留小数位 637 func Shift(input interface{}, ln int, fz bool) string { 638 var data decimal.Decimal 639 if v, b := input.(string); b { 640 if ret, err := decimal.NewFromString(v); err != nil { 641 return "" 642 } else { 643 data = ret 644 } 645 } else if v, b := input.(float32); b { 646 data = decimal.NewFromFloat32(v) 647 } else if v, b := input.(float64); b { 648 data = decimal.NewFromFloat(v) 649 } else { 650 return "" 651 } 652 part1 := data.String() 653 part2 := "" 654 if strings.Index(part1, ".") != -1 { 655 dataStr_ := strings.Split(part1, ".") 656 part1 = dataStr_[0] 657 part2 = dataStr_[1] 658 if len(part2) > ln { 659 part2 = Substr(part2, 0, ln) 660 } 661 } 662 if fz && ln > 0 && len(part2) < ln { 663 var zero string 664 for i := 0; i < ln-len(part2); i++ { 665 zero = AddStr(zero, "0") 666 } 667 part2 = AddStr(part2, zero) 668 } 669 if len(part2) > 0 { 670 part1 = AddStr(part1, ".", part2) 671 } 672 return part1 673 } 674 675 func Reverse(s string) string { 676 runes := []rune(s) 677 for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 { 678 runes[i], runes[j] = runes[j], runes[i] 679 } 680 return string(runes) 681 } 682 683 func ReverseBase64(s string) string { 684 return Base64Encode(ReverseStr(s, 0, 12, 12, 12, 24, 8)) 685 } 686 687 func ReverseStr(s string, x ...int) string { 688 a := Substr(s, x[0], x[1]) 689 b := Substr(s, x[2], x[3]) 690 c := Substr(s, x[4], x[5]) 691 return Reverse(AddStr(c, a, b)) 692 } 693 694 func InArray(p interface{}) []interface{} { 695 if p == nil { 696 return []interface{}{} 697 } 698 if data, ok := p.([]int); ok { 699 result := make([]interface{}, 0, len(data)) 700 for _, v := range data { 701 result = append(result, v) 702 } 703 return result 704 } else if data, ok := p.([]int64); ok { 705 result := make([]interface{}, 0, len(data)) 706 for _, v := range data { 707 result = append(result, v) 708 } 709 return result 710 } else if data, ok := p.([]string); ok { 711 result := make([]interface{}, 0, len(data)) 712 for _, v := range data { 713 result = append(result, v) 714 } 715 return result 716 } 717 return []interface{}{} 718 } 719 720 func Div(a, b interface{}, n int32) (string, error) { 721 x, err := decimal.NewFromString(AnyToStr(a)) 722 if err != nil { 723 return "", err 724 } 725 y, err := decimal.NewFromString(AnyToStr(b)) 726 if err != nil { 727 return "", err 728 } 729 return x.DivRound(y, n).String(), nil 730 } 731 732 func ShiftN(a interface{}, n int32) (string, error) { 733 x, err := decimal.NewFromString(AnyToStr(a)) 734 if err != nil { 735 return "", err 736 } 737 return x.Shift(n).String(), nil 738 } 739 740 func Mul(a, b interface{}) (string, error) { 741 x, err := decimal.NewFromString(AnyToStr(a)) 742 if err != nil { 743 return "", err 744 } 745 y, err := decimal.NewFromString(AnyToStr(b)) 746 if err != nil { 747 return "", err 748 } 749 return x.Mul(y).String(), nil 750 } 751 752 func Add(a, b interface{}) (string, error) { 753 x, err := decimal.NewFromString(AnyToStr(a)) 754 if err != nil { 755 return "", err 756 } 757 y, err := decimal.NewFromString(AnyToStr(b)) 758 if err != nil { 759 return "", err 760 } 761 return x.Add(y).String(), nil 762 } 763 764 func Sub(a, b interface{}) (string, error) { 765 x, err := decimal.NewFromString(AnyToStr(a)) 766 if err != nil { 767 return "", err 768 } 769 y, err := decimal.NewFromString(AnyToStr(b)) 770 if err != nil { 771 return "", err 772 } 773 return x.Sub(y).String(), nil 774 } 775 776 // a>b=1 a=b=0 a<b=-1 777 func Cmp(a, b interface{}) int { 778 x, _ := decimal.NewFromString(AnyToStr(a)) 779 y, _ := decimal.NewFromString(AnyToStr(b)) 780 return x.Cmp(y) 781 } 782 783 // 获取混合字符串实际长度 784 func Len(o interface{}) int { 785 return utf8.RuneCountInString(AnyToStr(o)) 786 } 787 788 // 获取并校验字符串长度 789 func CheckLen(o interface{}, min, max int) bool { 790 l := Len(o) 791 if l >= min && l <= max { 792 return true 793 } 794 return false 795 } 796 797 // 获取并校验字符串长度 798 func CheckStrLen(str string, min, max int) bool { 799 l := len(str) 800 if l >= min && l <= max { 801 return true 802 } 803 return false 804 } 805 806 func MatchFilterURL(requestPath string, matchPattern []string) bool { 807 if matchPattern == nil || len(matchPattern) == 0 { 808 return true 809 } 810 for _, pattern := range matchPattern { 811 // case 1 812 if requestPath == pattern || pattern == "/*" { 813 return true 814 } 815 // case 2 - Path Match ("/test*", "/test/*", "/test/test*") 816 if pattern == "/*" { 817 return true 818 } 819 if strings.HasSuffix(pattern, "*") { 820 l := len(pattern) - 1 821 if len(requestPath) < l { 822 return false 823 } 824 if requestPath[0:l] == pattern[0:l] { 825 return true 826 } 827 } 828 } 829 return false 830 } 831 832 func FmtDiv(v string, d int64) string { 833 if len(v) == 0 { 834 return "0" 835 } 836 if d == 0 { 837 return v 838 } 839 x, err := decimal.NewFromString(v) 840 if err != nil { 841 return "0" 842 } 843 return x.Shift(-int32(d)).String() 844 } 845 846 func FmtZero(r string) string { 847 if len(r) == 0 { 848 return "0" 849 } 850 a := decimal.New(0, 0) 851 b, _ := decimal.NewFromString(r) 852 a = a.Add(b) 853 return a.String() 854 } 855 856 // 深度复制对象 857 func DeepCopy(dst, src interface{}) error { 858 var buf bytes.Buffer 859 if err := gob.NewEncoder(&buf).Encode(src); err != nil { 860 return Error("深度复制对象序列化异常: ", err.Error()) 861 } 862 if err := gob.NewDecoder(bytes.NewBuffer(buf.Bytes())).Decode(dst); err != nil { 863 return Error("深度复制对象反序列异常: ", err.Error()) 864 } 865 return nil 866 }