package util
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"gopkg.in/gomail.v2"
"io"
"log"
"math/rand"
"net"
"net/url"
"os"
"path"
"path/filepath"
"reflect"
"strconv"
"strings"
"time"
)
func ParseUriQueryToMap(query string) map[string]interface{} {
queryMap := strings.Split(query, "&")
a := make(map[string]interface{}, len(queryMap))
for _,item := range queryMap {
itemMap := strings.Split(item, "=")
a[itemMap[0]] = itemMap[1]
}
return a
}
func MapToJson(data map[string]interface{}) string {
jsonStr, err := json.Marshal(data)
Must(err)
return string(jsonStr)
}
func RandomN(n int) int {
rand.Seed(time.Now().UnixNano())
return rand.Intn(n)
}
func Must(err error) {
if err != nil {
panic(err)
}
}
func Must2(i interface{}, err error) interface{} {
if err != nil {
panic(err)
}
return i
}
//获得某一天0点的时间戳
func GetDaysAgoZeroTime(day int) int64 {
date := time.Now().AddDate(0, 0, day).Format("2006-01-02")
t, _ := time.Parse("2006-01-02", date)
return t.Unix()
}
//时间戳转人可读
func TimeToHuman(target int) string {
var res = ""
if target == 0 {
return res
}
t := int(time.Now().Unix()) - target
data := [7]map[string]interface{}{
{"key": 31536000, "value": "年"},
{"key": 2592000, "value": "个月"},
{"key": 604800, "value": "星期"},
{"key": 86400, "value": "天"},
{"key": 3600, "value": "小时"},
{"key": 60, "value": "分钟"},
{"key": 1, "value": "秒"},
}
for _, v := range data {
var c = t / v["key"].(int)
if 0 != c {
res = strconv.Itoa(c) + v["value"].(string) + "前"
break
}
}
return res
}
//结构体转map
func StructToMap(obj interface{}) map[string]interface{} {
obj1 := reflect.TypeOf(obj)
obj2 := reflect.ValueOf(obj)
var data = make(map[string]interface{})
for i := 0; i < obj1.NumField(); i++ {
data[strings.ToLower(obj1.Field(i).Name)] = obj2.Field(i).Interface()
}
return data
}
//在字符串中查找指定字串,并返回left或right部分
func Substr(str string, target string, turn string, hasPos bool) string {
pos := strings.Index(str, target)
if pos == -1 {
return ""
}
if turn == "left" {
if hasPos == true {
pos = pos + 1
}
return str[:pos]
} else if turn == "right" {
if hasPos == false {
pos = pos + 1
}
return str[pos:]
} else {
panic("params 3 error")
}
}
//获得当前绝对路径
func GetCurrentDirectory() string {
dir, err := filepath.Abs(filepath.Dir(os.Args[0])) //返回绝对路径 filepath.Dir(os.Args[0])去除最后一个元素的路径
if err != nil {
log.Fatal(err)
}
return strings.Replace(dir, "\\", "/", -1) //将\替换成/
}
//url的path转文件名
func UriToFilePathByDate(uriPath string, dir string) string {
pathArr := strings.Split(uriPath, "/")
fileName := strings.Join(pathArr, "-")
writePath := CreateDateDir(dir, "") //根据时间检测是否存在目录,不存在创建
writePath = RightAddPathPos(writePath)
fileName = path.Join(writePath, fileName[1:len(fileName)]+".log")
return fileName
}
//检测并补全路径左边的反斜杠
func LeftAddPathPos(path string) string {
if path[:0] != "/" {
path = "/" + path
}
return path
}
//检测并补全路径右边的反斜杠
func RightAddPathPos(path string) string {
if path[len(path)-1:len(path)] != "/" {
path = path + "/"
}
return path
}
//根据当天日期和给定dir返回log文件名路径
func FileNameByDate(dir string) string {
fileName := time.Now().Format("2006-01-02")
dir = RightAddPathPos(dir)
return dir + fileName + ".log"
}
//uri转log路径
func UriToFilePath(uri string, dir string) string {
pathArr := strings.Split(uri, "/")
fileName := strings.Join(pathArr, "-")
fileName = path.Join(dir, fileName[1:len(fileName)]+".log")
if fileName[len(fileName)-1:len(fileName)] != "/" {
fileName = fileName + "/"
}
return fileName
}
//uri转log文件名
func UriToFileName(uri string) string {
pathArr := strings.Split(uri, "/")
fileName := strings.Join(pathArr, "-")
fileName = fileName + ".log"
return fileName
}
func LogByUrl(fullUrl string) string {
u, err := url.Parse(fullUrl)
if err != nil {
panic(err)
}
pathArr := strings.Split(u.Path, "/")
fileName := strings.Join(pathArr, "-")
writePath := "/tmp/logs/2020-01-12"
fileName = path.Join(writePath, fileName[1:len(fileName)]+".log")
return fileName
}
//根据当前日期,不存在则创建目录
func CreateDateDir(Path string, prex string) string {
folderName := time.Now().Format("20060102")
if prex != "" {
folderName = prex + folderName
}
folderPath := filepath.Join(Path, folderName)
if _, err := os.Stat(folderPath); os.IsNotExist(err) {
// 必须分成两步:先创建文件夹、再修改权限
os.Mkdir(folderPath, 0777) //0777也可以os.ModePerm
os.Chmod(folderPath, 0777)
}
return folderPath
}
//使用io.WriteString()函数进行数据的写入,不存在则创建
func WriteWithIo(filePath, content string) error {
//os.O_WRONLY | os.O_CREATE | O_EXCL 【如果已经存在,则失败】
//os.O_WRONLY | os.O_CREATE 【如果已经存在,会覆盖写,不会清空原来的文件,而是从头直接覆盖写】
//os.O_WRONLY | os.O_CREATE | os.O_APPEND 【如果已经存在,则在尾部添加写】
fileObj, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0777)
if err != nil {
fmt.Println("Failed to open the file", err.Error())
return err
}
if content != "" {
if _, err := io.WriteString(fileObj, content); err == nil {
fmt.Println("Successful appending to the file with os.OpenFile and io.WriteString.", content)
return nil
}
return err
}
return nil
}
/*func StructToByte(tmp struct{}){
tmp := &Test{Name: "why", Age: 34, Id: 1}
length := unsafe.Sizeof(tmp)
data := &SliceMock{
addr: uintptr(unsafe.Pointer(tmp)),
cap : int(length),
len : int(length),
}
ret := *(*[]byte)(unsafe.Pointer(data))
}*/
//断言
func Assertion(data interface{}) interface{} {
switch data.(type) {
case string:
return data.(string)
case int:
return data.(int)
case int8:
return data.(int8)
case int32:
return data.(int32)
case int64:
return data.(int64)
case float32:
return data.(float32)
case float64:
return data.(float64)
default:
return data
}
return nil
}
//发邮件
func SendMail(mailTo string, subject string, body string) error {
m := gomail.NewMessage()
//设置发件人
m.SetHeader("From", "444216978@qq.com")
//设置发送给多个用户
mailArrTo := strings.Split(mailTo, ",")
m.SetHeader("To", mailArrTo...)
//设置邮件主题
m.SetHeader("Subject", subject)
//设置邮件正文
m.SetBody("text/html", body)
d := gomail.NewDialer("email.qq.com", 587, "444216978@qq.com", "oxlqpamltwqibieg")
err := d.DialAndSend(m)
if err != nil {
fmt.Println(err)
}
return err
}
//json转map数组
func JsonToMapArray(data string) []map[string]interface{} {
var res []map[string]interface{}
if data == "" {
return res
}
err := json.Unmarshal([]byte(data), &res)
Must(err)
return res
}
//json转map
func JsonToMap(data string) map[string]interface{} {
var res map[string]interface{}
if data == "" {
return res
}
err := json.Unmarshal([]byte(data), &res)
Must(err)
return res
}
func BytesToString(b *[]byte) *string {
s := bytes.NewBuffer(*b)
r := s.String()
return &r
}
func ExternalIP() (string, error) {
iFaces, err := net.Interfaces()
if err != nil {
return "", err
}
for _, iFace := range iFaces {
if iFace.Flags&net.FlagUp == 0 {
continue // interface down
}
if iFace.Flags&net.FlagLoopback != 0 {
continue // loopback interface
}
addrs, err := iFace.Addrs()
if err != nil {
return "", err
}
for _, addr := range addrs {
var ip net.IP
switch v := addr.(type) {
case *net.IPNet:
ip = v.IP
case *net.IPAddr:
ip = v.IP
}
if ip == nil || ip.IsLoopback() {
continue
}
ip = ip.To4()
if ip == nil {
continue // not an ipv4 address
}
return ip.String(), nil
}
}
return "", errors.New("are you connected to the network?")
}
//获得本机名
func HostName() string {
hostNamePrefix := ""
host, err := os.Hostname()
Must(err)
if err == nil {
parts := strings.SplitN(host, ".", 2)
if len(parts) > 0 {
hostNamePrefix = parts[0]
}
}
return hostNamePrefix
}
/*
slice test code:
i := 1
a := []int{1, 2, 3}
fmt.Println(a)
res, err := util.InsertSliceByIndex(a , i, 9)
util.Must(err)
data := res.([]int)
fmt.Println(data)
res, err = util.DeleteSliceByPos(data, i)
util.Must(err)
data = res.([]int)
fmt.Println(data)
res, err = util.UpdateSliceByIndex(data, i , 6)
util.Must(err)
data = res.([]int)
fmt.Println(data)
*/
func DeleteSliceByPos(slice interface{}, index int) (interface{}, error) {
v := reflect.ValueOf(slice)
if v.Kind() != reflect.Slice {
return slice, errors.New("not slice")
}
if v.Len() == 0 || index < 0 || index > v.Len()-1 {
return slice, errors.New("index error")
}
return reflect.AppendSlice(v.Slice(0, index), v.Slice(index+1, v.Len())).Interface(), nil
}
func InsertSliceByIndex(slice interface{}, index int, value interface{}) (interface{}, error) {
v := reflect.ValueOf(slice)
if v.Kind() != reflect.Slice {
return slice, errors.New("not slice")
}
if index < 0 || index > v.Len() || reflect.TypeOf(slice).Elem() != reflect.TypeOf(value) {
return slice, errors.New("index error")
}
if index == v.Len() {
return reflect.Append(v, reflect.ValueOf(value)).Interface(), nil
}
v = reflect.AppendSlice(v.Slice(0, index+1), v.Slice(index, v.Len()))
v.Index(index).Set(reflect.ValueOf(value))
return v.Interface(), nil
}
func UpdateSliceByIndex(slice interface{}, index int, value interface{}) (interface{}, error) {
v := reflect.ValueOf(slice)
if v.Kind() != reflect.Slice {
return slice, errors.New("not slice")
}
if index > v.Len()-1 || reflect.TypeOf(slice).Elem() != reflect.TypeOf(value) {
return slice, errors.New("index error")
}
v.Index(index).Set(reflect.ValueOf(value))
return v.Interface(), nil
}
//备忘:切片指定位置插入和删除原理
func sliceInsertAndDelete() {
//insert
data := []int{1, 2, 3, 4, 5}
left := data[:3]
right := data[3:]
tmp := append([]int{}, left...)
tmp = append(tmp, 0)
res := append(tmp, right...)
fmt.Println(res)
//delete
data = []int{1, 2, 3, 4, 5}
left = data[:3]
right = data[3+1:]
res = append(left, right...)
fmt.Println(res)
}