You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

447 lines
9.6 KiB

  1. package utils
  2. import (
  3. "errors"
  4. "fmt"
  5. "github.com/lianggx6/goutf16"
  6. "io"
  7. "math/rand"
  8. "net/http"
  9. "os"
  10. "path"
  11. "path/filepath"
  12. "reflect"
  13. "regexp"
  14. "runtime"
  15. "strconv"
  16. "strings"
  17. "sync"
  18. "syscall"
  19. "time"
  20. "unsafe"
  21. )
  22. type HWND uintptr
  23. const (
  24. ERROR_FILE_NOT_FOUND = 2
  25. ERROR_PATH_NOT_FOUND = 3
  26. ERROR_BAD_FORMAT = 11
  27. )
  28. const (
  29. SE_ERR_ACCESSDENIED = 5
  30. SE_ERR_OOM = 8
  31. SE_ERR_DLLNOTFOUND = 32
  32. SE_ERR_SHARE = 26
  33. SE_ERR_ASSOCINCOMPLETE = 27
  34. SE_ERR_DDETIMEOUT = 28
  35. SE_ERR_DDEFAIL = 29
  36. SE_ERR_DDEBUSY = 30
  37. SE_ERR_NOASSOC = 31
  38. )
  39. var (
  40. modshell32 = syscall.NewLazyDLL("shell32.dll")
  41. procShellExecute = modshell32.NewProc("ShellExecuteW")
  42. )
  43. // 判断文件夹是否存在
  44. func PathExists(path string) (bool, error) {
  45. var err error
  46. if _, err = os.Stat(path); err == nil {
  47. return true, nil
  48. }
  49. if os.IsNotExist(err) {
  50. return false, nil
  51. }
  52. return false, err
  53. }
  54. // 用b的所有字段覆盖a的
  55. // 如果fields不为空, 表示用b的特定字段覆盖a的
  56. // a应该为结构体指针
  57. func CopyFields(a interface{}, b interface{}, fields ...string) (err error) {
  58. at := reflect.TypeOf(a)
  59. av := reflect.ValueOf(a)
  60. bt := reflect.TypeOf(b)
  61. bv := reflect.ValueOf(b)
  62. // 简单判断下
  63. if at.Kind() != reflect.Ptr {
  64. err = fmt.Errorf("a must be a struct pointer")
  65. return
  66. }
  67. av = reflect.ValueOf(av.Interface())
  68. // 要复制哪些字段
  69. _fields := make([]string, 0)
  70. if len(fields) > 0 {
  71. _fields = fields
  72. } else {
  73. for i := 0; i < bv.NumField(); i++ {
  74. _fields = append(_fields, bt.Field(i).Name)
  75. }
  76. }
  77. if len(_fields) == 0 {
  78. fmt.Println("no fields to copy")
  79. return
  80. }
  81. // 复制
  82. for i := 0; i < len(_fields); i++ {
  83. name := _fields[i]
  84. f := av.Elem().FieldByName(name)
  85. bValue := bv.FieldByName(name)
  86. // a中有同名的字段并且类型一致才复制
  87. if f.IsValid() && f.Kind() == bValue.Kind() {
  88. f.Set(bValue)
  89. } else {
  90. //fmt.Printf("no such field or different kind, fieldName: %s\n", name)
  91. }
  92. }
  93. return
  94. }
  95. //获取默认打印机
  96. func GetDefaultPrinterName() (string, []uint16) {
  97. var (
  98. dll = syscall.MustLoadDLL("winspool.drv")
  99. getDefaultPrinter = dll.MustFindProc("GetDefaultPrinterW")
  100. pn [256]uint16
  101. )
  102. plen := len(pn)
  103. getDefaultPrinter.Call(uintptr(unsafe.Pointer(&pn)), uintptr(unsafe.Pointer(&plen)))
  104. printerName := syscall.UTF16ToString(pn[:])
  105. printer16 := goutf16.EncodeStringToUTF16(printerName)
  106. return printerName, printer16
  107. }
  108. // 设置默认打印机
  109. func SetDefaultPrinter(printerName string) error {
  110. var (
  111. dll = syscall.MustLoadDLL("winspool.drv")
  112. setDefaultPrinter = dll.MustFindProc("SetDefaultPrinterW")
  113. p []uint16
  114. pn [256]uint16
  115. )
  116. p = goutf16.EncodeStringToUTF16(printerName)
  117. pn = UintSliceTo256Uint(p)
  118. ret, _, msg := setDefaultPrinter.Call(uintptr(unsafe.Pointer(&pn)))
  119. if ret == 0 {
  120. return msg
  121. }
  122. return nil
  123. }
  124. func Uint16ToBytes(n uint16) []byte {
  125. return []byte{
  126. byte(n),
  127. byte(n >> 8),
  128. }
  129. }
  130. func BytesToUint16(array []byte) uint16 {
  131. var data uint16 = 0
  132. for i := 0; i < len(array); i++ {
  133. data = data + uint16(uint(array[i])<<uint(8*i))
  134. }
  135. return data
  136. }
  137. func UintSliceTo256Uint(us []uint16) (res [256]uint16) {
  138. var i int
  139. for i = 0; i < len(us); i++ {
  140. res[i] = us[i]
  141. }
  142. return res
  143. }
  144. func GetExcelCellIntPos(pos string) (row, col int, err error) {
  145. var (
  146. chareg, numreg *regexp.Regexp
  147. cha, num [][]string
  148. i int
  149. uc []rune
  150. rowstr string
  151. )
  152. chareg = regexp.MustCompile("[a-zA-Z]")
  153. numreg = regexp.MustCompile("[0-9]")
  154. cha = chareg.FindAllStringSubmatch(pos, -1)
  155. num = numreg.FindAllStringSubmatch(pos, -1)
  156. // 获取字符的列值
  157. col = 0
  158. for i = 0; i < len(cha); i++ {
  159. uc = []rune(strings.ToUpper(cha[i][0]))
  160. col = col + i*26 + (int(uc[0]) - 65)
  161. }
  162. // 获取行值
  163. for i = 0; i < len(num); i++ {
  164. rowstr = rowstr + num[i][0]
  165. }
  166. row, _ = strconv.Atoi(rowstr)
  167. return row - 1, col, nil
  168. }
  169. func ShellExecute(hwnd HWND, lpOperation, lpFile, lpParameters, lpDirectory string, nShowCmd int) error {
  170. var op, param, directory uintptr
  171. if len(lpOperation) != 0 {
  172. op = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpOperation)))
  173. }
  174. if len(lpParameters) != 0 {
  175. param = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpParameters)))
  176. }
  177. if len(lpDirectory) != 0 {
  178. directory = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpDirectory)))
  179. }
  180. ret, _, _ := procShellExecute.Call(
  181. uintptr(hwnd),
  182. op,
  183. uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpFile))),
  184. param,
  185. directory,
  186. uintptr(nShowCmd))
  187. errorMsg := ""
  188. if ret != 0 && ret <= 32 {
  189. switch int(ret) {
  190. case ERROR_FILE_NOT_FOUND:
  191. errorMsg = "The specified file was not found."
  192. case ERROR_PATH_NOT_FOUND:
  193. errorMsg = "The specified path was not found."
  194. case ERROR_BAD_FORMAT:
  195. errorMsg = "The .exe file is invalid (non-Win32 .exe or error in .exe image)."
  196. case SE_ERR_ACCESSDENIED:
  197. errorMsg = "The operating system denied access to the specified file."
  198. case SE_ERR_ASSOCINCOMPLETE:
  199. errorMsg = "The file name association is incomplete or invalid."
  200. case SE_ERR_DDEBUSY:
  201. errorMsg = "The DDE transaction could not be completed because other DDE transactions were being processed."
  202. case SE_ERR_DDEFAIL:
  203. errorMsg = "The DDE transaction failed."
  204. case SE_ERR_DDETIMEOUT:
  205. errorMsg = "The DDE transaction could not be completed because the request timed out."
  206. case SE_ERR_DLLNOTFOUND:
  207. errorMsg = "The specified DLL was not found."
  208. case SE_ERR_NOASSOC:
  209. errorMsg = "There is no application associated with the given file name extension. This error will also be returned if you attempt to print a file that is not printable."
  210. case SE_ERR_OOM:
  211. errorMsg = "There was not enough memory to complete the operation."
  212. case SE_ERR_SHARE:
  213. errorMsg = "A sharing violation occurred."
  214. default:
  215. errorMsg = fmt.Sprintf("Unknown error occurred with error code %v", ret)
  216. }
  217. } else {
  218. return nil
  219. }
  220. return errors.New(errorMsg)
  221. }
  222. // RandNumber 生成min - max之间的随机数
  223. // 如果min大于max, panic
  224. func RandNumber(min, max int) int {
  225. r := rand.New(rand.NewSource(time.Now().UnixNano()))
  226. switch {
  227. case min == max:
  228. return min
  229. case min > max:
  230. panic("min must be less than or equal to max")
  231. }
  232. return min + r.Intn(max-min)
  233. }
  234. // PanicToError Panic转换为error
  235. func PanicToError(f func()) (err error) {
  236. defer func() {
  237. if e := recover(); e != nil {
  238. err = fmt.Errorf(PanicTrace(e))
  239. }
  240. }()
  241. f()
  242. return
  243. }
  244. // PanicTrace panic调用链跟踪
  245. func PanicTrace(err interface{}) string {
  246. stackBuf := make([]byte, 4096)
  247. n := runtime.Stack(stackBuf, false)
  248. return fmt.Sprintf("panic: %v %s", err, stackBuf[:n])
  249. }
  250. // DownloadFile 文件下载
  251. func DownloadFile(filePath string, rw http.ResponseWriter) error {
  252. file, err := os.Open(filePath)
  253. if err != nil {
  254. return err
  255. }
  256. filename := path.Base(filePath)
  257. rw.Header().Set("Content-Type", "application/octet-stream")
  258. rw.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, filename))
  259. _, err = io.Copy(rw, file)
  260. return err
  261. }
  262. // WorkDir 获取程序运行时根目录
  263. func WorkDir() (string, error) {
  264. execPath, err := os.Executable()
  265. if err != nil {
  266. return "", err
  267. }
  268. wd := filepath.Dir(execPath)
  269. if filepath.Base(wd) == "bin" {
  270. wd = filepath.Dir(wd)
  271. }
  272. return wd, nil
  273. }
  274. // WaitGroupWrapper waitGroup包装
  275. type WaitGroupWrapper struct {
  276. sync.WaitGroup
  277. }
  278. // Wrap 包装Add, Done方法
  279. func (w *WaitGroupWrapper) Wrap(f func()) {
  280. w.Add(1)
  281. go func() {
  282. defer w.Done()
  283. f()
  284. }()
  285. }
  286. // 生成长度为length的随机字符串
  287. func RandString(length int64) string {
  288. sources := []byte("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
  289. var result []byte
  290. r := rand.New(rand.NewSource(time.Now().UnixNano()))
  291. sourceLength := len(sources)
  292. var i int64 = 0
  293. for ; i < length; i++ {
  294. result = append(result, sources[r.Intn(sourceLength)])
  295. }
  296. return string(result)
  297. }
  298. // 批量替换字符串
  299. func ReplaceStrings(s string, old []string, replace []string) string {
  300. if s == "" {
  301. return s
  302. }
  303. if len(old) != len(replace) {
  304. return s
  305. }
  306. for i, v := range old {
  307. s = strings.Replace(s, v, replace[i], 1000)
  308. }
  309. return s
  310. }
  311. func InStringSlice(slice []string, element string) bool {
  312. element = strings.TrimSpace(element)
  313. for _, v := range slice {
  314. if strings.TrimSpace(v) == element {
  315. return true
  316. }
  317. }
  318. return false
  319. }
  320. // 转义json特殊字符
  321. func EscapeJson(s string) string {
  322. specialChars := []string{"\\", "\b", "\f", "\n", "\r", "\t", "\""}
  323. replaceChars := []string{"\\\\", "\\b", "\\f", "\\n", "\\r", "\\t", "\\\""}
  324. return ReplaceStrings(s, specialChars, replaceChars)
  325. }
  326. // 判断文件是否存在及是否有权限访问
  327. func FileExist(file string) bool {
  328. _, err := os.Stat(file)
  329. if os.IsNotExist(err) {
  330. return false
  331. }
  332. if os.IsPermission(err) {
  333. return false
  334. }
  335. return true
  336. }
  337. func Max(vals ...int) int {
  338. var max int
  339. for _, val := range vals {
  340. if val > max {
  341. max = val
  342. }
  343. }
  344. return max
  345. }
  346. func Min(vals ...int) int {
  347. var min int
  348. for _, val := range vals {
  349. if min == 0 || val <= min {
  350. min = val
  351. }
  352. }
  353. return min
  354. }
  355. func MaxTime(vals ...time.Time) time.Time {
  356. var max time.Time
  357. if len(vals) > 0 {
  358. max = vals[0]
  359. }else{
  360. // 默认返回一年前的时间
  361. return time.Now().Add(24*265*time.Second)
  362. }
  363. for _, val := range vals {
  364. if val.Unix() > max.Unix() {
  365. max = val
  366. }
  367. }
  368. return max
  369. }
  370. func MinTime(vals ...time.Time) time.Time {
  371. var min time.Time
  372. if len(vals) > 0 {
  373. min = vals[0]
  374. }else{
  375. // 默认返回一年前的时间
  376. return time.Now().Add(24*265*time.Second)
  377. }
  378. for _, val := range vals {
  379. if val.Unix() <= min.Unix() {
  380. min = val
  381. }
  382. }
  383. return min
  384. }