init
This commit is contained in:
51
utils/array.go
Normal file
51
utils/array.go
Normal file
@ -0,0 +1,51 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func InArray(search, needle interface{}) bool {
|
||||
val := reflect.ValueOf(needle)
|
||||
|
||||
kind := val.Kind()
|
||||
|
||||
if kind == reflect.Slice || kind == reflect.Array {
|
||||
for i := 0; i < val.Len(); i++ {
|
||||
if val.Index(i).Interface() == search {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func ArrayFlip(src interface{}) interface{} {
|
||||
val := reflect.ValueOf(src)
|
||||
|
||||
kind := val.Kind()
|
||||
|
||||
out := make(map[interface{}]interface{}, 0)
|
||||
|
||||
if kind == reflect.Slice || kind == reflect.Array || kind == reflect.Map {
|
||||
for i := 0; i < val.Len(); i++ {
|
||||
fmt.Printf("val.Field():%v\n", val.Index(i).MapKeys())
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func ArrayStrings(src interface{}) []string {
|
||||
out := make([]string, 0)
|
||||
|
||||
val := reflect.ValueOf(src)
|
||||
|
||||
kind := val.Kind()
|
||||
|
||||
if kind == reflect.Slice || kind == reflect.Array {
|
||||
for i := 0; i < val.Len(); i++ {
|
||||
out = append(out, fmt.Sprintf("%v", val.Index(i).Interface()))
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
31
utils/array_test.go
Normal file
31
utils/array_test.go
Normal file
@ -0,0 +1,31 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const (
|
||||
a = 0x00001
|
||||
b = 0x00010
|
||||
c = 0x00100
|
||||
)
|
||||
|
||||
func TestArrayFlip(t *testing.T) {
|
||||
//flip := []uint64{1, 2, 3, 4}
|
||||
//out := ArrayFlip(flip)
|
||||
//t.Logf("out:%v\n", out)
|
||||
|
||||
d := a & b & c
|
||||
t.Log(d)
|
||||
|
||||
}
|
||||
|
||||
func TestArrayStrings(t *testing.T) {
|
||||
a := []uint64{1, 2, 3, 4, 5}
|
||||
t.Log(a)
|
||||
t.Log(reflect.TypeOf(a).String())
|
||||
b := ArrayStrings(a)
|
||||
t.Log(b)
|
||||
t.Log(reflect.TypeOf(b).String())
|
||||
}
|
||||
9
utils/bit_calc.go
Normal file
9
utils/bit_calc.go
Normal file
@ -0,0 +1,9 @@
|
||||
package utils
|
||||
|
||||
// Exchange 位置交换
|
||||
func Exchange(a, b int) (int, int) {
|
||||
a = a ^ b
|
||||
b = a ^ b
|
||||
a = a ^ b
|
||||
return a, b
|
||||
}
|
||||
83
utils/bit_calc_test.go
Normal file
83
utils/bit_calc_test.go
Normal file
@ -0,0 +1,83 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func converToBianry(n int) string {
|
||||
result := ""
|
||||
for ; n > 0; n /= 2 {
|
||||
lsb := n % 2
|
||||
result = strconv.Itoa(lsb) + result
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// 1,2,4
|
||||
func TestExchange(t *testing.T) {
|
||||
for i := 0; i < 10; i++ {
|
||||
//t.Log(1 << uint(i))
|
||||
}
|
||||
|
||||
//t.Log(0b00000000100)
|
||||
a := 1
|
||||
b := 1 << 1
|
||||
c := 1 << 2
|
||||
t.Log(a)
|
||||
t.Log(b)
|
||||
t.Log(c)
|
||||
|
||||
d := a | b | c
|
||||
t.Log(d)
|
||||
|
||||
t.Log(d & a)
|
||||
t.Log(d & b)
|
||||
t.Log(d & c)
|
||||
}
|
||||
|
||||
func TestAnyToByte(t *testing.T) {
|
||||
src := []int{1}
|
||||
|
||||
mark := 0
|
||||
|
||||
for i := 0; i < len(src); i++ {
|
||||
mark = mark | src[i]
|
||||
}
|
||||
t.Log(mark)
|
||||
}
|
||||
|
||||
func TestFromJSONFile(t *testing.T) {
|
||||
file := "FWBAT-GX-A13-V310.bin"
|
||||
f, err := os.Open(file)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
content, err := ioutil.ReadAll(f)
|
||||
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
return
|
||||
}
|
||||
t.Log(content)
|
||||
t.Log(len(content))
|
||||
|
||||
inputReader := bufio.NewReader(f)
|
||||
s, _, _ := inputReader.ReadLine()
|
||||
|
||||
t.Log(s)
|
||||
t.Log(len(s))
|
||||
//t.Log(bufio.NewReader(f))
|
||||
//for {
|
||||
// inputString, readerError := inputReader.ReadString('\n') //我们将inputReader里面的字符串按行进行读取。
|
||||
// if readerError == io.EOF {
|
||||
// return
|
||||
// }
|
||||
// t.Log(inputString)
|
||||
//}
|
||||
}
|
||||
13
utils/catch.go
Normal file
13
utils/catch.go
Normal file
@ -0,0 +1,13 @@
|
||||
package utils
|
||||
|
||||
import "fmt"
|
||||
|
||||
func TryCatch(f func()) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
err = fmt.Errorf("internal error: %v", err)
|
||||
fmt.Printf("TryCatch Error:%v\n", err)
|
||||
}
|
||||
}()
|
||||
f()
|
||||
}
|
||||
89
utils/convert.go
Normal file
89
utils/convert.go
Normal file
@ -0,0 +1,89 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
// types 数据结构类型
|
||||
types = []string{"string", "int64", "int", "uint", "uint64", "byte"}
|
||||
)
|
||||
|
||||
// ConvertTypes 需转换的类型
|
||||
type ConvertTypes struct {
|
||||
String, Int64, Int, Uint, Uint64, Byte bool
|
||||
}
|
||||
|
||||
// TypeConvert type mutual convert
|
||||
// result -- interface.(type)
|
||||
func (c *ConvertTypes) TypeConvert(from interface{}) interface{} {
|
||||
|
||||
fType := reflect.TypeOf(from)
|
||||
|
||||
val := func(r reflect.Type) interface{} {
|
||||
|
||||
return nil
|
||||
|
||||
}(fType)
|
||||
|
||||
return val
|
||||
}
|
||||
|
||||
// MapToStruct map to struct
|
||||
// key is struct filedName
|
||||
func MapToStruct(m map[string]interface{}, s interface{}) {
|
||||
for k, v := range m {
|
||||
|
||||
tRef := reflect.TypeOf(s).Elem()
|
||||
|
||||
fieldNum := tRef.NumField()
|
||||
|
||||
for i := 0; i < fieldNum; i++ {
|
||||
// 匹配结构字段名称
|
||||
if strings.ToLower(k) != strings.ToLower(tRef.Field(i).Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
vRef := reflect.ValueOf(s).Elem().FieldByName(tRef.Field(i).Name)
|
||||
|
||||
if !vRef.CanSet() {
|
||||
continue
|
||||
}
|
||||
|
||||
switch vRef.Type().String() {
|
||||
case "string":
|
||||
vRef.SetString(v.(string))
|
||||
break
|
||||
case "int64":
|
||||
vRef.SetInt(v.(int64))
|
||||
break
|
||||
case "int":
|
||||
switch reflect.TypeOf(v).String() {
|
||||
case "float64":
|
||||
vRef.SetInt(int64(v.(float64)))
|
||||
break
|
||||
case "int":
|
||||
vRef.SetInt(int64(v.(int)))
|
||||
break
|
||||
}
|
||||
break
|
||||
case "bool":
|
||||
vRef.SetBool(v.(bool))
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// StructToMap struct to map
|
||||
func StructToMap(s interface{}, m map[string]interface{}) {
|
||||
tRef := reflect.TypeOf(s).Elem()
|
||||
vRef := reflect.ValueOf(s).Elem()
|
||||
|
||||
fieldNum := tRef.NumField()
|
||||
|
||||
for index := 0; index < fieldNum; index++ {
|
||||
m[tRef.Field(index).Name] = vRef.FieldByName(tRef.Field(index).Name).Interface()
|
||||
}
|
||||
}
|
||||
138
utils/encrypt.go
Normal file
138
utils/encrypt.go
Normal file
@ -0,0 +1,138 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/md5"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"github.com/speps/go-hashids"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
// salt 盐值
|
||||
const salt = "CHeF6AC392"
|
||||
|
||||
func Base64Encode(src string) string {
|
||||
return base64.StdEncoding.EncodeToString([]byte(src))
|
||||
}
|
||||
|
||||
func Base64Decode(src string) []byte {
|
||||
_bytes, _ := base64.StdEncoding.DecodeString(src)
|
||||
return _bytes
|
||||
}
|
||||
|
||||
// Md5String
|
||||
func Md5String(s string, salt ...string) string {
|
||||
h := md5.New()
|
||||
if len(salt) > 0 {
|
||||
s += strings.Join(salt, "")
|
||||
}
|
||||
h.Write([]byte(s))
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
// Sha1String
|
||||
func Sha1String(s string) string {
|
||||
h := sha1.New()
|
||||
h.Write([]byte(s))
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
// Sha256String
|
||||
func Sha256String(s string) string {
|
||||
h := sha256.New()
|
||||
h.Write([]byte(s))
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
// Sha512String
|
||||
func Sha512String(s string) string {
|
||||
h := sha512.New()
|
||||
h.Write([]byte(s))
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
func HashString(s []byte) string {
|
||||
hash, _ := bcrypt.GenerateFromPassword(s, bcrypt.DefaultCost)
|
||||
return string(hash)
|
||||
}
|
||||
|
||||
func HashCompare(src, compare []byte) bool {
|
||||
return bcrypt.CompareHashAndPassword(src, compare) == nil
|
||||
}
|
||||
|
||||
// HASHIDEncode 混淆
|
||||
func HASHIDEncode(src int) string {
|
||||
hd := hashids.NewData()
|
||||
hd.Salt = salt
|
||||
hd.MinLength = 6
|
||||
h := hashids.NewWithData(hd)
|
||||
e, _ := h.Encode([]int{src})
|
||||
return e
|
||||
}
|
||||
|
||||
// HASHIDDecode 还原混淆
|
||||
func HASHIDDecode(src string) int {
|
||||
hd := hashids.NewData()
|
||||
hd.Salt = salt
|
||||
h := hashids.NewWithData(hd)
|
||||
e, _ := h.DecodeWithError(src)
|
||||
return e[0]
|
||||
}
|
||||
|
||||
// Padding 对明文进行填充
|
||||
func Padding(plainText []byte, blockSize int) []byte {
|
||||
n := blockSize - len(plainText)%blockSize
|
||||
temp := bytes.Repeat([]byte{byte(n)}, n)
|
||||
plainText = append(plainText, temp...)
|
||||
return plainText
|
||||
}
|
||||
|
||||
// UnPadding 对密文删除填充
|
||||
func UnPadding(cipherText []byte) []byte {
|
||||
end := cipherText[len(cipherText)-1]
|
||||
cipherText = cipherText[:len(cipherText)-int(end)]
|
||||
return cipherText
|
||||
}
|
||||
|
||||
// AESCBCEncrypt AEC加密(CBC模式)
|
||||
func AESCBCEncrypt(plainText, key, iv []byte) ([]byte, error) {
|
||||
//指定加密算法,返回一个AES算法的Block接口对象
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//进行填充
|
||||
plainText = Padding(plainText, block.BlockSize())
|
||||
//指定分组模式,返回一个BlockMode接口对象
|
||||
blockMode := cipher.NewCBCEncrypter(block, iv)
|
||||
//加密连续数据库
|
||||
cipherText := make([]byte, len(plainText))
|
||||
blockMode.CryptBlocks(cipherText, plainText)
|
||||
//返回密文
|
||||
return cipherText, nil
|
||||
}
|
||||
|
||||
// AESCBCDecrypt AEC解密(CBC模式)
|
||||
func AESCBCDecrypt(cipherText, key, iv []byte) ([]byte, error) {
|
||||
//指定解密算法,返回一个AES算法的Block接口对象
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//指定分组模式,返回一个BlockMode接口对象
|
||||
blockMode := cipher.NewCBCDecrypter(block, iv)
|
||||
//解密
|
||||
plainText := make([]byte, len(cipherText))
|
||||
blockMode.CryptBlocks(plainText, cipherText)
|
||||
//删除填充
|
||||
plainText = UnPadding(plainText)
|
||||
return plainText, nil
|
||||
}
|
||||
9
utils/encrypt_test.go
Normal file
9
utils/encrypt_test.go
Normal file
@ -0,0 +1,9 @@
|
||||
package utils
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestSha256String(t *testing.T) {
|
||||
//t.Log(Md5String("9f735e0df9a1ddc702bf0a1a7b83033f9f7153a00c29de82cedadc9957289b05"))
|
||||
t.Log(HASHIDEncode(123))
|
||||
t.Log(HASHIDDecode("lV5OBJ"))
|
||||
}
|
||||
61
utils/file.go
Normal file
61
utils/file.go
Normal file
@ -0,0 +1,61 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func Open(name string) (f *os.File, err error) {
|
||||
_, err = os.Stat(name)
|
||||
|
||||
if os.IsNotExist(err) {
|
||||
return os.OpenFile(name, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, fmt.Errorf("file %s already exists", name)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
func IsDir(path string) bool {
|
||||
s, err := os.Stat(path)
|
||||
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return s.IsDir()
|
||||
}
|
||||
|
||||
func Mkdir(path string) error {
|
||||
return os.Mkdir(path, os.ModePerm)
|
||||
}
|
||||
|
||||
func MkdirAll(path string) error {
|
||||
return os.MkdirAll(path, os.ModePerm)
|
||||
}
|
||||
|
||||
func PrepareOutput(path string) error {
|
||||
fi, err := os.Stat(path)
|
||||
|
||||
if err != nil {
|
||||
if os.IsExist(err) && !fi.IsDir() {
|
||||
return err
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
err = os.MkdirAll(path, 0777)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
83
utils/json.go
Normal file
83
utils/json.go
Normal file
@ -0,0 +1,83 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// AnyToJSON ToJson
|
||||
func AnyToJSON(any interface{}) string {
|
||||
bytes, _ := json.Marshal(any)
|
||||
return string(bytes)
|
||||
}
|
||||
|
||||
// AnyToByte ToByte
|
||||
func AnyToByte(any interface{}) []byte {
|
||||
bytes, _ := json.Marshal(any)
|
||||
return bytes
|
||||
}
|
||||
|
||||
// FromJSON get value from JSON string
|
||||
func FromJSON(data string, v interface{}) error {
|
||||
if data == "" {
|
||||
return errors.New("data nil")
|
||||
}
|
||||
|
||||
if err := json.Unmarshal([]byte(data), v); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FromJSONToMap get mapvalue from JSON string
|
||||
func FromJSONToMap(data string) map[string]interface{} {
|
||||
var jsonBody map[string]interface{}
|
||||
//解析 body
|
||||
if len(data) > 0 {
|
||||
FromJSON(data, &jsonBody)
|
||||
} else {
|
||||
jsonBody = make(map[string]interface{}, 0)
|
||||
}
|
||||
return jsonBody
|
||||
}
|
||||
|
||||
// FromJSONBytes get value from JSON bytes
|
||||
func FromJSONBytes(data []byte, v interface{}) error {
|
||||
if len(data) <= 0 {
|
||||
return errors.New("data nil")
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(data, v); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FromJSONReader get value from JSON Reader
|
||||
func FromJSONReader(data io.Reader, v interface{}) error {
|
||||
if data == nil {
|
||||
return errors.New("jsonFile nail")
|
||||
}
|
||||
|
||||
jsonDecoder := json.NewDecoder(data)
|
||||
return jsonDecoder.Decode(v)
|
||||
}
|
||||
|
||||
// FromJSONFile get value from JSON file
|
||||
func FromJSONFile(jsonFile string, v interface{}) error {
|
||||
if len(jsonFile) <= 0 {
|
||||
return errors.New("jsonFile nail")
|
||||
}
|
||||
|
||||
file, err := os.Open(jsonFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
jsonDecoder := json.NewDecoder(bufio.NewReader(file))
|
||||
return jsonDecoder.Decode(v)
|
||||
}
|
||||
45
utils/jwt.go
Normal file
45
utils/jwt.go
Normal file
@ -0,0 +1,45 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
)
|
||||
|
||||
const jwtKey = "abc123ABC"
|
||||
|
||||
// JWTEncrypt 加密
|
||||
func JWTEncrypt(effectTimes int, param ...map[string]interface{}) string {
|
||||
token := jwt.New(jwt.SigningMethodHS256)
|
||||
claims := make(jwt.MapClaims, 0)
|
||||
claims["exp"] = fmt.Sprintf("%d", time.Now().Add(time.Second*time.Duration(effectTimes)).Unix())
|
||||
claims["iat"] = fmt.Sprintf("%d", time.Now().Unix())
|
||||
|
||||
if len(param) > 0 {
|
||||
for _, val := range param {
|
||||
for k, v := range val {
|
||||
claims[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
token.Claims = claims
|
||||
tokenString, _ := token.SignedString([]byte(jwtKey))
|
||||
return tokenString
|
||||
}
|
||||
|
||||
// JWTDecrypt 解密
|
||||
func JWTDecrypt(tokenString string) jwt.MapClaims {
|
||||
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(jwtKey), nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
claims, ok := token.Claims.(jwt.MapClaims)
|
||||
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return claims
|
||||
}
|
||||
42
utils/rand.go
Normal file
42
utils/rand.go
Normal file
@ -0,0 +1,42 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
uuid "github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
const (
|
||||
str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
)
|
||||
|
||||
func GetUUID() string {
|
||||
return uuid.NewV4().String()
|
||||
}
|
||||
|
||||
func GetRandomCode(length int) string {
|
||||
rand.Seed(time.Now().Unix())
|
||||
|
||||
code := make([]string, 0)
|
||||
|
||||
for i := 0; i < length; i++ {
|
||||
code = append(code, fmt.Sprintf("%d", rand.Intn(10)))
|
||||
}
|
||||
return strings.Join(code, "")
|
||||
}
|
||||
|
||||
func GetRandomString(length int) string {
|
||||
bytes := []byte(str)
|
||||
|
||||
result := make([]byte, 0)
|
||||
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
|
||||
for i := 0; i < length; i++ {
|
||||
result = append(result, bytes[r.Intn(len(bytes))])
|
||||
}
|
||||
return string(result)
|
||||
}
|
||||
14
utils/reflect.go
Normal file
14
utils/reflect.go
Normal file
@ -0,0 +1,14 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
)
|
||||
|
||||
func DeepCopy(dst, src interface{}) error {
|
||||
var buf bytes.Buffer
|
||||
if err := gob.NewEncoder(&buf).Encode(src); err != nil {
|
||||
return err
|
||||
}
|
||||
return gob.NewDecoder(bytes.NewBuffer(buf.Bytes())).Decode(dst)
|
||||
}
|
||||
45
utils/regexp.go
Normal file
45
utils/regexp.go
Normal file
@ -0,0 +1,45 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func ValidateMobile(mobile string) bool {
|
||||
reg := regexp.MustCompile("^1[3|4|5|6|7|8|9][0-9]\\d{8}$")
|
||||
return reg.MatchString(mobile)
|
||||
}
|
||||
|
||||
func ValidateEmail(email string) bool {
|
||||
reg := regexp.MustCompile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$")
|
||||
return reg.MatchString(email)
|
||||
}
|
||||
|
||||
func ValidateUrl(url string) {
|
||||
//reg := regexp.MustCompile("^([hH][tT]{2}[pP]:|||[hH][tT]{2}[pP][sS]:|www\.)(([A-Za-z0-9-~]+)\.)+([A-Za-z0-9-~\/])+$")
|
||||
}
|
||||
|
||||
func ValidateIDCard(obj string) bool {
|
||||
reg := regexp.MustCompile("^[1-9]\\d{5}(18|19|([23]\\d))\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$")
|
||||
return reg.MatchString(obj)
|
||||
|
||||
}
|
||||
|
||||
func ValidateIP(ip string) bool {
|
||||
reg := regexp.MustCompile("^((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})(\\.((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})){3}$")
|
||||
return reg.MatchString(ip)
|
||||
}
|
||||
|
||||
func ValidateCompile(obj, compile string) bool {
|
||||
reg := regexp.MustCompile(compile)
|
||||
return reg.MatchString(obj)
|
||||
}
|
||||
|
||||
func ReplaceAllCompile(obj, compile, replace string) string {
|
||||
reg := regexp.MustCompile(compile)
|
||||
return reg.ReplaceAllString(obj, replace)
|
||||
}
|
||||
|
||||
func MatchString(pattern string, s string) bool {
|
||||
status, _ := regexp.MatchString(pattern, s)
|
||||
return status
|
||||
}
|
||||
47
utils/regexp_test.go
Normal file
47
utils/regexp_test.go
Normal file
@ -0,0 +1,47 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestReplaceCompile(t *testing.T) {
|
||||
src := "12312321321"
|
||||
|
||||
t.Log(src)
|
||||
|
||||
compile := "[/]+"
|
||||
src = ReplaceAllCompile(src, compile, "/")
|
||||
t.Log(src)
|
||||
|
||||
compile = "(^[\\w])([\\w/]*)([\\w])$"
|
||||
//compile = "(^[\\w])"
|
||||
|
||||
//compile = "^[\\w]" +
|
||||
// "([\\w*])" +
|
||||
// "[\\w]$"
|
||||
status := ValidateCompile(src, compile)
|
||||
t.Log(status)
|
||||
|
||||
//compile := "user.+\\z"
|
||||
//src = ReplaceAllCompile(src, compile, "user")
|
||||
//t.Log(src)
|
||||
|
||||
//compile = "^\\w{0,50}$"
|
||||
//status = ValidateCompile(src, compile)
|
||||
//t.Log(status)
|
||||
//
|
||||
////支持中文、大小写字母、日文、数字、短划线、下划线、斜杠和小数点,必须以中文、英文或数字开头,不超过 30 个字符
|
||||
//compile = "(^[a-zA-Z0-9\u4e00-\u9fa5])([a-zA-Z0-9_\u4e00-\u9fa5-_/.]*){0,30}$"
|
||||
//status = ValidateCompile(src, compile)
|
||||
//t.Logf("文本检测:%v\n", status)
|
||||
}
|
||||
|
||||
func TestValidateCompile(t *testing.T) {
|
||||
src := "2134"
|
||||
|
||||
t.Log(src)
|
||||
|
||||
compile := "^[\\w-.:]{4,32}$"
|
||||
status := ValidateCompile(src, compile)
|
||||
t.Log(status)
|
||||
}
|
||||
118
utils/request.go
Normal file
118
utils/request.go
Normal file
@ -0,0 +1,118 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type (
|
||||
// Headers 消息头
|
||||
Headers struct {
|
||||
UserAgent string
|
||||
ContentType string
|
||||
Cookies map[string]string
|
||||
Others map[string]string
|
||||
}
|
||||
|
||||
// Method 请求方式
|
||||
Method string
|
||||
|
||||
// Client
|
||||
Client struct {
|
||||
Url string
|
||||
Method Method
|
||||
Params map[string]interface{}
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
MethodForGet Method = "GET"
|
||||
MethodForPost Method = "POST"
|
||||
|
||||
DefaultUserAgent string = "Mozilla/5.0 (SF) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.6.6666.66 Safari/537.36"
|
||||
)
|
||||
|
||||
// RequestBodyFormat 请求消息内容格式
|
||||
type RequestBodyFormat int
|
||||
|
||||
const (
|
||||
RequestBodyFormatForFormData RequestBodyFormat = iota + 1
|
||||
RequestBodyFormatForXWWWFormUrlencoded
|
||||
RequestBodyFormatForRaw
|
||||
)
|
||||
|
||||
const (
|
||||
RequestContentTypeForFormData string = "application/form-data"
|
||||
RequestContentTypeForXWWWFormUrlencoded string = "application/x-www-form-urlencoded"
|
||||
)
|
||||
|
||||
// Request 发起请求
|
||||
func (this *Client) Request(format RequestBodyFormat, headers ...Headers) ([]byte, error) {
|
||||
client := new(http.Client)
|
||||
|
||||
var reqBody io.Reader
|
||||
|
||||
if this.Method == MethodForGet {
|
||||
_params := make([]string, 0)
|
||||
|
||||
for k, v := range this.Params {
|
||||
_params = append(_params, fmt.Sprintf("%s=%v", k, v))
|
||||
}
|
||||
this.Url += "?" + strings.Join(_params, "&")
|
||||
} else {
|
||||
if format == RequestBodyFormatForFormData || format == RequestBodyFormatForXWWWFormUrlencoded {
|
||||
_params := make([]string, 0)
|
||||
for k, v := range this.Params {
|
||||
_params = append(_params, fmt.Sprintf("%s=%v", k, v))
|
||||
}
|
||||
reqBody = strings.NewReader(strings.Join(_params, "&"))
|
||||
} else if format == RequestBodyFormatForRaw {
|
||||
_bytes, _ := json.Marshal(this.Params)
|
||||
reqBody = bytes.NewReader(_bytes)
|
||||
}
|
||||
}
|
||||
req, err := http.NewRequest(string(this.Method), this.Url, reqBody)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, v := range headers {
|
||||
if v.UserAgent != "" {
|
||||
req.Header.Add("User-Agent", v.UserAgent)
|
||||
}
|
||||
if v.ContentType != "" {
|
||||
req.Header.Add("Content-Type", v.ContentType)
|
||||
}
|
||||
if len(v.Cookies) > 0 {
|
||||
for key, val := range v.Cookies {
|
||||
req.AddCookie(&http.Cookie{Name: key, Value: val})
|
||||
}
|
||||
}
|
||||
if len(v.Others) > 0 {
|
||||
for key, val := range v.Others {
|
||||
req.Header.Add(key, val)
|
||||
}
|
||||
}
|
||||
}
|
||||
resp := new(http.Response)
|
||||
|
||||
if resp, err = client.Do(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bytes, err := ioutil.ReadAll(resp.Body)
|
||||
defer resp.Body.Close()
|
||||
|
||||
return bytes, err
|
||||
}
|
||||
|
||||
// NewClient
|
||||
func NewClient(url string, method Method, params map[string]interface{}) *Client {
|
||||
return &Client{
|
||||
Url: url, Method: method, Params: params,
|
||||
}
|
||||
}
|
||||
266
utils/request_test.go
Normal file
266
utils/request_test.go
Normal file
@ -0,0 +1,266 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type (
|
||||
// BaiDuError 错误提示
|
||||
BaiDuError struct {
|
||||
Error string `json:"error"`
|
||||
ErrorDescription string `json:"error_description"`
|
||||
}
|
||||
// BaiDuAccessToken AccessToken信息
|
||||
BaiDuAccessToken struct {
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
ExpiresIn int `json:"expires_in"`
|
||||
Scope string `json:"scope"`
|
||||
SessionKey string `json:"session_key"`
|
||||
AccessToken string `json:"access_token"`
|
||||
SessionSecret string `json:"session_secret"`
|
||||
BaiDuError
|
||||
}
|
||||
// BaiDuSpeechQuick SpeechQuick信息
|
||||
BaiDuSpeechQuick struct {
|
||||
ErrNo int `json:"err_no"`
|
||||
ErrMsg string `json:"err_msg"`
|
||||
SN string `json:"sn"`
|
||||
Result []string `json:"result"`
|
||||
}
|
||||
// BaiDuRobotDialogue 机器人对话
|
||||
BaiDuRobotDialogue struct {
|
||||
ErrorCode int `json:"error_code"`
|
||||
ErrorMsg string `json:"error_msg"`
|
||||
Result struct {
|
||||
Version string `json:"version"`
|
||||
ServiceID string `json:"service_id"`
|
||||
LogID string `json:"log_id"`
|
||||
InteractionID string `json:"interaction_id"`
|
||||
Response struct {
|
||||
Status int `json:"status"`
|
||||
Msg string `json:"msg"`
|
||||
ActionList []struct {
|
||||
Confidence float64 `json:"confidence"`
|
||||
ActionID string `json:"action_id"`
|
||||
Say string `json:"say"`
|
||||
CustomReply string `json:"custom_reply"`
|
||||
Type string `json:"type"`
|
||||
} `json:"action_list"`
|
||||
Schema struct {
|
||||
Confidence float64 `json:"confidence"`
|
||||
Intent string `json:"intent"`
|
||||
IntentConfidence float64 `json:"intent_confidence"`
|
||||
Slots []struct {
|
||||
Confidence float64 `json:"confidence"`
|
||||
Begin int `json:"begin"`
|
||||
Length int `json:"length"`
|
||||
OriginalWord string `json:"original_word"`
|
||||
NormalizedWord string `json:"normalized_word"`
|
||||
WordType string `json:"word_type"`
|
||||
Name string `json:"name"`
|
||||
SessionOffset string `json:"session_offset"`
|
||||
MergeMethod string `json:"merge_method"`
|
||||
} `json:"slots"`
|
||||
} `json:"schema"`
|
||||
} `json:"response"`
|
||||
} `json:"result"`
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
baiDuClientID string = "Sy0tLT7bHWE2RhollVOqelHq"
|
||||
baiDuClientSecret string = "jSr0a2Isaivi1yvgk2TXlB7tqg21Gf1m"
|
||||
//baiDuClientID string = "MDNsII2jkUtbF729GQOZt7FS"
|
||||
//baiDuClientSecret string = "0vWCVCLsbWHMSH1wjvxaDq4VmvCZM2O9"
|
||||
|
||||
// baiDuRequestURLForAccessToken 获取token地址
|
||||
baiDuRequestURLForAccessToken string = "https://aip.baidubce.com/oauth/2.0/token"
|
||||
// baiDuRequestURLForVoiceQuick 语音识别极速版
|
||||
baiDuRequestURLForVoiceQuick string = "https://vop.baidu.com/pro_api"
|
||||
// baiDuRequestURLForRobotDialogue 语音机器人对话
|
||||
baiDuRequestURLForRobotDialogue string = "https://aip.baidubce.com/rpc/2.0/unit/bot/chat"
|
||||
//baiDuRequestURLForRobotDialogue string = "https://aip.baidubce.com/rpc/2.0/unit/service/chat"
|
||||
)
|
||||
|
||||
func TestNewClient(t *testing.T) {
|
||||
//file := "../upload/20210624/16k1.pcm"
|
||||
//
|
||||
client2 := NewClient(baiDuRequestURLForAccessToken, MethodForPost, map[string]interface{}{
|
||||
"grant_type": "client_credentials", "client_id": baiDuClientID, "client_secret": baiDuClientSecret,
|
||||
})
|
||||
resp2, err := client2.Request(RequestBodyFormatForFormData)
|
||||
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
return
|
||||
}
|
||||
response := new(BaiDuAccessToken)
|
||||
|
||||
_ = FromJSONBytes(resp2, response)
|
||||
|
||||
if response.Error != "" {
|
||||
t.Logf("获取百度AccessToken错误:%v - %v", response.Error, response.ErrorDescription)
|
||||
return
|
||||
}
|
||||
//t.Log(response.AccessToken)
|
||||
//
|
||||
//reader, err := os.OpenFile(file, os.O_RDONLY, 0666)
|
||||
//
|
||||
//if err != nil {
|
||||
// t.Log(err)
|
||||
// return
|
||||
//}
|
||||
//defer reader.Close()
|
||||
//
|
||||
//content, _ := ioutil.ReadAll(reader)
|
||||
//
|
||||
//cuid := ""
|
||||
//
|
||||
//netitfs, err := net.Interfaces()
|
||||
//
|
||||
//if err != nil {
|
||||
// cuid = "anonymous_sqzn"
|
||||
//} else {
|
||||
// for _, itf := range netitfs {
|
||||
// if cuid = itf.HardwareAddr.String(); len(cuid) > 0 {
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//t.Log(cuid)
|
||||
//t.Log(base64.StdEncoding.EncodeToString(content))
|
||||
//t.Log(fmt.Sprintf("%d", len(content)))
|
||||
//
|
||||
//_params := map[string]interface{}{
|
||||
// "format": file[len(file)-3:],
|
||||
// "rate": 16000,
|
||||
// "dev_pid": 1537,
|
||||
// "channel": 1,
|
||||
// "token": "24.1f876b06d070d7403c90832dddb813cb.2592000.1627110943.282335-24431674",
|
||||
// "cuid": cuid,
|
||||
// "speech": base64.StdEncoding.EncodeToString(content),
|
||||
// "len": len(content),
|
||||
//}
|
||||
//_json, _ := json.Marshal(_params)
|
||||
//
|
||||
//req, err := http.NewRequest("GET", "http://vop.baidu.com/server_api", bytes.NewBuffer(_json))
|
||||
//
|
||||
//if err != nil {
|
||||
// t.Log(err)
|
||||
// return
|
||||
//}
|
||||
//resp := new(http.Response)
|
||||
//
|
||||
//client := new(http.Client)
|
||||
//
|
||||
//if resp, err = client.Do(req); err != nil {
|
||||
// t.Log(err)
|
||||
// return
|
||||
//}
|
||||
//bytes, err := ioutil.ReadAll(resp.Body)
|
||||
//defer resp.Body.Close()
|
||||
//
|
||||
//response1 := new(BaiDuSpeechQuick)
|
||||
//
|
||||
//_ = FromJSONBytes(bytes, response1)
|
||||
//
|
||||
//t.Logf("resp:%v\n", AnyToJSON(response1))
|
||||
|
||||
serviceID := "1101579"
|
||||
|
||||
params2 := map[string]interface{}{
|
||||
"version": "2.0",
|
||||
//"service_id": serviceID,
|
||||
"bot_id": serviceID,
|
||||
"log_id": Md5String(AnyToJSON(2040256374931197952), serviceID),
|
||||
"session_id": Sha256String(AnyToJSON(2040256374931197952) + serviceID),
|
||||
"request": map[string]interface{}{
|
||||
"query": "公告",
|
||||
"user_id": AnyToJSON(2040256374931197952),
|
||||
"query_info": map[string]interface{}{
|
||||
"asr_candidates": []string{},
|
||||
"source": "KEYBOARD",
|
||||
"type": "TEXT",
|
||||
},
|
||||
},
|
||||
"bernard_level": 1,
|
||||
}
|
||||
t.Log(params2)
|
||||
client3 := NewClient(baiDuRequestURLForRobotDialogue+"?access_token="+response.AccessToken,
|
||||
MethodForPost, params2)
|
||||
|
||||
resp3, err := client3.Request(RequestBodyFormatForRaw, Headers{ContentType: "application/json; charset=UTF-8"})
|
||||
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
return
|
||||
}
|
||||
response3 := new(BaiDuRobotDialogue)
|
||||
|
||||
_ = FromJSONBytes(resp3, response3)
|
||||
|
||||
t.Log(AnyToJSON(response3))
|
||||
|
||||
return
|
||||
//
|
||||
//client1 := NewClient("http://vop.baidu.com/server_api", MethodForPost, params)
|
||||
//
|
||||
//resp1 := make([]byte, 0)
|
||||
//
|
||||
//if resp1, err = client1.Request(RequestBodyFormatForRaw, Headers{
|
||||
// ContentType: "application/json",
|
||||
//}); err != nil {
|
||||
// t.Log(err)
|
||||
// return
|
||||
//}
|
||||
//response1 := new(BaiDuSpeechQuick)
|
||||
//
|
||||
//_ = FromJSONBytes(resp1, response1)
|
||||
//
|
||||
//t.Logf("resp:%v\n", AnyToJSON(response1))
|
||||
}
|
||||
|
||||
func TestClient_Request(t *testing.T) {
|
||||
request := NewClient("https://image1.ljcdn.com/hdic-resblock/4494aa6e-4165-4f4a-b7ba-4ab095dd1ffa.JPG.710x400.jpg", "GET", nil)
|
||||
|
||||
resp, err := request.Request(RequestBodyFormatForFormData, Headers{
|
||||
Others: map[string]string{
|
||||
"Referer": "http://drc.hefei.gov.cn/group4/M00/07/4D/wKgEIWEM9X-AXLhsAAONk965l5o088.png",
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36",
|
||||
"Cookie": "__jsluid_h=9fcece02433a024c638dd5e8d4cf6f92; __jsl_clearance=1628842172.968|0|8rBRZzH5SoW3MMG1%2FWkYpLUeRXA%3D",
|
||||
},
|
||||
})
|
||||
f, err := os.Create("test.jpg")
|
||||
if err != nil {
|
||||
log.Fatal("Couldn't open file")
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
err = binary.Write(f, binary.LittleEndian, resp)
|
||||
|
||||
if err != nil {
|
||||
log.Fatal("Write failed")
|
||||
}
|
||||
|
||||
//resp, err := request.Request(RequestBodyFormatForFormData, Headers{
|
||||
// //Others: map[string]string{
|
||||
// // "Referer": "http://drc.hefei.gov.cn/group4/M00/07/4D/wKgEIWEM9X-AXLhsAAONk965l5o088.png",
|
||||
// // "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36",
|
||||
// // "Cookie": "__jsluid_h=2844bb494bad8b1cd372e28c65844abd; __jsl_clearance=1628840623.068|0|vNUfDD1V4muQrHrWy%2BmhoGbOFr0%3D",
|
||||
// //},
|
||||
//})
|
||||
//f, err := os.Create("test.jpg")
|
||||
//if err != nil {
|
||||
// log.Fatal("Couldn't open file")
|
||||
//}
|
||||
//defer f.Close()
|
||||
//
|
||||
//err = binary.Write(f, binary.LittleEndian, resp)
|
||||
//
|
||||
//if err != nil {
|
||||
// log.Fatal("Write failed")
|
||||
//}
|
||||
}
|
||||
55
utils/snowflake.go
Normal file
55
utils/snowflake.go
Normal file
@ -0,0 +1,55 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
workerBits uint8 = 10
|
||||
numberBits uint8 = 12
|
||||
workerMax int64 = -1 ^ (-1 << workerBits)
|
||||
numberMax int64 = -1 ^ (-1 << numberBits)
|
||||
timeShift uint8 = workerBits + numberBits
|
||||
workerShift uint8 = numberBits
|
||||
startTime int64 = 1136185445000
|
||||
)
|
||||
|
||||
type Worker struct {
|
||||
mu sync.Mutex
|
||||
timestamp int64
|
||||
workerID int64
|
||||
number int64
|
||||
}
|
||||
|
||||
func (w *Worker) GetID() int64 {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
now := time.Now().UnixNano() / 1e6
|
||||
|
||||
if w.timestamp == now {
|
||||
w.number++
|
||||
if w.number > numberMax {
|
||||
for now <= w.timestamp {
|
||||
now = time.Now().UnixNano() / 1e6
|
||||
}
|
||||
}
|
||||
} else {
|
||||
w.number = 0
|
||||
w.timestamp = now
|
||||
}
|
||||
return (now-startTime)<<timeShift | (w.workerID << workerShift) | (w.number)
|
||||
}
|
||||
|
||||
func NewSnowflake(workerID int64) (*Worker, error) {
|
||||
if workerID < 0 || workerID > workerMax {
|
||||
return nil, errors.New("Worker ID Excess Of Quantity")
|
||||
}
|
||||
// 生成一个新节点
|
||||
return &Worker{
|
||||
timestamp: 0,
|
||||
workerID: workerID,
|
||||
number: 0,
|
||||
}, nil
|
||||
}
|
||||
38
utils/strconv.go
Normal file
38
utils/strconv.go
Normal file
@ -0,0 +1,38 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func StringToInt(src string) int {
|
||||
dst, _ := strconv.Atoi(src)
|
||||
return dst
|
||||
}
|
||||
|
||||
func StringToInt64(src string) int64 {
|
||||
dst, _ := strconv.ParseInt(src, 10, 64)
|
||||
return dst
|
||||
}
|
||||
|
||||
func StringToUnit(src string) uint {
|
||||
dst, _ := strconv.Atoi(src)
|
||||
return uint(dst)
|
||||
}
|
||||
|
||||
func StringToUnit64(src string) uint64 {
|
||||
dst, _ := strconv.ParseUint(src, 10, 64)
|
||||
return dst
|
||||
}
|
||||
|
||||
func StringToFloat(src string) (float64, error) {
|
||||
return strconv.ParseFloat(src, 64)
|
||||
}
|
||||
|
||||
func IntToString(src int64) string {
|
||||
return fmt.Sprintf("%d", src)
|
||||
}
|
||||
|
||||
func UintToString(src uint64) string {
|
||||
return fmt.Sprintf("%d", src)
|
||||
}
|
||||
30
utils/string.go
Normal file
30
utils/string.go
Normal file
@ -0,0 +1,30 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ToLowerCase(src []rune) rune {
|
||||
return src[0] | 0x20
|
||||
}
|
||||
|
||||
func ToUpperCase(src []rune) rune {
|
||||
return src[0] ^ 0x20
|
||||
}
|
||||
|
||||
func ToSnake(src, delimiter string) string {
|
||||
src = strings.TrimSpace(src)
|
||||
objs := strings.Split(src, delimiter)
|
||||
|
||||
out := make([]rune, 0)
|
||||
|
||||
for _, v := range objs {
|
||||
if len(v) <= 0 {
|
||||
continue
|
||||
}
|
||||
obj := []rune(v)
|
||||
obj[0] = ToUpperCase(obj)
|
||||
out = append(out, obj...)
|
||||
}
|
||||
return string(out)
|
||||
}
|
||||
8
utils/string_test.go
Normal file
8
utils/string_test.go
Normal file
@ -0,0 +1,8 @@
|
||||
package utils
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestToSnake(t *testing.T) {
|
||||
src := "sys_"
|
||||
t.Log(ToSnake(src, "_"))
|
||||
}
|
||||
68
utils/time.go
Normal file
68
utils/time.go
Normal file
@ -0,0 +1,68 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"math"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Week int
|
||||
|
||||
const (
|
||||
Monday Week = iota + 1
|
||||
Tuesday
|
||||
Wednesday
|
||||
Thursday
|
||||
Friday
|
||||
Saturday
|
||||
Sunday
|
||||
)
|
||||
|
||||
func IsEmptyTime(t time.Time) bool {
|
||||
return t.IsZero()
|
||||
}
|
||||
|
||||
func FormatDate(t time.Time) string {
|
||||
return t.Format("2006-01-02")
|
||||
}
|
||||
|
||||
func FormatDatetime(t time.Time) string {
|
||||
return t.Format("2006-01-02 15:04:05")
|
||||
}
|
||||
|
||||
func FormatTimeForLayout(t time.Time, layout string) string {
|
||||
return t.Format(layout)
|
||||
}
|
||||
|
||||
func DateTimeToTime(t string) time.Time {
|
||||
_time, _ := time.ParseInLocation("2006-01-02 15:04:05", t, time.Local)
|
||||
return _time
|
||||
}
|
||||
|
||||
func DataTimeToDate(t string) time.Time {
|
||||
_time, _ := time.ParseInLocation("2006-01-02", t, time.Local)
|
||||
return _time
|
||||
}
|
||||
|
||||
func GetMondayTime(t time.Time) time.Time {
|
||||
offset := int(time.Monday - t.Weekday())
|
||||
|
||||
if offset > 0 {
|
||||
offset = -6
|
||||
}
|
||||
return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.Local).AddDate(0, 0, offset)
|
||||
}
|
||||
|
||||
func MonthBeginAt(year, month int) time.Time {
|
||||
return time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.Now().Location())
|
||||
}
|
||||
|
||||
func MonthFinishAt(year, month int) time.Time {
|
||||
mark := time.Date(year, time.Month(month), 1, 23, 59, 59, 0, time.Now().Location())
|
||||
return mark.AddDate(0, 1, -1)
|
||||
}
|
||||
|
||||
func DiffTimeMonth(time1, time2 time.Time) int {
|
||||
year := math.Abs(float64(time1.Year()) - float64(time2.Year()))
|
||||
month := math.Abs(float64(time1.Month()) - float64(time2.Month()))
|
||||
return int(year)*12 + int(month) + 1
|
||||
}
|
||||
Reference in New Issue
Block a user