├── LICENSE ├── README.md ├── compress └── compress.go ├── convert └── convert.go ├── datetime ├── date.go └── time.go ├── dict └── map.go ├── encrypt ├── ecb.go └── encrypt.go ├── go.mod ├── if.go ├── sli └── slice.go ├── str └── string.go ├── sys └── file.go ├── type.go ├── utils.go └── utils_test.go /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2019, Microlife 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | utils 2 | ===== 3 | Utils is a go language development toolkit that mainly includes functions such as string, slice, map, time, type judgment, type conversion, and data compression. 4 | 5 | 6 | ### Installing utils 7 | go get github.com/kirinlabs/utils 8 | 9 | ### How to use utils? 10 | 11 | 12 | ## Public 13 | 14 | ```go 15 | import "github.com/kirinlabs/utils" 16 | 17 | utils.Empty(arg interface{}) bool 18 | utils.Export(arg interface{}) string 19 | utils.Json(arg interface{}) string 20 | utils.Decode(s string) error 21 | utils.Unmarshal(s string, args ...interface{}) interface{} 22 | 23 | utils.Type(arg interface{}) string 24 | utils.IsInt(arg interface{}) bool 25 | utils.IsInt64(arg interface{}) bool 26 | utils.IsFloat64(arg interface{}) bool 27 | utils.IsString(arg interface{}) bool 28 | utils.IsTime(arg interface{}) bool 29 | utils.IsBool(arg interface{}) bool 30 | utils.IsSlice(arg interface{}) bool 31 | utils.If(c bool).Then(v interface{}).Else(v interface{}).String() string 32 | utils.If(c bool).Then(v interface{}).Else(v interface{}).Int() int64 error 33 | utils.If(c bool).Then(v interface{}).Else(v interface{}).Float() float64 error 34 | 35 | ``` 36 | 37 | ## String 38 | 39 | ```go 40 | import "github.com/kirinlabs/utils/str" 41 | 42 | s := "hello github" 43 | str.Before(s, "github") 44 | str.BeforeLast(s, "github") 45 | str.After(s, "git") 46 | str.AfterLast(s, "git") 47 | str.StartsWith(s, "hel") 48 | str.EndsWitdh(s, "b") 49 | str.RuneIndex(s,"github") 50 | str.Substr(s, 2, 3) 51 | str.Char(s) 52 | str.Escape(s) 53 | str.Contians(s, "hub") 54 | str.StartsWith(s, "hel") 55 | str.EndsWitdh(s, "b") 56 | str.String(i interface{}) 57 | str.Length(s) 58 | str.Ufirst(s) 59 | 60 | ``` 61 | 62 | ## Slice 63 | 64 | ```go 65 | import "github.com/kirinlabs/utils/sli" 66 | 67 | sli.InSlice(v interface{}, s interface{}) bool 68 | sli.InInterface(v interface{}, sl []interface{}) bool 69 | sli.Slice(iface interface{}) ([]interface{}, error) 70 | sli.Unique(list *[]string) []string 71 | sli.UniqueInt(list *[]int) []int 72 | sli.UniqueInt64(list *[]int64) []int64 73 | sli.Chunk(slice []interface{}, size int) (chunk [][]interface{}) 74 | sli.Range(start, end, step int64) (intslice []int64) 75 | sli.Pad(slice []interface{}, size int, val interface{}) []interface{} 76 | sli.Shuffle(slice []interface{}) []interface{} 77 | sli.Diff(slice1, slice2 []string) (diffslice []string) 78 | sli.Intersect(slice1, slice2 []string) (interSlice []string) 79 | sli.Reverse(list *[]string) []string 80 | sli.ReverseInt(list *[]int) []int 81 | sli.ReverseInt64(list *[]int64) []int64 82 | sli.ReverseFloat(list *[]float64) []float64 83 | sli.Rand(a []string) (b string) 84 | sli.RandInt(a []int) (b int) 85 | sli.RandInt64(a []int64) (b int64) 86 | sli.Sum(i []int64) (s int64) 87 | sli.Range(start, end, step int64) (intslice []int64) 88 | sli.JoinInt(s []int,sep ...string) string 89 | sli.SplitInt(str string, sep ...string) ([]int, error) 90 | 91 | ``` 92 | 93 | ## Convert 94 | 95 | ```go 96 | import "github.com/kirinlabs/utils/convert" 97 | 98 | convert.Int2Bytes(v interface{}) []byte 99 | convert.Int(v interface{}) (int64, error) 100 | convert.Float(v interface{}) (float64, error) 101 | convert.Bool(bs []byte) (bool, error) 102 | convert.Bytes(buf []byte, val reflect.Value) (b []byte, ok bool) 103 | convert.String(iface interface{}) string 104 | convert.Kind(vv reflect.Value, tp reflect.Type) (interface{}, error) 105 | 106 | ``` 107 | 108 | 109 | ## Datetime 110 | 111 | ```go 112 | import "github.com/kirinlabs/utils/datetime" 113 | 114 | datetime.Gmtime() string 115 | datetime.Localtime() string 116 | datetime.Strtotime(s string, args ...string) (time.Time, error) 117 | datetime.String(format ...string) string 118 | datetime.Year(t ...time.Time) int 119 | datetime.Month(t ...time.Time) int 120 | datetime.Day(t ...time.Time) int 121 | datetime.YearDay(t ...time.Time) int 122 | datetime.Hour(t ...time.Time) int 123 | datetime.Minute(t ...time.Time) int 124 | datetime.Second(t ...time.Time) int 125 | datetime.Millisecond() int64 126 | datetime.Microsecond() int64 127 | datetime.Nanosecond() int64 128 | datetime.Timestamp(args ...string) int64 129 | 130 | ``` 131 | 132 | ## Encrypt 133 | 134 | ```go 135 | import "github.com/kirinlabs/utils/encrypt" 136 | 137 | encrypt.Md5(s string) string 138 | encrypt.Sha1(s string) string 139 | encrypt.Sha256(s string) string 140 | encrypt.Sha512(s string) string 141 | encrypt.Base64Encode(s string) string 142 | encrypt.Base64Decode(s string) string 143 | 144 | AES/ECB 145 | ae := encrypt.NewEcb([]byte("0123456789ABCDEF")) 146 | encrypted, err := ae.Encrypt(src []byte) 147 | decrypted, err := ae.Decrypt(encrypted []byte) 148 | 149 | ``` 150 | 151 | ## sys 152 | 153 | ```go 154 | import "github.com/kirinlabs/utils/sys" 155 | 156 | sys.RealPath(f string) string 157 | sys.IsExists(path string) bool 158 | sys.IsFile(f string) bool 159 | sys.IsDir(p string) bool 160 | 161 | ``` -------------------------------------------------------------------------------- /compress/compress.go: -------------------------------------------------------------------------------- 1 | package compress 2 | 3 | import ( 4 | "bytes" 5 | "compress/zlib" 6 | "io" 7 | ) 8 | 9 | func ZlibCompress(src []byte) []byte { 10 | var in bytes.Buffer 11 | w := zlib.NewWriter(&in) 12 | w.Write(src) 13 | w.Close() 14 | return in.Bytes() 15 | } 16 | 17 | func ZlibUncompress(src []byte) []byte { 18 | var out bytes.Buffer 19 | b := bytes.NewReader(src) 20 | r, _ := zlib.NewReader(b) 21 | io.Copy(&out, r) 22 | return out.Bytes() 23 | } -------------------------------------------------------------------------------- /convert/convert.go: -------------------------------------------------------------------------------- 1 | package convert 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | "encoding/json" 7 | "fmt" 8 | "reflect" 9 | "strconv" 10 | ) 11 | 12 | func Atoi(v string) int { 13 | n, err := strconv.Atoi(v) 14 | if err != nil { 15 | return 0 16 | } 17 | return n 18 | } 19 | 20 | func Int(v interface{}) (int64, error) { 21 | switch v.(type) { 22 | case int: 23 | return int64(v.(int)), nil 24 | case int8: 25 | return int64(v.(int8)), nil 26 | case int16: 27 | return int64(v.(int16)), nil 28 | case int32: 29 | return int64(v.(int32)), nil 30 | case int64: 31 | return v.(int64), nil 32 | case float32: 33 | return int64(v.(float32)), nil 34 | case float64: 35 | return int64(v.(float64)), nil 36 | case []byte: 37 | i, err := strconv.ParseInt(string(v.([]byte)), 10, 64) 38 | if err != nil { 39 | return 0, err 40 | } 41 | return i, nil 42 | case string: 43 | i, err := strconv.ParseInt(v.(string), 10, 64) 44 | if err != nil { 45 | return 0, err 46 | } 47 | return i, nil 48 | } 49 | return 0, fmt.Errorf("Unsupported type: %v", v) 50 | } 51 | 52 | func Float(v interface{}) (float64, error) { 53 | switch v.(type) { 54 | case float32: 55 | return float64(v.(float32)), nil 56 | case float64: 57 | return v.(float64), nil 58 | case string: 59 | i, err := strconv.ParseFloat(v.(string), 64) 60 | if err != nil { 61 | return 0, err 62 | } 63 | return i, nil 64 | case []byte: 65 | i, err := strconv.ParseFloat(string(v.([]byte)), 64) 66 | if err != nil { 67 | return 0, err 68 | } 69 | return i, nil 70 | } 71 | return 0, fmt.Errorf("Unsupported type: %v", v) 72 | } 73 | 74 | func Bool(bs []byte) (bool, error) { 75 | if len(bs) == 0 { 76 | return false, nil 77 | } 78 | if bs[0] == 0x00 { 79 | return false, nil 80 | } else if bs[0] == 0x01 { 81 | return true, nil 82 | } 83 | return strconv.ParseBool(string(bs)) 84 | } 85 | 86 | func Int2Bytes(v interface{}) []byte { 87 | b := bytes.NewBuffer([]byte{}) 88 | switch v.(type) { 89 | case int: 90 | bit := 32 << (^uint(0) >> 63) 91 | if bit == 64 { 92 | binary.Write(b, binary.BigEndian, int64(v.(int))) 93 | } else { 94 | binary.Write(b, binary.BigEndian, int32(v.(int))) 95 | } 96 | case int8: 97 | binary.Write(b, binary.BigEndian, v.(int8)) 98 | case int16: 99 | binary.Write(b, binary.BigEndian, v.(int16)) 100 | case int32: 101 | binary.Write(b, binary.BigEndian, v.(int32)) 102 | case int64: 103 | binary.Write(b, binary.BigEndian, v.(int64)) 104 | case uint: 105 | bit := 32 << (^uint(0) >> 63) 106 | if bit == 64 { 107 | binary.Write(b, binary.BigEndian, uint64(v.(uint))) 108 | } else { 109 | binary.Write(b, binary.BigEndian, uint32(v.(uint))) 110 | } 111 | case uint8: 112 | binary.Write(b, binary.BigEndian, v.(uint8)) 113 | case uint16: 114 | binary.Write(b, binary.BigEndian, v.(uint16)) 115 | case uint32: 116 | binary.Write(b, binary.BigEndian, v.(uint32)) 117 | case uint64: 118 | binary.Write(b, binary.BigEndian, v.(uint64)) 119 | default: 120 | return nil 121 | } 122 | return b.Bytes() 123 | } 124 | 125 | func Bytes(buf []byte, val reflect.Value) (b []byte, ok bool) { 126 | switch val.Kind() { 127 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 128 | return strconv.AppendInt(buf, val.Int(), 10), true 129 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 130 | return strconv.AppendUint(buf, val.Uint(), 10), true 131 | case reflect.Float32: 132 | return strconv.AppendFloat(buf, val.Float(), 'f', -1, 32), true 133 | case reflect.Float64: 134 | return strconv.AppendFloat(buf, val.Float(), 'f', -1, 64), true 135 | case reflect.Bool: 136 | return strconv.AppendBool(buf, val.Bool()), true 137 | case reflect.String: 138 | s := val.String() 139 | return append(buf, s...), true 140 | } 141 | return 142 | } 143 | 144 | func String(iface interface{}) string { 145 | switch val := iface.(type) { 146 | case []byte: 147 | return string(val) 148 | case string: 149 | return val 150 | } 151 | v := reflect.ValueOf(iface) 152 | switch v.Kind() { 153 | case reflect.Invalid: 154 | return "" 155 | case reflect.Bool: 156 | return strconv.FormatBool(v.Bool()) 157 | case reflect.String: 158 | return v.String() 159 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 160 | return strconv.FormatInt(v.Int(), 10) 161 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 162 | return strconv.FormatUint(v.Uint(), 10) 163 | case reflect.Float64: 164 | return strconv.FormatFloat(v.Float(), 'f', -1, 64) 165 | case reflect.Float32: 166 | return strconv.FormatFloat(v.Float(), 'f', -1, 32) 167 | case reflect.Ptr, reflect.Struct, reflect.Map: 168 | b, err := json.Marshal(v.Interface()) 169 | if err != nil { 170 | return "" 171 | } 172 | return string(b) 173 | } 174 | return fmt.Sprintf("%v", iface) 175 | } 176 | 177 | func Kind(vv reflect.Value, tp reflect.Type) (interface{}, error) { 178 | switch tp.Kind() { 179 | case reflect.Int64: 180 | return vv.Int(), nil 181 | case reflect.Int: 182 | return int(vv.Int()), nil 183 | case reflect.Int32: 184 | return int32(vv.Int()), nil 185 | case reflect.Int16: 186 | return int16(vv.Int()), nil 187 | case reflect.Int8: 188 | return int8(vv.Int()), nil 189 | case reflect.Uint64: 190 | return vv.Uint(), nil 191 | case reflect.Uint: 192 | return uint(vv.Uint()), nil 193 | case reflect.Uint32: 194 | return uint32(vv.Uint()), nil 195 | case reflect.Uint16: 196 | return uint16(vv.Uint()), nil 197 | case reflect.Uint8: 198 | return uint8(vv.Uint()), nil 199 | case reflect.String: 200 | return vv.String(), nil 201 | case reflect.Slice: 202 | if tp.Elem().Kind() == reflect.Uint8 { 203 | v, err := strconv.ParseInt(string(vv.Interface().([]byte)), 10, 64) 204 | if err != nil { 205 | return nil, err 206 | } 207 | return v, nil 208 | } 209 | 210 | } 211 | return nil, fmt.Errorf("Unsupported primary key type: %v, %v", tp, vv) 212 | } 213 | -------------------------------------------------------------------------------- /datetime/date.go: -------------------------------------------------------------------------------- 1 | package datetime 2 | 3 | import "time" 4 | 5 | func Year(t ...time.Time) int { 6 | tmp := time.Now() 7 | if len(t) > 0 { 8 | tmp = t[0] 9 | } 10 | return tmp.Year() 11 | } 12 | 13 | func Month(t ...time.Time) int { 14 | tmp := time.Now() 15 | if len(t) > 0 { 16 | tmp = t[0] 17 | } 18 | return int(tmp.Month()) 19 | } 20 | 21 | func Day(t ...time.Time) int { 22 | tmp := time.Now() 23 | if len(t) > 0 { 24 | tmp = t[0] 25 | } 26 | return tmp.Day() 27 | } 28 | 29 | func YearDay(t ...time.Time) int { 30 | tmp := time.Now() 31 | if len(t) > 0 { 32 | tmp = t[0] 33 | } 34 | return tmp.YearDay() 35 | } -------------------------------------------------------------------------------- /datetime/time.go: -------------------------------------------------------------------------------- 1 | package datetime 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "log" 7 | "reflect" 8 | "strings" 9 | "time" 10 | ) 11 | 12 | // timestamp 13 | func String(f ...string) string { 14 | format := "2006-01-02 15:04:05" 15 | if len(f) > 0 { 16 | format = f[0] 17 | } 18 | return time.Now().Format(format) 19 | } 20 | 21 | func Hour(t ...time.Time) int { 22 | tmp := time.Now() 23 | if len(t) > 0 { 24 | tmp = t[0] 25 | } 26 | return tmp.Hour() 27 | } 28 | 29 | func Minute(t ...time.Time) int { 30 | tmp := time.Now() 31 | if len(t) > 0 { 32 | tmp = t[0] 33 | } 34 | return tmp.Minute() 35 | } 36 | 37 | func Second(t ...time.Time) int { 38 | tmp := time.Now() 39 | if len(t) > 0 { 40 | tmp = t[0] 41 | } 42 | return tmp.Second() 43 | } 44 | 45 | // String to timestamp 46 | func Timestamp(args ...string) int64 { 47 | var timestamp int64 = 0 48 | l := len(args) 49 | if l == 0 { 50 | timestamp = time.Now().Unix() 51 | } 52 | if l > 0 { 53 | if reflect.TypeOf(args[0]).String() == "string" { 54 | t, err := Strtotime(string(args[0]), "2006-01-02 15:04:05") 55 | if err != nil { 56 | log.Println("datetime.Timestamp error:", err) 57 | return -1 58 | } 59 | timestamp = t.Unix() 60 | } 61 | } 62 | return timestamp 63 | } 64 | 65 | func Millisecond() int64 { 66 | return time.Now().UnixNano() / 1e6 67 | } 68 | 69 | func Microsecond() int64 { 70 | return time.Now().UnixNano() / 1e3 71 | } 72 | 73 | func Nanosecond() int64 { 74 | return time.Now().UnixNano() 75 | } 76 | 77 | // GMT TIME 78 | func Gmtime() string { 79 | now := time.Now() 80 | year, mon, day := now.UTC().Date() 81 | hour, min, sec := now.UTC().Clock() 82 | zone, _ := now.UTC().Zone() 83 | return fmt.Sprintf("%d-%d-%d %02d:%02d:%02d %s", year, mon, day, hour, min, sec, zone) 84 | } 85 | 86 | func Localtime() string { 87 | now := time.Now().Local() 88 | year, mon, day := now.Date() 89 | hour, min, sec := now.Clock() 90 | zone, _ := now.Zone() 91 | return fmt.Sprintf("%d-%d-%d %02d:%02d:%02d %s", year, mon, day, hour, min, sec, zone) 92 | } 93 | 94 | // String to time.Time 95 | func Strtotime(s string, args ...string) (time.Time, error) { 96 | format := "2006-01-02 15:04:05" 97 | if len(args) > 0 { 98 | format = strings.Trim(args[0], " ") 99 | } 100 | if len(s) != len(format) { 101 | return time.Now(), errors.New("String to time: parameter format error") 102 | } 103 | return time.ParseInLocation(format, s, time.Local) 104 | } 105 | 106 | func charToCode(layout string) string { 107 | characters := []string{ 108 | "y", "06", 109 | "m", "1", 110 | "d", "2", 111 | "Y", "2006", 112 | "M", "01", 113 | "D", "02", 114 | 115 | "h", "03", 116 | "H", "15", 117 | "i", "4", 118 | "s", "5", 119 | "I", "04", 120 | "S", "05", 121 | 122 | "t", "pm", 123 | "T", "PM", 124 | } 125 | replacer := strings.NewReplacer(characters...) 126 | return replacer.Replace(layout) 127 | } 128 | -------------------------------------------------------------------------------- /dict/map.go: -------------------------------------------------------------------------------- 1 | package dict 2 | 3 | func Delete(src map[string]interface{}, args ...string) { 4 | for _, v := range args { 5 | delete(src, v) 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /encrypt/ecb.go: -------------------------------------------------------------------------------- 1 | package encrypt 2 | 3 | import ( 4 | "bytes" 5 | "crypto/aes" 6 | "errors" 7 | ) 8 | 9 | type AesECB struct { 10 | key []byte 11 | blockSize int 12 | } 13 | 14 | func NewEcb(key []byte, blocks ...int) *AesECB { 15 | size := aes.BlockSize 16 | if len(blocks) > 0 { 17 | size = blocks[0] 18 | } 19 | return &AesECB{ 20 | key: key, 21 | blockSize: size, 22 | } 23 | } 24 | 25 | // When isPad is false, use Nopadding mode 26 | func (a *AesECB) Encrypt(src []byte, isPad ...bool) ([]byte, error) { 27 | block, err := aes.NewCipher(a.key) 28 | if err != nil { 29 | return nil, err 30 | } 31 | 32 | if len(src) == 0 { 33 | return nil, errors.New("content is empty") 34 | } 35 | 36 | if len(isPad) > 0 && isPad[0] == false { 37 | src = a.noPadding(src) 38 | } else { 39 | src = a.padding(src) 40 | } 41 | 42 | buf := make([]byte, a.blockSize) 43 | encrypted := make([]byte, 0) 44 | for i := 0; i < len(src); i += a.blockSize { 45 | block.Encrypt(buf, src[i:i+a.blockSize]) 46 | encrypted = append(encrypted, buf...) 47 | } 48 | return encrypted, nil 49 | } 50 | 51 | // When isPad is false, use Nopadding mode 52 | func (a *AesECB) Decrypt(src []byte, isPad ...bool) ([]byte, error) { 53 | block, err := aes.NewCipher(a.key) 54 | if err != nil { 55 | return nil, err 56 | } 57 | if len(src) == 0 { 58 | return nil, errors.New("content is empty") 59 | } 60 | buf := make([]byte, a.blockSize) 61 | decrypted := make([]byte, 0) 62 | for i := 0; i < len(src); i += a.blockSize { 63 | block.Decrypt(buf, src[i:i+a.blockSize]) 64 | decrypted = append(decrypted, buf...) 65 | } 66 | 67 | if len(isPad) > 0 && isPad[0] == false { 68 | decrypted = a.unNoPadding(decrypted) 69 | } else { 70 | decrypted = a.unPadding(decrypted) 71 | } 72 | 73 | return decrypted, nil 74 | } 75 | 76 | // Nopadding mode 77 | func (a *AesECB) noPadding(src []byte) []byte { 78 | count := a.blockSize - len(src)%a.blockSize 79 | if len(src)%a.blockSize == 0 { 80 | return src 81 | } else { 82 | return append(src, bytes.Repeat([]byte{byte(0)}, count)...) 83 | } 84 | } 85 | 86 | // Nopadding mode 87 | func (a *AesECB) unNoPadding(src []byte) []byte { 88 | for i := len(src) - 1; ; i-- { 89 | if src[i] != 0 { 90 | return src[:i+1] 91 | } 92 | } 93 | return nil 94 | } 95 | 96 | // Padding Mode 97 | func (a *AesECB) padding(src []byte) []byte { 98 | count := a.blockSize - len(src)%a.blockSize 99 | padding := bytes.Repeat([]byte{byte(0)}, count) 100 | padding[count-1] = byte(count) 101 | return append(src, padding...) 102 | } 103 | 104 | // Padding Mode 105 | func (a *AesECB) unPadding(src []byte) []byte { 106 | l := len(src) 107 | p := int(src[l-1]) 108 | return src[:l-p] 109 | } 110 | -------------------------------------------------------------------------------- /encrypt/encrypt.go: -------------------------------------------------------------------------------- 1 | package encrypt 2 | 3 | import ( 4 | "crypto/md5" 5 | "crypto/sha1" 6 | "crypto/sha256" 7 | "crypto/sha512" 8 | "encoding/base64" 9 | "encoding/hex" 10 | "fmt" 11 | ) 12 | 13 | func Md5(s string) (result string) { 14 | m := md5.New() 15 | m.Write([]byte(s)) 16 | b := m.Sum(nil) 17 | result = hex.EncodeToString(b) 18 | return 19 | } 20 | 21 | func Sha1(s string) (result string) { 22 | sha := sha1.New() 23 | sha.Write([]byte(s)) 24 | b := sha.Sum(nil) 25 | result = fmt.Sprintf("%x", b) 26 | return 27 | } 28 | 29 | func Sha256(s string) (result string) { 30 | sha := sha256.New() 31 | sha.Write([]byte(s)) 32 | b := sha.Sum(nil) 33 | result = fmt.Sprintf("%x", b) 34 | return 35 | } 36 | 37 | func Sha512(s string) (result string) { 38 | sha := sha512.New() 39 | sha.Write([]byte(s)) 40 | b := sha.Sum(nil) 41 | result = fmt.Sprintf("%x", b) 42 | return 43 | } 44 | 45 | func Base64Encode(s string) (result string) { 46 | result = base64.StdEncoding.EncodeToString([]byte(s)) 47 | return 48 | } 49 | 50 | func Base64Decode(s string) (string, error) { 51 | result, err := base64.StdEncoding.DecodeString(s) 52 | if err != nil { 53 | return "nil", err 54 | } 55 | return string(result), nil 56 | } 57 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/kirinlabs/utils 2 | 3 | go 1.11 4 | -------------------------------------------------------------------------------- /if.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Kirinlabs. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package utils 6 | 7 | import ( 8 | "fmt" 9 | "strconv" 10 | ) 11 | 12 | type ifThen struct { 13 | c bool 14 | t interface{} 15 | e interface{} 16 | v interface{} 17 | } 18 | 19 | func (i *ifThen) If(c bool) *ifThen { 20 | i.c = c 21 | return i 22 | } 23 | 24 | func (i *ifThen) Then(v interface{}) *ifThen { 25 | i.t = v 26 | return i 27 | } 28 | 29 | func (i *ifThen) Else(v interface{}) *ifThen { 30 | i.e = v 31 | return i 32 | } 33 | 34 | func (i *ifThen) String() string { 35 | if i.c { 36 | i.v = i.t 37 | } else { 38 | i.v = i.e 39 | } 40 | return fmt.Sprintf("%v", i.v) 41 | } 42 | 43 | func (i *ifThen) Int() (int64, error) { 44 | if i.c { 45 | i.v = i.t 46 | } else { 47 | i.v = i.e 48 | } 49 | switch i.v.(type) { 50 | case int64: 51 | return i.v.(int64), nil 52 | case int32: 53 | return int64(i.v.(int32)), nil 54 | case int: 55 | return int64(i.v.(int)), nil 56 | case int8: 57 | return int64(i.v.(int8)), nil 58 | case int16: 59 | return int64(i.v.(int16)), nil 60 | case float32: 61 | return int64(i.v.(float32)), nil 62 | case float64: 63 | return int64(i.v.(float64)), nil 64 | case []byte: 65 | i, err := strconv.ParseInt(string(i.v.([]byte)), 10, 64) 66 | if err != nil { 67 | return 0, err 68 | } 69 | return i, nil 70 | case string: 71 | i, err := strconv.ParseInt(i.v.(string), 10, 64) 72 | if err != nil { 73 | return 0, err 74 | } 75 | return i, nil 76 | } 77 | return 0, fmt.Errorf("Unsupported type: %v", i.v) 78 | } 79 | 80 | func (i *ifThen) Float() (float64, error) { 81 | if i.c { 82 | i.v = i.t 83 | } else { 84 | i.v = i.e 85 | } 86 | switch i.v.(type) { 87 | case float32: 88 | return float64(i.v.(float32)), nil 89 | case float64: 90 | return i.v.(float64), nil 91 | case string: 92 | i, err := strconv.ParseFloat(i.v.(string), 64) 93 | if err != nil { 94 | return 0, err 95 | } 96 | return i, nil 97 | case []byte: 98 | i, err := strconv.ParseFloat(string(i.v.([]byte)), 64) 99 | if err != nil { 100 | return 0, err 101 | } 102 | return i, nil 103 | } 104 | return 0, fmt.Errorf("Unsupported type: %v", i.v) 105 | } 106 | -------------------------------------------------------------------------------- /sli/slice.go: -------------------------------------------------------------------------------- 1 | package sli 2 | 3 | import ( 4 | "errors" 5 | "log" 6 | "math/rand" 7 | "reflect" 8 | "strconv" 9 | "strings" 10 | "time" 11 | 12 | "github.com/kirinlabs/utils/str" 13 | ) 14 | 15 | func JoinInt(s []int, sep ...string) string { 16 | l := "," 17 | if len(sep) > 0 { 18 | l = sep[0] 19 | } 20 | str := make([]string, 0) 21 | for _, v := range s { 22 | str = append(str, strconv.FormatInt(int64(v), 10)) 23 | } 24 | return strings.Join(str, l) 25 | } 26 | 27 | func SplitInt(str string, sep ...string) ([]int, error) { 28 | l := "," 29 | if len(sep) > 0 { 30 | l = sep[0] 31 | } 32 | i := make([]int, 0) 33 | s := strings.Split(str, l) 34 | for _, v := range s { 35 | d, err := strconv.Atoi(v) 36 | if err != nil { 37 | return []int{}, err 38 | } 39 | i = append(i, d) 40 | } 41 | return i, nil 42 | } 43 | 44 | func InSlice(v interface{}, s interface{}) bool { 45 | val := reflect.Indirect(reflect.ValueOf(v)) 46 | if val.Kind() == reflect.Slice { 47 | log.Println("Warning: first parameter cannot be a slice, Function: InSlice") 48 | return false 49 | } 50 | 51 | sv := reflect.Indirect(reflect.ValueOf(s)) 52 | if sv.Kind() != reflect.Slice { 53 | log.Println("Warning: second parameter needs a slice, Function: InSlice") 54 | return false 55 | } 56 | 57 | st := reflect.TypeOf(s).Elem().String() 58 | vt := reflect.TypeOf(v).String() 59 | if st != vt { 60 | log.Println("Warning: two parameters are not the same type, Function: InSlice") 61 | return false 62 | } 63 | 64 | switch vt { 65 | case "string": 66 | for _, vv := range s.([]string) { 67 | if vv == v { 68 | return true 69 | } 70 | } 71 | case "int": 72 | for _, vv := range s.([]int) { 73 | if vv == v { 74 | return true 75 | } 76 | } 77 | case "int64": 78 | for _, vv := range s.([]int64) { 79 | if vv == v { 80 | return true 81 | } 82 | } 83 | case "float64": 84 | for _, vv := range s.([]float64) { 85 | if vv == v { 86 | return true 87 | } 88 | } 89 | default: 90 | log.Println("Warning: this type is not supported, Function: InSlice") 91 | return false 92 | } 93 | 94 | return false 95 | } 96 | 97 | func InInterface(v interface{}, sl []interface{}) bool { 98 | for _, vv := range sl { 99 | if vv == v { 100 | return true 101 | } 102 | } 103 | return false 104 | } 105 | 106 | func Slice(iface interface{}) ([]interface{}, error) { 107 | d := make([]interface{}, 0) 108 | v := reflect.Indirect(reflect.ValueOf(iface)) 109 | if v.Kind() != reflect.Slice { 110 | return []interface{}{}, errors.New("Needs a slice") 111 | } 112 | t := reflect.TypeOf(iface).Elem().String() 113 | switch t { 114 | case "string": 115 | for _, v := range iface.([]string) { 116 | if strings.Trim(str.String(v), " ") == "" { 117 | continue 118 | } 119 | d = append(d, v) 120 | } 121 | case "int": 122 | for _, v := range iface.([]int) { 123 | d = append(d, v) 124 | } 125 | case "int64": 126 | for _, v := range iface.([]int64) { 127 | d = append(d, v) 128 | } 129 | case "float64": 130 | for _, v := range iface.([]float64) { 131 | d = append(d, v) 132 | } 133 | default: 134 | return d, errors.New("this type is not supported") 135 | } 136 | return d, nil 137 | } 138 | 139 | func Unique(list *[]string) []string { 140 | r := make([]string, 0) 141 | temp := map[string]byte{} 142 | for _, v := range *list { 143 | l := len(temp) 144 | temp[v] = 0 145 | if len(temp) != l { 146 | r = append(r, v) 147 | } 148 | } 149 | return r 150 | } 151 | 152 | func UniqueInt(list *[]int) []int { 153 | r := make([]int, 0) 154 | temp := map[int]byte{} 155 | for _, v := range *list { 156 | l := len(temp) 157 | temp[v] = 0 158 | if len(temp) != l { 159 | r = append(r, v) 160 | } 161 | } 162 | return r 163 | } 164 | 165 | /*func UniqueInt(list *[]int) []int { 166 | var r []int = []int{} 167 | for _, i := range *list { 168 | if len(r) == 0 { 169 | r = append(r, i) 170 | } else { 171 | for k, v := range r { 172 | if i == v { 173 | break 174 | } 175 | if k == len(r)-1 { 176 | r = append(r, i) 177 | } 178 | } 179 | } 180 | } 181 | return r 182 | }*/ 183 | 184 | func UniqueInt64(list *[]int64) []int64 { 185 | r := make([]int64, 0) 186 | temp := map[int64]byte{} 187 | for _, v := range *list { 188 | l := len(temp) 189 | temp[v] = 0 190 | if len(temp) != l { 191 | r = append(r, v) 192 | } 193 | } 194 | return r 195 | } 196 | 197 | func UniqueIface(list *[]interface{}) []interface{} { 198 | r := make([]interface{}, 0) 199 | temp := map[interface{}]byte{} 200 | for _, v := range *list { 201 | l := len(temp) 202 | temp[v] = 0 203 | if len(temp) != l { 204 | r = append(r, v) 205 | } 206 | } 207 | return r 208 | } 209 | 210 | func UniqueFloat(list *[]float64) []float64 { 211 | r := make([]float64, 0) 212 | temp := map[float64]byte{} 213 | for _, v := range *list { 214 | l := len(temp) 215 | temp[v] = 0 216 | if len(temp) != l { 217 | r = append(r, v) 218 | } 219 | } 220 | return r 221 | } 222 | 223 | func Chunk(slice []interface{}, size int) (chunk [][]interface{}) { 224 | if size <= 0 { 225 | chunk = make([][]interface{}, 0) 226 | return 227 | } 228 | if size >= len(slice) { 229 | chunk = append(chunk, slice) 230 | return 231 | } 232 | end := size 233 | for i := 0; i < len(slice); i += size { 234 | if end > len(slice) { 235 | chunk = append(chunk, slice[i:]) 236 | break 237 | } 238 | chunk = append(chunk, slice[i:end]) 239 | end += size 240 | } 241 | return 242 | } 243 | 244 | func Rand(a []string) (b string) { 245 | r := rand.Intn(len(a)) 246 | b = a[r] 247 | return 248 | } 249 | 250 | func RandInt(a []int) (b int) { 251 | r := rand.Intn(len(a)) 252 | b = a[r] 253 | return 254 | } 255 | 256 | func RandInt64(a []int64) (b int64) { 257 | r := rand.Intn(len(a)) 258 | b = a[r] 259 | return 260 | } 261 | 262 | func RandList(min, max int) []int { 263 | if max < min { 264 | min, max = max, min 265 | } 266 | length := max - min + 1 267 | t := time.Now() 268 | rand.Seed(int64(t.Nanosecond())) 269 | list := rand.Perm(length) 270 | for index := range list { 271 | list[index] += min 272 | } 273 | return list 274 | } 275 | 276 | func Sum(i []int64) (s int64) { 277 | for _, v := range i { 278 | s += v 279 | } 280 | return 281 | } 282 | 283 | func Diff(slice1, slice2 []string) (diffslice []string) { 284 | for _, v := range slice1 { 285 | if !InSlice(v, slice2) { 286 | diffslice = append(diffslice, v) 287 | } 288 | } 289 | return 290 | } 291 | 292 | func DiffInt(slice1, slice2 []int) (diffslice []int) { 293 | for _, v := range slice1 { 294 | if !InSlice(v, slice2) { 295 | diffslice = append(diffslice, v) 296 | } 297 | } 298 | return 299 | } 300 | 301 | func DiffInt64(slice1, slice2 []int64) (diffslice []int64) { 302 | for _, v := range slice1 { 303 | if !InSlice(v, slice2) { 304 | diffslice = append(diffslice, v) 305 | } 306 | } 307 | return 308 | } 309 | 310 | func DiffFloat(slice1, slice2 []float64) (diffslice []float64) { 311 | for _, v := range slice1 { 312 | if !InSlice(v, slice2) { 313 | diffslice = append(diffslice, v) 314 | } 315 | } 316 | return 317 | } 318 | 319 | func Intersect(slice1, slice2 []string) (interSlice []string) { 320 | for _, v := range slice1 { 321 | if InSlice(v, slice2) { 322 | interSlice = append(interSlice, v) 323 | } 324 | } 325 | return 326 | } 327 | 328 | func IntersectInt(slice1, slice2 []int) (interSlice []int) { 329 | for _, v := range slice1 { 330 | if InSlice(v, slice2) { 331 | interSlice = append(interSlice, v) 332 | } 333 | } 334 | return 335 | } 336 | 337 | func IntersectIn64(slice1, slice2 []int64) (interSlice []int64) { 338 | for _, v := range slice1 { 339 | if InSlice(v, slice2) { 340 | interSlice = append(interSlice, v) 341 | } 342 | } 343 | return 344 | } 345 | 346 | func Reverse(s *[]string) []string { 347 | l := len(*s) - 1 348 | m := len(*s) / 2 349 | r := make([]string, len(*s)) 350 | for i := 0; i < l; i++ { 351 | j := l - i 352 | if i == j || i >= m { 353 | break 354 | } 355 | r[i], r[j] = (*s)[j], (*s)[i] 356 | } 357 | return r 358 | } 359 | 360 | func ReverseInt(s *[]int) []int { 361 | l := len(*s) - 1 362 | m := len(*s) / 2 363 | r := make([]int, len(*s)) 364 | for i := 0; i < l; i++ { 365 | j := l - i 366 | if i == j || i >= m { 367 | break 368 | } 369 | r[i], r[j] = (*s)[j], (*s)[i] 370 | } 371 | return r 372 | } 373 | 374 | func ReverseInt64(s *[]int64) []int64 { 375 | l := len(*s) - 1 376 | m := len(*s) / 2 377 | r := make([]int64, len(*s)) 378 | for i := 0; i < l; i++ { 379 | j := l - i 380 | if i == j || i >= m { 381 | break 382 | } 383 | r[i], r[j] = (*s)[j], (*s)[i] 384 | } 385 | return r 386 | } 387 | 388 | func ReverseFloat(s *[]float64) []float64 { 389 | l := len(*s) - 1 390 | m := len(*s) / 2 391 | r := make([]float64, len(*s)) 392 | for i := 0; i < l; i++ { 393 | j := l - i 394 | if i == j || i >= m { 395 | break 396 | } 397 | r[i], r[j] = (*s)[j], (*s)[i] 398 | } 399 | return r 400 | } 401 | 402 | func Range(start, end, step int64) (intslice []int64) { 403 | for i := start; i <= end; i += step { 404 | intslice = append(intslice, i) 405 | } 406 | return 407 | } 408 | 409 | func Pad(slice []interface{}, size int, val interface{}) []interface{} { 410 | if size <= len(slice) { 411 | return slice 412 | } 413 | for i := 0; i < (size - len(slice)); i++ { 414 | slice = append(slice, val) 415 | } 416 | return slice 417 | } 418 | 419 | func Shuffle(slice []interface{}) []interface{} { 420 | for i := 0; i < len(slice); i++ { 421 | a := rand.Intn(len(slice)) 422 | b := rand.Intn(len(slice)) 423 | slice[a], slice[b] = slice[b], slice[a] 424 | } 425 | return slice 426 | } 427 | -------------------------------------------------------------------------------- /str/string.go: -------------------------------------------------------------------------------- 1 | package str 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "reflect" 7 | "strconv" 8 | "strings" 9 | "unicode" 10 | ) 11 | 12 | // Length returns number of characters 13 | func Length(s string) int { 14 | return len([]rune(s)) 15 | } 16 | 17 | // Before returns the string before the first occurrence of the substr string 18 | func Before(s, substr string) string { 19 | if substr == "" { 20 | return s 21 | } 22 | i := strings.Index(s, substr) 23 | if i != -1 { 24 | return s[:i] 25 | } 26 | return s 27 | } 28 | 29 | // BeforeLast returns the string before the last occurrence of the substr string 30 | func BeforeLast(s, substr string) string { 31 | if substr == "" { 32 | return s 33 | } 34 | i := strings.LastIndex(s, substr) 35 | if i != -1 { 36 | return s[:i] 37 | } 38 | return s 39 | } 40 | 41 | // After returns the string after the first occurrence of the substr string 42 | func After(s, substr string) string { 43 | if substr == "" { 44 | return s 45 | } 46 | i := strings.Index(s, substr) 47 | if i != -1 { 48 | i = i + len(substr) 49 | return s[i:] 50 | } 51 | return s 52 | } 53 | 54 | // AfterLast returns the string after the last occurrence of the substr string 55 | func AfterLast(s, substr string) string { 56 | if substr == "" { 57 | return s 58 | } 59 | i := strings.LastIndex(s, substr) 60 | if i != -1 { 61 | i = i + len(substr) 62 | return s[i:] 63 | } 64 | return s 65 | } 66 | 67 | func Index(s, substr string) int { 68 | return strings.Index(s, substr) 69 | } 70 | 71 | func RuneIndex(s, substr string) int { 72 | p := strings.Index(s, substr) 73 | if p == -1 || p == 0 { 74 | return p 75 | } 76 | pos := 0 77 | totalSize := 0 78 | reader := strings.NewReader(s) 79 | for _, size, err := reader.ReadRune(); err == nil; _, size, err = reader.ReadRune() { 80 | pos++ 81 | totalSize += size 82 | 83 | if totalSize == p { 84 | return pos 85 | } 86 | } 87 | return pos 88 | } 89 | 90 | func Contians(s, substr string) bool { 91 | return strings.Contains(s, substr) 92 | } 93 | 94 | func StartsWith(s, substr string) bool { 95 | if substr != "" && Substr(s, 0, len([]rune(substr))) == substr { 96 | return true 97 | } 98 | return false 99 | } 100 | 101 | func EndsWith(s, substr string) bool { 102 | if Substr(s, -len([]rune(substr)), len(s)) == substr { 103 | return true 104 | } 105 | return false 106 | } 107 | 108 | // Substr returns a string of length length from the start position 109 | func Substr(s string, start int, strlength ...int) string { 110 | charlist := []rune(s) 111 | l := len(charlist) 112 | length := 0 113 | end := 0 114 | 115 | if len(strlength) == 0 { 116 | length = l 117 | } else { 118 | length = strlength[0] 119 | } 120 | 121 | if start < 0 { 122 | start = l + start 123 | } 124 | end = start + length 125 | 126 | if start > end { 127 | start, end = end, start 128 | } 129 | 130 | if start < 0 { 131 | start = 0 132 | } 133 | 134 | if start > l { 135 | start = l 136 | } 137 | 138 | if end < 0 { 139 | end = 0 140 | } 141 | 142 | if end > l { 143 | end = l 144 | } 145 | 146 | return string(charlist[start:end]) 147 | } 148 | 149 | func SubByte(str string, length int) string { 150 | bs := []byte(str)[:length] 151 | bl := 0 152 | for i := len(bs) - 1; i >= 0; i-- { 153 | switch { 154 | case bs[i] >= 0 && bs[i] <= 127: 155 | return string(bs[:i+1]) 156 | case bs[i] >= 128 && bs[i] <= 191: 157 | bl++ 158 | case bs[i] >= 192 && bs[i] <= 253: 159 | cl := 0 160 | switch { 161 | case bs[i]&252 == 252: 162 | cl = 6 163 | case bs[i]&248 == 248: 164 | cl = 5 165 | case bs[i]&240 == 240: 166 | cl = 4 167 | case bs[i]&224 == 224: 168 | cl = 3 169 | default: 170 | cl = 2 171 | } 172 | if bl+1 == cl { 173 | return string(bs[:i+cl]) 174 | } 175 | return string(bs[:i]) 176 | } 177 | } 178 | return "" 179 | } 180 | 181 | // Char returns a char slice 182 | func Char(str string) []string { 183 | c := make([]string, 0) 184 | for _, v := range str { 185 | c = append(c, string(v)) 186 | } 187 | return c 188 | } 189 | 190 | func Escape(s string) string { 191 | str := strconv.Quote(s) 192 | str = strings.Replace(str, "'", "\\'", -1) 193 | strlist := []rune(str) 194 | l := len(strlist) 195 | return Substr(str, 1, l-2) 196 | } 197 | 198 | func Ufirst(s string) string { 199 | r := []rune(s) 200 | if len(s) > 0 && unicode.IsLetter(r[0]) && unicode.IsLower(r[0]) { 201 | r[0] -= 32 202 | return string(r) 203 | } 204 | return s 205 | } 206 | 207 | // String returns a string of any type 208 | func String(iface interface{}) string { 209 | switch val := iface.(type) { 210 | case []byte: 211 | return string(val) 212 | case string: 213 | return val 214 | } 215 | v := reflect.ValueOf(iface) 216 | switch v.Kind() { 217 | case reflect.Invalid: 218 | return "" 219 | case reflect.Bool: 220 | return strconv.FormatBool(v.Bool()) 221 | case reflect.String: 222 | return v.String() 223 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 224 | return strconv.FormatInt(v.Int(), 10) 225 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 226 | return strconv.FormatUint(v.Uint(), 10) 227 | case reflect.Float64: 228 | return strconv.FormatFloat(v.Float(), 'f', -1, 64) 229 | case reflect.Float32: 230 | return strconv.FormatFloat(v.Float(), 'f', -1, 32) 231 | case reflect.Ptr, reflect.Struct, reflect.Map: 232 | b, err := json.Marshal(v.Interface()) 233 | if err != nil { 234 | return "" 235 | } 236 | return string(b) 237 | } 238 | return fmt.Sprintf("%v", iface) 239 | } 240 | -------------------------------------------------------------------------------- /sys/file.go: -------------------------------------------------------------------------------- 1 | package sys 2 | 3 | import ( 4 | "log" 5 | "os" 6 | "path/filepath" 7 | "strings" 8 | 9 | "github.com/kirinlabs/utils/str" 10 | ) 11 | 12 | func RealPath(f string) string { 13 | p, err := filepath.Abs(f) 14 | if err != nil { 15 | log.Panicln("Get absolute path error.") 16 | } 17 | p = strings.Replace(p, "\\", "/", -1) 18 | l := strings.LastIndex(p, "/") + 1 19 | return str.Substr(p, 0, l) 20 | } 21 | 22 | func IsExists(path string) bool { 23 | _, err := os.Stat(path) 24 | if err == nil { 25 | return true 26 | } 27 | if os.IsNotExist(err) { 28 | return false 29 | } 30 | return false 31 | } 32 | 33 | func IsFile(f string) bool { 34 | b, err := os.Stat(f) 35 | if err != nil { 36 | return false 37 | } 38 | if b.IsDir() { 39 | return false 40 | } 41 | return true 42 | } 43 | 44 | func IsDir(p string) bool { 45 | b, err := os.Stat(p) 46 | if err != nil { 47 | return false 48 | } 49 | if b.IsDir() { 50 | return true 51 | } 52 | return false 53 | } 54 | -------------------------------------------------------------------------------- /type.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Kirinlabs. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package utils 6 | 7 | import ( 8 | "reflect" 9 | ) 10 | 11 | // Returns a string of variable type 12 | func Type(arg interface{}) string { 13 | return reflect.TypeOf(arg).String() 14 | } 15 | 16 | // Int 17 | func IsInt(arg interface{}) bool { 18 | switch arg.(type) { 19 | case int: 20 | return true 21 | default: 22 | return false 23 | } 24 | } 25 | 26 | // Int64 27 | func IsInt64(arg interface{}) bool { 28 | switch arg.(type) { 29 | case int64: 30 | return true 31 | default: 32 | return false 33 | } 34 | } 35 | 36 | // Float64 37 | func IsFloat(arg interface{}) bool { 38 | return Type(arg) == "float64" 39 | } 40 | 41 | // String 42 | func IsString(arg interface{}) bool { 43 | return Type(arg) == "string" 44 | } 45 | 46 | func IsTime(arg interface{}) bool { 47 | return Type(arg) == "time.Time" 48 | } 49 | 50 | func IsBool(arg interface{}) bool { 51 | return Type(arg) == "bool" 52 | } 53 | 54 | func IsSlice(arg interface{}) bool { 55 | return reflect.TypeOf(arg).Kind().String() == "slice" 56 | } 57 | -------------------------------------------------------------------------------- /utils.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Kirinlabs. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package utils 6 | 7 | import ( 8 | "bytes" 9 | "encoding/json" 10 | "errors" 11 | "reflect" 12 | ) 13 | 14 | // Determine if the variable is null 15 | func Empty(arg interface{}) bool { 16 | if arg == nil { 17 | return true 18 | } 19 | v := reflect.ValueOf(arg) 20 | switch v.Kind() { 21 | case reflect.Slice, reflect.Map, reflect.Array: 22 | if v.Len() > 0 { 23 | return false 24 | } 25 | return true 26 | case reflect.Ptr: 27 | v = v.Elem() 28 | } 29 | return v.Interface() == reflect.Zero(v.Type()).Interface() 30 | } 31 | 32 | // Returns a formatted Json string 33 | func Export(v interface{}) string { 34 | b, err := json.Marshal(v) 35 | if err != nil { 36 | return "" 37 | } 38 | var buf bytes.Buffer 39 | err = json.Indent(&buf, b, "", "\t") 40 | if err != nil { 41 | return "" 42 | } 43 | return buf.String() 44 | } 45 | 46 | // Returns a Json string 47 | func Json(v interface{}) string { 48 | b, err := json.Marshal(v) 49 | if err != nil { 50 | return "" 51 | } 52 | return string(b) 53 | } 54 | 55 | func Decode(s string) interface{} { 56 | var i interface{} 57 | err := json.Unmarshal([]byte(s), &i) 58 | if err != nil { 59 | return nil 60 | } 61 | return i 62 | } 63 | 64 | func Unmarshal(s string, args ...interface{}) error { 65 | if len(args) == 0 { 66 | return errors.New("the second parameter is required.") 67 | } 68 | err := json.Unmarshal([]byte(s), &args[0]) 69 | if err != nil { 70 | return err 71 | } 72 | return nil 73 | } 74 | 75 | // utils.If(c).Then(v).Else(v).String() 76 | func If(c bool) *ifThen { 77 | return new(ifThen).If(c) 78 | } 79 | 80 | func Then(v interface{}) *ifThen { 81 | return new(ifThen).Then(v) 82 | } 83 | 84 | func Else(v interface{}) *ifThen { 85 | return new(ifThen).Else(v) 86 | } 87 | -------------------------------------------------------------------------------- /utils_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestEmpty(t *testing.T) { 8 | type KV struct { 9 | value interface{} 10 | result bool 11 | } 12 | 13 | data := map[string]*KV{ 14 | "int_true": &KV{0, true}, 15 | "int_false": &KV{100, false}, 16 | "str_true": &KV{"", true}, 17 | "str_false": &KV{"github", false}, 18 | "slice_true": &KV{make([]int, 0), true}, 19 | "slice_false": &KV{[]int{1, 2}, false}, 20 | "map_true": &KV{map[string]interface{}{}, true}, 21 | "map_false": &KV{map[string]interface{}{"name": "utils"}, false}, 22 | "ptr_true": &KV{&KV{}, true}, 23 | "ptr_false": &KV{&KV{"utils", false}, false}, 24 | "struct_true": &KV{KV{}, true}, 25 | "struct_false": &KV{KV{"utils", false}, false}, 26 | } 27 | 28 | for k, v := range data { 29 | if Empty(v.value) != v.result { 30 | t.Errorf("Empty test failed: %s expected %v,return %v != %v", k, v.result, Empty(v.value), v.result) 31 | } 32 | } 33 | } 34 | --------------------------------------------------------------------------------