|
@@ -1,18 +1,140 @@
|
|
|
package helper
|
|
|
|
|
|
-import "strings"
|
|
|
+import (
|
|
|
+ "encoding/binary"
|
|
|
+ "math/rand"
|
|
|
+ "net"
|
|
|
+ "os"
|
|
|
+ "reflect"
|
|
|
+ "strconv"
|
|
|
+ "strings"
|
|
|
+ "time"
|
|
|
+)
|
|
|
|
|
|
+//LowerFirst Make a string's first character lowercase
|
|
|
func LowerFirst(s string) string {
|
|
|
isFirst := true
|
|
|
return strings.Map(func(r rune) rune {
|
|
|
if isFirst && r >= 'A' && r <= 'Z' {
|
|
|
- return r + 32
|
|
|
+ r = r + 32
|
|
|
}
|
|
|
isFirst = false
|
|
|
return r
|
|
|
}, s)
|
|
|
}
|
|
|
|
|
|
+//UpperFirst Make a string's first character uppercase
|
|
|
+func UpperFirst(s string) string {
|
|
|
+ isFirst := true
|
|
|
+ return strings.Map(func(r rune) rune {
|
|
|
+ if isFirst && r >= 'a' && r <= 'z' {
|
|
|
+ r = r - 32
|
|
|
+ }
|
|
|
+ isFirst = false
|
|
|
+ return r
|
|
|
+ }, s)
|
|
|
+}
|
|
|
+
|
|
|
+//InArray Checks if a value exists in an array
|
|
|
+func InArray(needle interface{}, haystack interface{}) bool {
|
|
|
+ val := reflect.ValueOf(haystack)
|
|
|
+ switch val.Kind() {
|
|
|
+ case reflect.Slice, reflect.Array:
|
|
|
+ for i := 0; i < val.Len(); i++ {
|
|
|
+ if reflect.DeepEqual(needle, val.Index(i).Interface()) {
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ case reflect.Map:
|
|
|
+ for _, k := range val.MapKeys() {
|
|
|
+ if reflect.DeepEqual(needle, val.MapIndex(k).Interface()) {
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ panic("haystack: haystack type muset be slice, array or map")
|
|
|
+ }
|
|
|
+
|
|
|
+ return false
|
|
|
+}
|
|
|
+
|
|
|
+//IsEmpty Determine whether a variable is empty
|
|
|
+func IsEmpty(val interface{}) bool {
|
|
|
+ if val == nil {
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ v := reflect.ValueOf(val)
|
|
|
+ switch v.Kind() {
|
|
|
+ case reflect.String, reflect.Array:
|
|
|
+ return v.Len() == 0
|
|
|
+ case reflect.Map, reflect.Slice:
|
|
|
+ return v.Len() == 0 || v.IsNil()
|
|
|
+ case reflect.Bool:
|
|
|
+ return !v.Bool()
|
|
|
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
|
+ return v.Int() == 0
|
|
|
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
|
|
+ return v.Uint() == 0
|
|
|
+ case reflect.Float32, reflect.Float64:
|
|
|
+ return v.Float() == 0
|
|
|
+ case reflect.Interface, reflect.Ptr:
|
|
|
+ return v.IsNil()
|
|
|
+ }
|
|
|
+ return reflect.DeepEqual(val, reflect.Zero(v.Type()).Interface())
|
|
|
+}
|
|
|
+
|
|
|
+//IsNumeric Finds whether a variable is a number or a numeric string
|
|
|
+func IsNumeric(val interface{}) bool {
|
|
|
+ switch val.(type) {
|
|
|
+ case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
|
|
|
+ return true
|
|
|
+ case float32, float64, complex64, complex128:
|
|
|
+ return true
|
|
|
+ case string:
|
|
|
+ str := val.(string)
|
|
|
+ if str == "" {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ // Trim any whitespace
|
|
|
+ str = strings.TrimSpace(str)
|
|
|
+ if str[0] == '-' || str[0] == '+' {
|
|
|
+ if len(str) == 1 {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ str = str[1:]
|
|
|
+ }
|
|
|
+ // hex
|
|
|
+ if len(str) > 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X') {
|
|
|
+ for _, h := range str[2:] {
|
|
|
+ if !((h >= '0' && h <= '9') || (h >= 'a' && h <= 'f') || (h >= 'A' && h <= 'F')) {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ // 0-9, Point, Scientific
|
|
|
+ p, s, l := 0, 0, len(str)
|
|
|
+ for i, v := range str {
|
|
|
+ if v == '.' { // Point
|
|
|
+ if p > 0 || s > 0 || i+1 == l {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ p = i
|
|
|
+ } else if v == 'e' || v == 'E' { // Scientific
|
|
|
+ if i == 0 || s > 0 || i+1 == l {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ s = i
|
|
|
+ } else if v < '0' || v > '9' {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ return false
|
|
|
+}
|
|
|
+
|
|
|
+//BreakUp break strings
|
|
|
func BreakUp(s string) []string {
|
|
|
length := len(s)
|
|
|
b := make([]byte, length)
|
|
@@ -36,6 +158,100 @@ func BreakUp(s string) []string {
|
|
|
return ss
|
|
|
}
|
|
|
|
|
|
+//Camel2id eg SendMail into send-mail
|
|
|
func Camel2id(s string) string {
|
|
|
return strings.Join(BreakUp(s), "-")
|
|
|
}
|
|
|
+
|
|
|
+//Rand Generate a random integer
|
|
|
+func Rand(min, max int) int {
|
|
|
+ if min > max {
|
|
|
+ panic("min: min cannot be greater than max")
|
|
|
+ }
|
|
|
+ if int31 := 1<<31 - 1; max > int31 {
|
|
|
+ panic("max: max can not be greater than " + strconv.Itoa(int31))
|
|
|
+ }
|
|
|
+ if min == max {
|
|
|
+ return min
|
|
|
+ }
|
|
|
+ r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
|
+ return r.Intn(max+1-min) + min
|
|
|
+}
|
|
|
+
|
|
|
+//FileExists Checks whether a file or directory exists
|
|
|
+func FileExists(filename string) bool {
|
|
|
+ if _, err := os.Stat(filename); err != nil && os.IsNotExist(err) {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ return true
|
|
|
+}
|
|
|
+
|
|
|
+//IsDir Tells whether the filename is a directory
|
|
|
+func IsDir(filename string) (bool, error) {
|
|
|
+ fd, err := os.Stat(filename)
|
|
|
+ if err != nil {
|
|
|
+ return false, err
|
|
|
+ }
|
|
|
+ fm := fd.Mode()
|
|
|
+ return fm.IsDir(), nil
|
|
|
+}
|
|
|
+
|
|
|
+//SimilarText Calculate the similarity between two strings
|
|
|
+func SimilarText(first, second string, percent *float64) int {
|
|
|
+ var similarText func(string, string, int, int) int
|
|
|
+ similarText = func(str1, str2 string, len1, len2 int) int {
|
|
|
+ var sum, max int
|
|
|
+ pos1, pos2 := 0, 0
|
|
|
+
|
|
|
+ // Find the longest segment of the same section in two strings
|
|
|
+ for i := 0; i < len1; i++ {
|
|
|
+ for j := 0; j < len2; j++ {
|
|
|
+ for l := 0; (i+l < len1) && (j+l < len2) && (str1[i+l] == str2[j+l]); l++ {
|
|
|
+ if l+1 > max {
|
|
|
+ max = l + 1
|
|
|
+ pos1 = i
|
|
|
+ pos2 = j
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if sum = max; sum > 0 {
|
|
|
+ if pos1 > 0 && pos2 > 0 {
|
|
|
+ sum += similarText(str1, str2, pos1, pos2)
|
|
|
+ }
|
|
|
+ if (pos1+max < len1) && (pos2+max < len2) {
|
|
|
+ s1 := []byte(str1)
|
|
|
+ s2 := []byte(str2)
|
|
|
+ sum += similarText(string(s1[pos1+max:]), string(s2[pos2+max:]), len1-pos1-max, len2-pos2-max)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return sum
|
|
|
+ }
|
|
|
+ l1, l2 := len(first), len(second)
|
|
|
+ if l1+l2 == 0 {
|
|
|
+ return 0
|
|
|
+ }
|
|
|
+ sim := similarText(first, second, l1, l2)
|
|
|
+ if percent != nil {
|
|
|
+ *percent = float64(sim*200) / float64(l1+l2)
|
|
|
+ }
|
|
|
+ return sim
|
|
|
+}
|
|
|
+
|
|
|
+//IP2long Converts a string containing an (IPv4) Internet Protocol dotted address into a long integer
|
|
|
+func IP2long(ipAddress string) uint32 {
|
|
|
+ ip := net.ParseIP(ipAddress)
|
|
|
+ if ip == nil {
|
|
|
+ return 0
|
|
|
+ }
|
|
|
+ return binary.BigEndian.Uint32(ip.To4())
|
|
|
+}
|
|
|
+
|
|
|
+//Long2IP Converts an long integer address into a string in (IPv4) Internet standard dotted format
|
|
|
+func Long2IP(properAddress uint32) string {
|
|
|
+ ipByte := make([]byte, 4)
|
|
|
+ binary.BigEndian.PutUint32(ipByte, properAddress)
|
|
|
+ ip := net.IP(ipByte)
|
|
|
+ return ip.String()
|
|
|
+}
|