mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-09 07:02:29 +08:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4959f26003 | ||
|
|
eb683a33d2 | ||
|
|
0e63489e9e | ||
|
|
d9e318550a | ||
|
|
993b0e6023 | ||
|
|
7cf358a0ec | ||
|
|
b85545c584 | ||
|
|
c3c6c92cd4 | ||
|
|
8587abc977 | ||
|
|
5c01b7e675 | ||
|
|
0247ac232a | ||
|
|
e77354d7ff | ||
|
|
8998dc35bb | ||
|
|
ad9fd196ce | ||
|
|
c8a65c33a4 | ||
|
|
69a797f8ed | ||
|
|
1e5b69e9bf | ||
|
|
275abcc8c2 | ||
|
|
065b3b84fe | ||
|
|
4bc43f3278 | ||
|
|
f3382ceac9 | ||
|
|
d20f8783b2 | ||
|
|
8432a4e1ee |
27
README.md
27
README.md
@@ -4,7 +4,7 @@
|
||||
<br/>
|
||||
|
||||

|
||||
[](https://github.com/duke-git/lancet/releases)
|
||||
[](https://github.com/duke-git/lancet/releases)
|
||||
[](https://pkg.go.dev/github.com/duke-git/lancet)
|
||||
[](https://goreportcard.com/report/github.com/duke-git/lancet)
|
||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||
@@ -100,6 +100,9 @@ import "github.com/duke-git/lancet/convertor"
|
||||
- [DecodeByte](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#DecodeByte)
|
||||
- [DeepClone](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#DeepClone)
|
||||
- [CopyProperties](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#CopyProperties)
|
||||
- [ToInterface](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#ToInterface)
|
||||
- [Utf8ToGbk](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#Utf8ToGbk)
|
||||
- [GbkToUtf8](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#GbkToUtf8)
|
||||
|
||||
### 3. Cryptor package is for data encryption and decryption.
|
||||
|
||||
@@ -130,14 +133,24 @@ import "github.com/duke-git/lancet/cryptor"
|
||||
- [DesOfbEncrypt](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#DesOfbEncrypt)
|
||||
- [DesOfbDecrypt](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#DesOfbDecrypt)
|
||||
- [HmacMd5](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#HmacMd5)
|
||||
- [HmacMd5WithBase64](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#HmacMd5WithBase64)
|
||||
- [HmacSha1](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#HmacSha1)
|
||||
- [HmacSha1WithBase64](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#HmacSha1WithBase64)
|
||||
- [HmacSha256](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#HmacSha256)
|
||||
- [HmacSha256WithBase64](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#HmacSha256WithBase64)
|
||||
- [HmacSha512](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#HmacSha512)
|
||||
- [HmacSha512WithBase64](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#HmacSha512WithBase64)
|
||||
- [Md5String](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#Md5String)
|
||||
- [Md5StringWithBase64](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#Md5StringWithBase64)
|
||||
- [Md5Byte](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#Md5Byte)
|
||||
- [Md5ByteWithBase64](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#Md5ByteWithBase64)
|
||||
- [Md5File](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#Md5File)
|
||||
- [Sha1](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#Sha1)
|
||||
- [Sha1WithBase64](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#Sha1WithBase64)
|
||||
- [Sha256](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#Sha256)
|
||||
- [Sha256WithBase64](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#Sha256WithBase64)
|
||||
- [Sha512](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#Sha512)
|
||||
- [Sha512WithBase64](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#Sha512WithBase64)
|
||||
- [GenerateRsaKey](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#GenerateRsaKey)
|
||||
- [RsaEncrypt](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#RsaEncrypt)
|
||||
- [RsaDecrypt](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#RsaDecrypt)
|
||||
@@ -185,6 +198,11 @@ import "github.com/duke-git/lancet/datetime"
|
||||
- [BetweenSeconds](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#BetweenSeconds)
|
||||
- [DayOfYear](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#DayOfYear)
|
||||
- [IsWeekend](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#IsWeekend)
|
||||
- [NowDateOrTime](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#NowDateOrTime)
|
||||
- [Timestamp](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#Timestamp)
|
||||
- [TimestampMilli](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#TimestampMilli)
|
||||
- [TimestampMicro](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#TimestampMicro)
|
||||
- [TimestampNano](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#TimestampNano)
|
||||
|
||||
### 5. Fileutil package implements some basic functions for file operations.
|
||||
|
||||
@@ -208,6 +226,7 @@ import "github.com/duke-git/lancet/fileutil"
|
||||
- [ReadFileToString](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#ReadFileToString)
|
||||
- [ReadFileByLine](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#ReadFileByLine)
|
||||
- [Zip](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#Zip)
|
||||
- [ZipAppendEntry](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#ZipAppendEntry)
|
||||
- [UnZip](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#UnZip)
|
||||
- [CurrentPath](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#CurrentPath)
|
||||
- [IsZipFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#IsZipFile)
|
||||
@@ -215,6 +234,7 @@ import "github.com/duke-git/lancet/fileutil"
|
||||
- [MTime](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#MTime)
|
||||
- [Sha](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#Sha)
|
||||
- [ReadCsvFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#ReadCsvFile)
|
||||
- [WriteCsvFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#WriteCsvFile)
|
||||
- [WriteStringToFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#WriteStringToFile)
|
||||
- [WriteBytesToFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#WriteBytesToFile)
|
||||
|
||||
@@ -275,6 +295,7 @@ import "github.com/duke-git/lancet/mathutil"
|
||||
- [LCM](https://github.com/duke-git/lancet/blob/v1/docs/mathutil.md#LCM)
|
||||
- [Cos](https://github.com/duke-git/lancet/blob/v1/docs/mathutil.md#Cos)
|
||||
- [Sin](https://github.com/duke-git/lancet/blob/v1/docs/mathutil.md#Sin)
|
||||
- [Log](https://github.com/duke-git/lancet/blob/v1/docs/mathutil.md#Log)
|
||||
|
||||
### 9. Netutil package contains functions to get net information and send http request.
|
||||
|
||||
@@ -320,6 +341,7 @@ import "github.com/duke-git/lancet/random"
|
||||
- [RandNumeral](https://github.com/duke-git/lancet/blob/v1/docs/random.md#RandNumeral)
|
||||
- [RandNumeralOrLetter](https://github.com/duke-git/lancet/blob/v1/docs/random.md#RandNumeralOrLetter)
|
||||
- [UUIdV4](https://github.com/duke-git/lancet/blob/v1/docs/random.md#UUIdV4)
|
||||
- [RandUniqueIntSlice](https://github.com/duke-git/lancet/blob/v1/docs/random.md#RandUniqueIntSlice)
|
||||
|
||||
### 11. Retry package is for executing a function repeatedly until it was successful or canceled by the context.
|
||||
|
||||
@@ -383,6 +405,7 @@ import "github.com/duke-git/lancet/slice"
|
||||
- [Union](https://github.com/duke-git/lancet/blob/v1/docs/slice.md#Union)
|
||||
- [UpdateByIndex](https://github.com/duke-git/lancet/blob/v1/docs/slice.md#UpdateByIndex)
|
||||
- [Without](https://github.com/duke-git/lancet/blob/v1/docs/slice.md#Without)
|
||||
- [Join](https://github.com/duke-git/lancet/blob/v1/docs/slice.md#Join)
|
||||
|
||||
### 13. Strutil package contains some functions to manipulate string.
|
||||
|
||||
@@ -427,7 +450,7 @@ import "github.com/duke-git/lancet/strutil"
|
||||
- [Trim](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#Trim)
|
||||
- [SplitAndTrim](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#SplitAndTrim)
|
||||
- [HideString](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#HideString)
|
||||
|
||||
- [RemoveWhiteSpace](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#RemoveWhiteSpace)
|
||||
### 14. System package contain some functions about os, runtime, shell command.
|
||||
|
||||
```go
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<br/>
|
||||
|
||||

|
||||
[](https://github.com/duke-git/lancet/releases)
|
||||
[](https://github.com/duke-git/lancet/releases)
|
||||
[](https://pkg.go.dev/github.com/duke-git/lancet)
|
||||
[](https://goreportcard.com/report/github.com/duke-git/lancet)
|
||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||
@@ -99,7 +99,9 @@ import "github.com/duke-git/lancet/convertor"
|
||||
- [DecodeByte](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#DecodeByte)
|
||||
- [DeepClone](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#DeepClone)
|
||||
- [CopyProperties](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#CopyProperties)
|
||||
|
||||
- [ToInterface](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#ToInterface)
|
||||
- [Utf8ToGbk](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#Utf8ToGbk)
|
||||
- [GbkToUtf8](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#GbkToUtf8)
|
||||
### 3. cryptor 加密包支持数据加密和解密,获取 md5,hash 值。支持 base64, md5, hmac, aes, des, rsa。
|
||||
|
||||
```go
|
||||
@@ -129,14 +131,25 @@ import "github.com/duke-git/lancet/cryptor"
|
||||
- [DesOfbEncrypt](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#DesOfbEncrypt)
|
||||
- [DesOfbDecrypt](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#DesOfbDecrypt)
|
||||
- [HmacMd5](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#HmacMd5)
|
||||
- [HmacMd5WithBase64](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#HmacMd5WithBase64)
|
||||
md#HmacSha256WithBase64)
|
||||
- [HmacSha1](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#HmacSha1)
|
||||
- [HmacSha256](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#HmacSha256)
|
||||
- [HmacSha1WithBase64](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#HmacSha1WithBase64)
|
||||
- [HmacSha256](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#HmacSha256)
|
||||
- [HmacSha256WithBase64](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#HmacSha256WithBase64)
|
||||
- [HmacSha512](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#HmacSha512)
|
||||
- [HmacSha512WithBase64](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#HmacSha512WithBase64)
|
||||
- [Md5String](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#Md5String)
|
||||
- [Md5StringWithBase64](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#Md5StringWithBase64)
|
||||
- [Md5Byte](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#Md5Byte)
|
||||
- [Md5ByteWithBase64](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#Md5ByteWithBase64)
|
||||
- [Md5File](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#Md5File)
|
||||
- [Sha1](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#Sha1)
|
||||
- [Sha1WithBase64](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#Sha1WithBase64)
|
||||
- [Sha256](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#Sha256)
|
||||
- [Sha256WithBase64](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#Sha256WithBase64)
|
||||
- [Sha512](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#Sha512)
|
||||
- [Sha512WithBase64](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#Sha512WithBase64)
|
||||
- [GenerateRsaKey](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#GenerateRsaKey)
|
||||
- [RsaEncrypt](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#RsaEncrypt)
|
||||
- [RsaDecrypt](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#RsaDecrypt)
|
||||
@@ -184,6 +197,11 @@ import "github.com/duke-git/lancet/datetime"
|
||||
- [BetweenSeconds](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#BetweenSeconds)
|
||||
- [DayOfYear](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#DayOfYear)
|
||||
- [IsWeekend](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#IsWeekend)
|
||||
- [NowDateOrTime](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#NowDateOrTime)
|
||||
- [Timestamp](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#Timestamp)
|
||||
- [TimestampMilli](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#TimestampMilli)
|
||||
- [TimestampMicro](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#TimestampMicro)
|
||||
- [TimestampNano](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#TimestampNano)
|
||||
|
||||
### 5. fileutil 包支持文件基本操作。
|
||||
|
||||
@@ -207,6 +225,7 @@ import "github.com/duke-git/lancet/fileutil"
|
||||
- [ReadFileToString](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#ReadFileToString)
|
||||
- [ReadFileByLine](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#ReadFileByLine)
|
||||
- [Zip](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#Zip)
|
||||
- [ZipAppendEntry](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#ZipAppendEntry)
|
||||
- [UnZip](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#UnZip)
|
||||
- [CurrentPath](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#CurrentPath)
|
||||
- [IsZipFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#IsZipFile)
|
||||
@@ -214,6 +233,7 @@ import "github.com/duke-git/lancet/fileutil"
|
||||
- [MTime](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#MTime)
|
||||
- [Sha](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#Sha)
|
||||
- [ReadCsvFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#ReadCsvFile)
|
||||
- [WriteCsvFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#WriteCsvFile)
|
||||
- [WriteStringToFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#WriteStringToFile)
|
||||
- [WriteBytesToFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#WriteBytesToFile)
|
||||
|
||||
@@ -274,7 +294,7 @@ import "github.com/duke-git/lancet/mathutil"
|
||||
- [LCM](https://github.com/duke-git/lancet/blob/v1/docs/mathutil_zh-CN.md#LCM)
|
||||
- [Cos](https://github.com/duke-git/lancet/blob/v1/docs/mathutil_zh-CN.md#Cos)
|
||||
- [Sin](https://github.com/duke-git/lancet/blob/v1/docs/mathutil_zh-CN.md#Sin)
|
||||
|
||||
- [Log](https://github.com/duke-git/lancet/blob/v1/docs/mathutil_zh-CN.md#Log)
|
||||
### 9. netutil 网络包支持获取 ip 地址,发送 http 请求。
|
||||
|
||||
```go
|
||||
@@ -319,6 +339,7 @@ import "github.com/duke-git/lancet/random"
|
||||
- [RandNumeral](https://github.com/duke-git/lancet/blob/v1/docs/random_zh-CN.md#RandNumeral)
|
||||
- [RandNumeralOrLetter](https://github.com/duke-git/lancet/blob/v1/docs/random_zh-CN.md#RandNumeralOrLetter)
|
||||
- [UUIdV4](https://github.com/duke-git/lancet/blob/v1/docs/random.md#UUIdV4)
|
||||
- [RandUniqueIntSlice](https://github.com/duke-git/lancet/blob/v1/docs/random.md#RandUniqueIntSlice)
|
||||
|
||||
### 11. retry 重试执行函数直到函数运行成功或被 context cancel。
|
||||
|
||||
@@ -382,6 +403,7 @@ import "github.com/duke-git/lancet/slice"
|
||||
- [Union](https://github.com/duke-git/lancet/blob/v1/docs/slice_zh-CN.md#Union)
|
||||
- [UpdateByIndex](https://github.com/duke-git/lancet/blob/v1/docs/slice_zh-CN.md#UpdateByIndex)
|
||||
- [Without](https://github.com/duke-git/lancet/blob/v1/docs/slice_zh-CN.md#Without)
|
||||
- [Join](https://github.com/duke-git/lancet/blob/v1/docs/slice_zh-CN.md#Join)
|
||||
|
||||
### 13. strutil 包含处理字符串的相关函数。
|
||||
|
||||
@@ -426,6 +448,7 @@ import "github.com/duke-git/lancet/strutil"
|
||||
- [Trim](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#Trim)
|
||||
- [SplitAndTrim](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#SplitAndTrim)
|
||||
- [HideString](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#HideString)
|
||||
- [RemoveWhiteSpace](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#RemoveWhiteSpace)
|
||||
|
||||
### 14. system 包含 os, runtime, shell command 相关函数。
|
||||
|
||||
|
||||
@@ -11,11 +11,15 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/text/encoding/simplifiedchinese"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// ToBool convert string to a boolean
|
||||
@@ -78,33 +82,45 @@ func ToChar(s string) []string {
|
||||
|
||||
// ToString convert value to string
|
||||
func ToString(value interface{}) string {
|
||||
res := ""
|
||||
if value == nil {
|
||||
return res
|
||||
return ""
|
||||
}
|
||||
|
||||
v := reflect.ValueOf(value)
|
||||
|
||||
switch value.(type) {
|
||||
case float32, float64:
|
||||
res = strconv.FormatFloat(v.Float(), 'f', -1, 64)
|
||||
return res
|
||||
case int, int8, int16, int32, int64:
|
||||
res = strconv.FormatInt(v.Int(), 10)
|
||||
return res
|
||||
case uint, uint8, uint16, uint32, uint64:
|
||||
res = strconv.FormatUint(v.Uint(), 10)
|
||||
return res
|
||||
switch val := value.(type) {
|
||||
case float32:
|
||||
return strconv.FormatFloat(float64(val), 'f', -1, 32)
|
||||
case float64:
|
||||
return strconv.FormatFloat(val, 'f', -1, 64)
|
||||
case int:
|
||||
return strconv.FormatInt(int64(val), 10)
|
||||
case int8:
|
||||
return strconv.FormatInt(int64(val), 10)
|
||||
case int16:
|
||||
return strconv.FormatInt(int64(val), 10)
|
||||
case int32:
|
||||
return strconv.FormatInt(int64(val), 10)
|
||||
case int64:
|
||||
return strconv.FormatInt(val, 10)
|
||||
case uint:
|
||||
return strconv.FormatUint(uint64(val), 10)
|
||||
case uint8:
|
||||
return strconv.FormatUint(uint64(val), 10)
|
||||
case uint16:
|
||||
return strconv.FormatUint(uint64(val), 10)
|
||||
case uint32:
|
||||
return strconv.FormatUint(uint64(val), 10)
|
||||
case uint64:
|
||||
return strconv.FormatUint(val, 10)
|
||||
case string:
|
||||
res = v.String()
|
||||
return res
|
||||
return val
|
||||
case []byte:
|
||||
res = string(v.Bytes())
|
||||
return res
|
||||
return string(val)
|
||||
default:
|
||||
newValue, _ := json.Marshal(value)
|
||||
res = string(newValue)
|
||||
return res
|
||||
b, err := json.Marshal(val)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -374,3 +390,17 @@ func ToInterface(v reflect.Value) (value interface{}, ok bool) {
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
|
||||
// Utf8ToGbk convert utf8 encoding data to GBK encoding data.
|
||||
func Utf8ToGbk(bs []byte) ([]byte, error) {
|
||||
r := transform.NewReader(bytes.NewReader(bs), simplifiedchinese.GBK.NewEncoder())
|
||||
b, err := io.ReadAll(r)
|
||||
return b, err
|
||||
}
|
||||
|
||||
// GbkToUtf8 convert GBK encoding data to utf8 encoding data.
|
||||
func GbkToUtf8(bs []byte) ([]byte, error) {
|
||||
r := transform.NewReader(bytes.NewReader(bs), simplifiedchinese.GBK.NewDecoder())
|
||||
b, err := io.ReadAll(r)
|
||||
return b, err
|
||||
}
|
||||
|
||||
@@ -4,8 +4,10 @@ import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/duke-git/lancet/internal"
|
||||
"github.com/duke-git/lancet/validator"
|
||||
)
|
||||
|
||||
func TestToChar(t *testing.T) {
|
||||
@@ -119,7 +121,7 @@ func TestToString(t *testing.T) {
|
||||
"", "",
|
||||
"0", "1", "-1",
|
||||
"123", "123", "123", "123", "123", "123", "123",
|
||||
"12.3", "12.300000190734863",
|
||||
"12.3", "12.3",
|
||||
"true", "false",
|
||||
"[1,2,3]", "{\"a\":1,\"b\":2,\"c\":3}", "{\"Name\":\"TestStruct\"}", "hello"}
|
||||
|
||||
@@ -339,3 +341,25 @@ func TestToInterface(t *testing.T) {
|
||||
assert.EqualValues(nil, nilVal)
|
||||
assert.Equal(false, ok)
|
||||
}
|
||||
|
||||
func TestUtf8ToGbk(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestUtf8ToGbk")
|
||||
|
||||
utf8Data := []byte("hello")
|
||||
gbkData, err := Utf8ToGbk(utf8Data)
|
||||
|
||||
assert.Equal(true, utf8.Valid(utf8Data))
|
||||
assert.Equal(true, validator.IsGBK(gbkData))
|
||||
assert.IsNil(err)
|
||||
}
|
||||
|
||||
func TestGbkToUtf8(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestGbkToUtf8")
|
||||
|
||||
gbkData, err := Utf8ToGbk([]byte("hello"))
|
||||
utf8Data, err := GbkToUtf8(gbkData)
|
||||
|
||||
assert.IsNil(err)
|
||||
assert.Equal(true, utf8.Valid(utf8Data))
|
||||
assert.Equal("hello", string(utf8Data))
|
||||
}
|
||||
|
||||
188
cryptor/aes.go
188
cryptor/aes.go
@@ -1,188 +0,0 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package cryptor implements some util functions to encrypt and decrypt.
|
||||
// Note:
|
||||
// 1. for aes crypt function, the `key` param length should be 16, 24 or 32. if not, will panic.
|
||||
package cryptor
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"io"
|
||||
)
|
||||
|
||||
// AesEcbEncrypt encrypt data with key use AES ECB algorithm
|
||||
// len(key) should be 16, 24 or 32
|
||||
func AesEcbEncrypt(data, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 16 && size != 24 && size != 32 {
|
||||
panic("key length shoud be 16 or 24 or 32")
|
||||
}
|
||||
|
||||
cipher, _ := aes.NewCipher(generateAesKey(key, size))
|
||||
length := (len(data) + aes.BlockSize) / aes.BlockSize
|
||||
|
||||
plain := make([]byte, length*aes.BlockSize)
|
||||
|
||||
copy(plain, data)
|
||||
|
||||
pad := byte(len(plain) - len(data))
|
||||
for i := len(data); i < len(plain); i++ {
|
||||
plain[i] = pad
|
||||
}
|
||||
|
||||
encrypted := make([]byte, len(plain))
|
||||
for bs, be := 0, cipher.BlockSize(); bs <= len(data); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||||
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
|
||||
}
|
||||
|
||||
return encrypted
|
||||
}
|
||||
|
||||
// AesEcbDecrypt decrypt data with key use AES ECB algorithm
|
||||
// len(key) should be 16, 24 or 32
|
||||
func AesEcbDecrypt(encrypted, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 16 && size != 24 && size != 32 {
|
||||
panic("key length shoud be 16 or 24 or 32")
|
||||
}
|
||||
|
||||
cipher, _ := aes.NewCipher(generateAesKey(key, size))
|
||||
decrypted := make([]byte, len(encrypted))
|
||||
|
||||
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||||
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
|
||||
}
|
||||
|
||||
trim := 0
|
||||
if len(decrypted) > 0 {
|
||||
trim = len(decrypted) - int(decrypted[len(decrypted)-1])
|
||||
}
|
||||
|
||||
return decrypted[:trim]
|
||||
}
|
||||
|
||||
// AesCbcEncrypt encrypt data with key use AES CBC algorithm
|
||||
// len(key) should be 16, 24 or 32
|
||||
func AesCbcEncrypt(data, key []byte) []byte {
|
||||
block, _ := aes.NewCipher(key)
|
||||
data = pkcs7Padding(data, block.BlockSize())
|
||||
|
||||
encrypted := make([]byte, aes.BlockSize+len(data))
|
||||
iv := encrypted[:aes.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
mode := cipher.NewCBCEncrypter(block, iv)
|
||||
mode.CryptBlocks(encrypted[aes.BlockSize:], data)
|
||||
|
||||
return encrypted
|
||||
}
|
||||
|
||||
// AesCbcDecrypt decrypt data with key use AES CBC algorithm
|
||||
// len(key) should be 16, 24 or 32
|
||||
func AesCbcDecrypt(encrypted, key []byte) []byte {
|
||||
block, _ := aes.NewCipher(key)
|
||||
|
||||
iv := encrypted[:aes.BlockSize]
|
||||
encrypted = encrypted[aes.BlockSize:]
|
||||
|
||||
mode := cipher.NewCBCDecrypter(block, iv)
|
||||
mode.CryptBlocks(encrypted, encrypted)
|
||||
|
||||
decrypted := pkcs7UnPadding(encrypted)
|
||||
return decrypted
|
||||
}
|
||||
|
||||
// AesCtrCrypt encrypt data with key use AES CTR algorithm
|
||||
// len(key) should be 16, 24 or 32
|
||||
func AesCtrCrypt(data, key []byte) []byte {
|
||||
block, _ := aes.NewCipher(key)
|
||||
|
||||
iv := bytes.Repeat([]byte("1"), block.BlockSize())
|
||||
stream := cipher.NewCTR(block, iv)
|
||||
|
||||
dst := make([]byte, len(data))
|
||||
stream.XORKeyStream(dst, data)
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
// AesCfbEncrypt encrypt data with key use AES CFB algorithm
|
||||
// len(key) should be 16, 24 or 32
|
||||
func AesCfbEncrypt(data, key []byte) []byte {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
encrypted := make([]byte, aes.BlockSize+len(data))
|
||||
iv := encrypted[:aes.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
stream := cipher.NewCFBEncrypter(block, iv)
|
||||
stream.XORKeyStream(encrypted[aes.BlockSize:], data)
|
||||
return encrypted
|
||||
}
|
||||
|
||||
// AesCfbDecrypt decrypt data with key use AES CFB algorithm
|
||||
// len(encrypted) should be great than 16, len(key) should be 16, 24 or 32
|
||||
func AesCfbDecrypt(encrypted, key []byte) []byte {
|
||||
block, _ := aes.NewCipher(key)
|
||||
if len(encrypted) < aes.BlockSize {
|
||||
panic("encrypted data is too short")
|
||||
}
|
||||
iv := encrypted[:aes.BlockSize]
|
||||
encrypted = encrypted[aes.BlockSize:]
|
||||
|
||||
stream := cipher.NewCFBDecrypter(block, iv)
|
||||
stream.XORKeyStream(encrypted, encrypted)
|
||||
return encrypted
|
||||
}
|
||||
|
||||
// AesOfbEncrypt encrypt data with key use AES OFB algorithm
|
||||
// len(key) should be 16, 24 or 32
|
||||
func AesOfbEncrypt(data, key []byte) []byte {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
data = pkcs7Padding(data, aes.BlockSize)
|
||||
encrypted := make([]byte, aes.BlockSize+len(data))
|
||||
iv := encrypted[:aes.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
stream := cipher.NewOFB(block, iv)
|
||||
stream.XORKeyStream(encrypted[aes.BlockSize:], data)
|
||||
return encrypted
|
||||
}
|
||||
|
||||
// AesOfbDecrypt decrypt data with key use AES OFB algorithm
|
||||
// len(key) should be 16, 24 or 32
|
||||
func AesOfbDecrypt(data, key []byte) []byte {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
iv := data[:aes.BlockSize]
|
||||
data = data[aes.BlockSize:]
|
||||
if len(data)%aes.BlockSize != 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
decrypted := make([]byte, len(data))
|
||||
mode := cipher.NewOFB(block, iv)
|
||||
mode.XORKeyStream(decrypted, data)
|
||||
|
||||
decrypted = pkcs7UnPadding(decrypted)
|
||||
return decrypted
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package cryptor
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/internal"
|
||||
)
|
||||
|
||||
func TestAesEcbEncrypt(t *testing.T) {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
|
||||
aesEcbEncrypt := AesEcbEncrypt([]byte(data), []byte(key))
|
||||
aesEcbDecrypt := AesEcbDecrypt(aesEcbEncrypt, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestAesEcbEncrypt")
|
||||
assert.Equal(data, string(aesEcbDecrypt))
|
||||
}
|
||||
|
||||
func TestAesCbcEncrypt(t *testing.T) {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
|
||||
aesCbcEncrypt := AesCbcEncrypt([]byte(data), []byte(key))
|
||||
aesCbcDecrypt := AesCbcDecrypt(aesCbcEncrypt, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestAesCbcEncrypt")
|
||||
assert.Equal(data, string(aesCbcDecrypt))
|
||||
}
|
||||
|
||||
func TestAesCtrCrypt(t *testing.T) {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
|
||||
aesCtrCrypt := AesCtrCrypt([]byte(data), []byte(key))
|
||||
aesCtrDeCrypt := AesCtrCrypt(aesCtrCrypt, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestAesCtrCrypt")
|
||||
assert.Equal(data, string(aesCtrDeCrypt))
|
||||
}
|
||||
|
||||
func TestAesCfbEncrypt(t *testing.T) {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
|
||||
aesCfbEncrypt := AesCfbEncrypt([]byte(data), []byte(key))
|
||||
aesCfbDecrypt := AesCfbDecrypt(aesCfbEncrypt, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestAesCfbEncrypt")
|
||||
assert.Equal(data, string(aesCfbDecrypt))
|
||||
}
|
||||
|
||||
func TestAesOfbEncrypt(t *testing.T) {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
|
||||
aesOfbEncrypt := AesOfbEncrypt([]byte(data), []byte(key))
|
||||
aesOfbDecrypt := AesOfbDecrypt(aesOfbEncrypt, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestAesOfbEncrypt")
|
||||
assert.Equal(data, string(aesOfbDecrypt))
|
||||
}
|
||||
@@ -37,6 +37,27 @@ func Md5String(s string) string {
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
// Md5StringWithBase64 return the md5 value of string with base64.
|
||||
func Md5StringWithBase64(s string) string {
|
||||
h := md5.New()
|
||||
h.Write([]byte(s))
|
||||
return base64.StdEncoding.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
// Md5Byte return the md5 string of byte slice.
|
||||
func Md5Byte(data []byte) string {
|
||||
h := md5.New()
|
||||
h.Write(data)
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
// Md5ByteWithBase64 return the md5 string of byte slice with base64.
|
||||
func Md5ByteWithBase64(data []byte) string {
|
||||
h := md5.New()
|
||||
h.Write(data)
|
||||
return base64.StdEncoding.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
// Md5File return the md5 value of file
|
||||
func Md5File(filename string) (string, error) {
|
||||
if fileInfo, err := os.Stat(filename); err != nil {
|
||||
@@ -76,6 +97,13 @@ func HmacMd5(data, key string) string {
|
||||
return hex.EncodeToString(h.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// HmacMd5WithBase64 return the hmac hash of string use md5 with base64.
|
||||
func HmacMd5WithBase64(data, key string) string {
|
||||
h := hmac.New(md5.New, []byte(key))
|
||||
h.Write([]byte(data))
|
||||
return base64.StdEncoding.EncodeToString(h.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// HmacSha1 return the hmac hash of string use sha1
|
||||
func HmacSha1(data, key string) string {
|
||||
h := hmac.New(sha1.New, []byte(key))
|
||||
@@ -83,6 +111,13 @@ func HmacSha1(data, key string) string {
|
||||
return hex.EncodeToString(h.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// HmacSha1WithBase64 return the hmac hash of string use sha1 with base64.
|
||||
func HmacSha1WithBase64(str, key string) string {
|
||||
h := hmac.New(sha1.New, []byte(key))
|
||||
h.Write([]byte(str))
|
||||
return base64.StdEncoding.EncodeToString(h.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// HmacSha256 return the hmac hash of string use sha256
|
||||
func HmacSha256(data, key string) string {
|
||||
h := hmac.New(sha256.New, []byte(key))
|
||||
@@ -90,6 +125,13 @@ func HmacSha256(data, key string) string {
|
||||
return hex.EncodeToString(h.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// HmacSha256WithBase64 return the hmac hash of string use sha256 with base64.
|
||||
func HmacSha256WithBase64(str, key string) string {
|
||||
h := hmac.New(sha256.New, []byte(key))
|
||||
h.Write([]byte(str))
|
||||
return base64.StdEncoding.EncodeToString(h.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// HmacSha512 return the hmac hash of string use sha512
|
||||
func HmacSha512(data, key string) string {
|
||||
h := hmac.New(sha512.New, []byte(key))
|
||||
@@ -97,6 +139,13 @@ func HmacSha512(data, key string) string {
|
||||
return hex.EncodeToString(h.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// HmacSha512WithBase64 return the hmac hash of string use sha512 with base64.
|
||||
func HmacSha512WithBase64(str, key string) string {
|
||||
h := hmac.New(sha512.New, []byte(key))
|
||||
h.Write([]byte(str))
|
||||
return base64.StdEncoding.EncodeToString(h.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// Sha1 return the sha1 value (SHA-1 hash algorithm) of string
|
||||
func Sha1(data string) string {
|
||||
sha1 := sha1.New()
|
||||
@@ -104,6 +153,13 @@ func Sha1(data string) string {
|
||||
return hex.EncodeToString(sha1.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// Sha1WithBase64 return the sha1 value (SHA-1 hash algorithm) of base64 string.
|
||||
func Sha1WithBase64(str string) string {
|
||||
sha1 := sha1.New()
|
||||
sha1.Write([]byte(str))
|
||||
return base64.StdEncoding.EncodeToString(sha1.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// Sha256 return the sha256 value (SHA256 hash algorithm) of string
|
||||
func Sha256(data string) string {
|
||||
sha256 := sha256.New()
|
||||
@@ -111,9 +167,23 @@ func Sha256(data string) string {
|
||||
return hex.EncodeToString(sha256.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// Sha256WithBase64 return the sha256 value (SHA256 hash algorithm) of base64 string.
|
||||
func Sha256WithBase64(str string) string {
|
||||
sha256 := sha256.New()
|
||||
sha256.Write([]byte(str))
|
||||
return base64.StdEncoding.EncodeToString(sha256.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// Sha512 return the sha512 value (SHA512 hash algorithm) of string
|
||||
func Sha512(data string) string {
|
||||
sha512 := sha512.New()
|
||||
sha512.Write([]byte(data))
|
||||
return hex.EncodeToString(sha512.Sum([]byte("")))
|
||||
}
|
||||
|
||||
// Sha512WithBase64 return the sha512 value (SHA512 hash algorithm) of base64 string.
|
||||
func Sha512WithBase64(str string) string {
|
||||
sha512 := sha512.New()
|
||||
sha512.Write([]byte(str))
|
||||
return base64.StdEncoding.EncodeToString(sha512.Sum([]byte("")))
|
||||
}
|
||||
|
||||
@@ -21,6 +21,22 @@ func TestMd5String(t *testing.T) {
|
||||
assert.Equal("5d41402abc4b2a76b9719d911017c592", Md5String("hello"))
|
||||
}
|
||||
|
||||
func TestMd5StringWithBase64(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestMd5StringWithBase64")
|
||||
assert.Equal("XUFAKrxLKna5cZ2REBfFkg==", Md5StringWithBase64("hello"))
|
||||
}
|
||||
|
||||
func TestMd5Byte(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestMd5Byte")
|
||||
data := []byte{'a'}
|
||||
assert.Equal("0cc175b9c0f1b6a831c399e269772661", Md5Byte(data))
|
||||
}
|
||||
|
||||
func TestMd5ByteWithBase64(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestMd5ByteWithBase64")
|
||||
assert.Equal("XUFAKrxLKna5cZ2REBfFkg==", Md5ByteWithBase64([]byte("hello")))
|
||||
}
|
||||
|
||||
func TestMd5File(t *testing.T) {
|
||||
fileMd5, err := Md5File("./basic.go")
|
||||
assert := internal.NewAssert(t, "TestMd5File")
|
||||
@@ -33,6 +49,11 @@ func TestHmacMd5(t *testing.T) {
|
||||
assert.Equal("5f4c9faaff0a1ad3007d9ddc06abe36d", HmacMd5("hello world", "12345"))
|
||||
}
|
||||
|
||||
func TestHmacMd5WithBase64(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestHmacMd5WithBase64")
|
||||
assert.Equal("6DQwbquJLYclJdSRinpjmg==", HmacMd5WithBase64("hello", "12345"))
|
||||
}
|
||||
|
||||
func TestHmacSha1(t *testing.T) {
|
||||
s := "hello world"
|
||||
key := "12345"
|
||||
@@ -43,6 +64,16 @@ func TestHmacSha1(t *testing.T) {
|
||||
assert.Equal(expected, hmacSha1)
|
||||
}
|
||||
|
||||
func TestHmacSha1WithBase64(t *testing.T) {
|
||||
s := "hello"
|
||||
key := "12345"
|
||||
hmacSha1 := HmacSha1WithBase64(s, key)
|
||||
expected := "XGqdsMzLkuNu0DI/0Jt/k23prOA="
|
||||
|
||||
assert := internal.NewAssert(t, "TestHmacSha1")
|
||||
assert.Equal(expected, hmacSha1)
|
||||
}
|
||||
|
||||
func TestHmacSha256(t *testing.T) {
|
||||
s := "hello world"
|
||||
key := "12345"
|
||||
@@ -53,6 +84,16 @@ func TestHmacSha256(t *testing.T) {
|
||||
assert.Equal(expected, hmacSha256)
|
||||
}
|
||||
|
||||
func TestHmacSha256WithBase64(t *testing.T) {
|
||||
str := "hello"
|
||||
key := "12345"
|
||||
hms := HmacSha256WithBase64(str, key)
|
||||
expected := "MVu5PE6YmGK6Ccti4F1zpfN2yzbw14btqwwyDQWf3nU="
|
||||
|
||||
assert := internal.NewAssert(t, "TestHmacSha256WithBase64")
|
||||
assert.Equal(expected, hms)
|
||||
}
|
||||
|
||||
func TestHmacSha512(t *testing.T) {
|
||||
s := "hello world"
|
||||
key := "12345"
|
||||
@@ -63,6 +104,16 @@ func TestHmacSha512(t *testing.T) {
|
||||
assert.Equal(expected, hmacSha512)
|
||||
}
|
||||
|
||||
func TestHmacSha512WithBase64(t *testing.T) {
|
||||
str := "hello"
|
||||
key := "12345"
|
||||
hms := HmacSha512WithBase64(str, key)
|
||||
expected := "3Y8SkKndI9NU4lJtmi6c6M///dN8syCADRxsE9Lvw2Mog3ahlsVFja9T+OGqa0Wm2FYwPVwKIGS/+XhYYdSM/A=="
|
||||
|
||||
assert := internal.NewAssert(t, "TestHmacSha512WithBase64")
|
||||
assert.Equal(expected, hms)
|
||||
}
|
||||
|
||||
func TestSha1(t *testing.T) {
|
||||
s := "hello world"
|
||||
sha1 := Sha1(s)
|
||||
@@ -72,6 +123,14 @@ func TestSha1(t *testing.T) {
|
||||
assert.Equal(expected, sha1)
|
||||
}
|
||||
|
||||
func TestSha1WithBase64(t *testing.T) {
|
||||
str := Sha1WithBase64("hello")
|
||||
expected := "qvTGHdzF6KLavt4PO0gs2a6pQ00="
|
||||
|
||||
assert := internal.NewAssert(t, "TestSha1WithBase64")
|
||||
assert.Equal(expected, str)
|
||||
}
|
||||
|
||||
func TestSha256(t *testing.T) {
|
||||
s := "hello world"
|
||||
sha256 := Sha256(s)
|
||||
@@ -81,6 +140,14 @@ func TestSha256(t *testing.T) {
|
||||
assert.Equal(expected, sha256)
|
||||
}
|
||||
|
||||
func TestSha256WithBase64(t *testing.T) {
|
||||
str := Sha256WithBase64("hello")
|
||||
expected := "LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ="
|
||||
|
||||
assert := internal.NewAssert(t, "TestSha256WithBase64")
|
||||
assert.Equal(expected, str)
|
||||
}
|
||||
|
||||
func TestSha512(t *testing.T) {
|
||||
s := "hello world"
|
||||
sha512 := Sha512(s)
|
||||
@@ -89,3 +156,11 @@ func TestSha512(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSha512")
|
||||
assert.Equal(expected, sha512)
|
||||
}
|
||||
|
||||
func TestSha512WithBase64(t *testing.T) {
|
||||
str := Sha512WithBase64("hello")
|
||||
expected := "m3HSJL1i83hdltRq0+o9czGb+8KJDKra4t/3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw=="
|
||||
|
||||
assert := internal.NewAssert(t, "TestSha512WithBase64")
|
||||
assert.Equal(expected, str)
|
||||
}
|
||||
|
||||
463
cryptor/crypto.go
Normal file
463
cryptor/crypto.go
Normal file
@@ -0,0 +1,463 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package cryptor implements some util functions to encrypt and decrypt.
|
||||
// Note:
|
||||
// 1. for aes crypt function, the `key` param length should be 16, 24 or 32. if not, will panic.
|
||||
package cryptor
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/des"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// AesEcbEncrypt encrypt data with key use AES ECB algorithm
|
||||
// len(key) should be 16, 24 or 32
|
||||
func AesEcbEncrypt(data, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 16 && size != 24 && size != 32 {
|
||||
panic("key length shoud be 16 or 24 or 32")
|
||||
}
|
||||
|
||||
cipher, _ := aes.NewCipher(generateAesKey(key, size))
|
||||
length := (len(data) + aes.BlockSize) / aes.BlockSize
|
||||
|
||||
plain := make([]byte, length*aes.BlockSize)
|
||||
|
||||
copy(plain, data)
|
||||
|
||||
pad := byte(len(plain) - len(data))
|
||||
for i := len(data); i < len(plain); i++ {
|
||||
plain[i] = pad
|
||||
}
|
||||
|
||||
encrypted := make([]byte, len(plain))
|
||||
for bs, be := 0, cipher.BlockSize(); bs <= len(data); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||||
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
|
||||
}
|
||||
|
||||
return encrypted
|
||||
}
|
||||
|
||||
// AesEcbDecrypt decrypt data with key use AES ECB algorithm
|
||||
// len(key) should be 16, 24 or 32
|
||||
func AesEcbDecrypt(encrypted, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 16 && size != 24 && size != 32 {
|
||||
panic("key length shoud be 16 or 24 or 32")
|
||||
}
|
||||
|
||||
cipher, _ := aes.NewCipher(generateAesKey(key, size))
|
||||
decrypted := make([]byte, len(encrypted))
|
||||
|
||||
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||||
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
|
||||
}
|
||||
|
||||
trim := 0
|
||||
if len(decrypted) > 0 {
|
||||
trim = len(decrypted) - int(decrypted[len(decrypted)-1])
|
||||
}
|
||||
|
||||
return decrypted[:trim]
|
||||
}
|
||||
|
||||
// AesCbcEncrypt encrypt data with key use AES CBC algorithm
|
||||
// len(key) should be 16, 24 or 32
|
||||
func AesCbcEncrypt(data, key []byte) []byte {
|
||||
block, _ := aes.NewCipher(key)
|
||||
data = pkcs7Padding(data, block.BlockSize())
|
||||
|
||||
encrypted := make([]byte, aes.BlockSize+len(data))
|
||||
iv := encrypted[:aes.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
mode := cipher.NewCBCEncrypter(block, iv)
|
||||
mode.CryptBlocks(encrypted[aes.BlockSize:], data)
|
||||
|
||||
return encrypted
|
||||
}
|
||||
|
||||
// AesCbcDecrypt decrypt data with key use AES CBC algorithm
|
||||
// len(key) should be 16, 24 or 32
|
||||
func AesCbcDecrypt(encrypted, key []byte) []byte {
|
||||
block, _ := aes.NewCipher(key)
|
||||
|
||||
iv := encrypted[:aes.BlockSize]
|
||||
encrypted = encrypted[aes.BlockSize:]
|
||||
|
||||
mode := cipher.NewCBCDecrypter(block, iv)
|
||||
mode.CryptBlocks(encrypted, encrypted)
|
||||
|
||||
decrypted := pkcs7UnPadding(encrypted)
|
||||
return decrypted
|
||||
}
|
||||
|
||||
// AesCtrCrypt encrypt data with key use AES CTR algorithm
|
||||
// len(key) should be 16, 24 or 32
|
||||
func AesCtrCrypt(data, key []byte) []byte {
|
||||
block, _ := aes.NewCipher(key)
|
||||
|
||||
iv := bytes.Repeat([]byte("1"), block.BlockSize())
|
||||
stream := cipher.NewCTR(block, iv)
|
||||
|
||||
dst := make([]byte, len(data))
|
||||
stream.XORKeyStream(dst, data)
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
// AesCfbEncrypt encrypt data with key use AES CFB algorithm
|
||||
// len(key) should be 16, 24 or 32
|
||||
func AesCfbEncrypt(data, key []byte) []byte {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
encrypted := make([]byte, aes.BlockSize+len(data))
|
||||
iv := encrypted[:aes.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
stream := cipher.NewCFBEncrypter(block, iv)
|
||||
stream.XORKeyStream(encrypted[aes.BlockSize:], data)
|
||||
return encrypted
|
||||
}
|
||||
|
||||
// AesCfbDecrypt decrypt data with key use AES CFB algorithm
|
||||
// len(encrypted) should be great than 16, len(key) should be 16, 24 or 32
|
||||
func AesCfbDecrypt(encrypted, key []byte) []byte {
|
||||
block, _ := aes.NewCipher(key)
|
||||
if len(encrypted) < aes.BlockSize {
|
||||
panic("encrypted data is too short")
|
||||
}
|
||||
iv := encrypted[:aes.BlockSize]
|
||||
encrypted = encrypted[aes.BlockSize:]
|
||||
|
||||
stream := cipher.NewCFBDecrypter(block, iv)
|
||||
stream.XORKeyStream(encrypted, encrypted)
|
||||
return encrypted
|
||||
}
|
||||
|
||||
// AesOfbEncrypt encrypt data with key use AES OFB algorithm
|
||||
// len(key) should be 16, 24 or 32
|
||||
func AesOfbEncrypt(data, key []byte) []byte {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
data = pkcs7Padding(data, aes.BlockSize)
|
||||
encrypted := make([]byte, aes.BlockSize+len(data))
|
||||
iv := encrypted[:aes.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
stream := cipher.NewOFB(block, iv)
|
||||
stream.XORKeyStream(encrypted[aes.BlockSize:], data)
|
||||
return encrypted
|
||||
}
|
||||
|
||||
// AesOfbDecrypt decrypt data with key use AES OFB algorithm
|
||||
// len(key) should be 16, 24 or 32
|
||||
func AesOfbDecrypt(data, key []byte) []byte {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
iv := data[:aes.BlockSize]
|
||||
data = data[aes.BlockSize:]
|
||||
if len(data)%aes.BlockSize != 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
decrypted := make([]byte, len(data))
|
||||
mode := cipher.NewOFB(block, iv)
|
||||
mode.XORKeyStream(decrypted, data)
|
||||
|
||||
decrypted = pkcs7UnPadding(decrypted)
|
||||
return decrypted
|
||||
}
|
||||
|
||||
// DesEcbEncrypt encrypt data with key use DES ECB algorithm
|
||||
// len(key) should be 8
|
||||
func DesEcbEncrypt(data, key []byte) []byte {
|
||||
cipher, _ := des.NewCipher(generateDesKey(key))
|
||||
length := (len(data) + des.BlockSize) / des.BlockSize
|
||||
plain := make([]byte, length*des.BlockSize)
|
||||
copy(plain, data)
|
||||
|
||||
pad := byte(len(plain) - len(data))
|
||||
for i := len(data); i < len(plain); i++ {
|
||||
plain[i] = pad
|
||||
}
|
||||
|
||||
encrypted := make([]byte, len(plain))
|
||||
for bs, be := 0, cipher.BlockSize(); bs <= len(data); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||||
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
|
||||
}
|
||||
|
||||
return encrypted
|
||||
}
|
||||
|
||||
// DesEcbDecrypt decrypt data with key use DES ECB algorithm
|
||||
// len(key) should be 8
|
||||
func DesEcbDecrypt(encrypted, key []byte) []byte {
|
||||
cipher, _ := des.NewCipher(generateDesKey(key))
|
||||
decrypted := make([]byte, len(encrypted))
|
||||
|
||||
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||||
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
|
||||
}
|
||||
|
||||
trim := 0
|
||||
if len(decrypted) > 0 {
|
||||
trim = len(decrypted) - int(decrypted[len(decrypted)-1])
|
||||
}
|
||||
|
||||
return decrypted[:trim]
|
||||
}
|
||||
|
||||
// DesCbcEncrypt encrypt data with key use DES CBC algorithm
|
||||
// len(key) should be 8
|
||||
func DesCbcEncrypt(data, key []byte) []byte {
|
||||
block, _ := des.NewCipher(key)
|
||||
data = pkcs7Padding(data, block.BlockSize())
|
||||
|
||||
encrypted := make([]byte, des.BlockSize+len(data))
|
||||
iv := encrypted[:des.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
mode := cipher.NewCBCEncrypter(block, iv)
|
||||
mode.CryptBlocks(encrypted[des.BlockSize:], data)
|
||||
|
||||
return encrypted
|
||||
}
|
||||
|
||||
// DesCbcDecrypt decrypt data with key use DES CBC algorithm
|
||||
// len(key) should be 8
|
||||
func DesCbcDecrypt(encrypted, key []byte) []byte {
|
||||
block, _ := des.NewCipher(key)
|
||||
|
||||
iv := encrypted[:des.BlockSize]
|
||||
encrypted = encrypted[des.BlockSize:]
|
||||
|
||||
mode := cipher.NewCBCDecrypter(block, iv)
|
||||
mode.CryptBlocks(encrypted, encrypted)
|
||||
|
||||
decrypted := pkcs7UnPadding(encrypted)
|
||||
return decrypted
|
||||
}
|
||||
|
||||
// DesCtrCrypt encrypt data with key use DES CTR algorithm
|
||||
// len(key) should be 8
|
||||
func DesCtrCrypt(data, key []byte) []byte {
|
||||
block, _ := des.NewCipher(key)
|
||||
|
||||
iv := bytes.Repeat([]byte("1"), block.BlockSize())
|
||||
stream := cipher.NewCTR(block, iv)
|
||||
|
||||
dst := make([]byte, len(data))
|
||||
stream.XORKeyStream(dst, data)
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
// DesCfbEncrypt encrypt data with key use DES CFB algorithm
|
||||
// len(key) should be 8
|
||||
func DesCfbEncrypt(data, key []byte) []byte {
|
||||
block, err := des.NewCipher(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
encrypted := make([]byte, des.BlockSize+len(data))
|
||||
iv := encrypted[:des.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
stream := cipher.NewCFBEncrypter(block, iv)
|
||||
stream.XORKeyStream(encrypted[des.BlockSize:], data)
|
||||
|
||||
return encrypted
|
||||
}
|
||||
|
||||
// DesCfbDecrypt decrypt data with key use DES CFB algorithm
|
||||
// len(encrypted) should be great than 16, len(key) should be 8
|
||||
func DesCfbDecrypt(encrypted, key []byte) []byte {
|
||||
block, _ := des.NewCipher(key)
|
||||
if len(encrypted) < des.BlockSize {
|
||||
panic("encrypted data is too short")
|
||||
}
|
||||
iv := encrypted[:des.BlockSize]
|
||||
encrypted = encrypted[des.BlockSize:]
|
||||
|
||||
stream := cipher.NewCFBDecrypter(block, iv)
|
||||
stream.XORKeyStream(encrypted, encrypted)
|
||||
|
||||
return encrypted
|
||||
}
|
||||
|
||||
// DesOfbEncrypt encrypt data with key use DES OFB algorithm
|
||||
// len(key) should be 16, 24 or 32
|
||||
func DesOfbEncrypt(data, key []byte) []byte {
|
||||
block, err := des.NewCipher(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
data = pkcs7Padding(data, des.BlockSize)
|
||||
encrypted := make([]byte, des.BlockSize+len(data))
|
||||
iv := encrypted[:des.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
stream := cipher.NewOFB(block, iv)
|
||||
stream.XORKeyStream(encrypted[des.BlockSize:], data)
|
||||
|
||||
return encrypted
|
||||
}
|
||||
|
||||
// DesOfbDecrypt decrypt data with key use DES OFB algorithm
|
||||
// len(key) should be 8
|
||||
func DesOfbDecrypt(data, key []byte) []byte {
|
||||
block, err := des.NewCipher(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
iv := data[:des.BlockSize]
|
||||
data = data[des.BlockSize:]
|
||||
if len(data)%des.BlockSize != 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
decrypted := make([]byte, len(data))
|
||||
mode := cipher.NewOFB(block, iv)
|
||||
mode.XORKeyStream(decrypted, data)
|
||||
|
||||
decrypted = pkcs7UnPadding(decrypted)
|
||||
|
||||
return decrypted
|
||||
}
|
||||
|
||||
// GenerateRsaKey make a rsa private key, and return key file name
|
||||
// Generated key file is `rsa_private.pem` and `rsa_public.pem` in current path
|
||||
func GenerateRsaKey(keySize int, priKeyFile, pubKeyFile string) error {
|
||||
// private key
|
||||
privateKey, err := rsa.GenerateKey(rand.Reader, keySize)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
derText := x509.MarshalPKCS1PrivateKey(privateKey)
|
||||
|
||||
block := pem.Block{
|
||||
Type: "rsa private key",
|
||||
Bytes: derText,
|
||||
}
|
||||
|
||||
//file,err := os.Create("rsa_private.pem")
|
||||
file, err := os.Create(priKeyFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
pem.Encode(file, &block)
|
||||
file.Close()
|
||||
|
||||
// public key
|
||||
publicKey := privateKey.PublicKey
|
||||
|
||||
derpText, err := x509.MarshalPKIXPublicKey(&publicKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
block = pem.Block{
|
||||
Type: "rsa public key",
|
||||
Bytes: derpText,
|
||||
}
|
||||
|
||||
//file,err = os.Create("rsa_public.pem")
|
||||
file, err = os.Create(pubKeyFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pem.Encode(file, &block)
|
||||
file.Close()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RsaEncrypt encrypt data with ras algorithm
|
||||
func RsaEncrypt(data []byte, pubKeyFileName string) []byte {
|
||||
file, err := os.Open(pubKeyFileName)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fileInfo, err := file.Stat()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer file.Close()
|
||||
buf := make([]byte, fileInfo.Size())
|
||||
file.Read(buf)
|
||||
|
||||
block, _ := pem.Decode(buf)
|
||||
|
||||
pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
pubKey := pubInterface.(*rsa.PublicKey)
|
||||
|
||||
cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, pubKey, data)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return cipherText
|
||||
}
|
||||
|
||||
// RsaDecrypt decrypt data with ras algorithm
|
||||
func RsaDecrypt(data []byte, privateKeyFileName string) []byte {
|
||||
file, err := os.Open(privateKeyFileName)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fileInfo, err := file.Stat()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
buf := make([]byte, fileInfo.Size())
|
||||
defer file.Close()
|
||||
file.Read(buf)
|
||||
|
||||
block, _ := pem.Decode(buf)
|
||||
|
||||
priKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
plainText, err := rsa.DecryptPKCS1v15(rand.Reader, priKey, data)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return plainText
|
||||
}
|
||||
130
cryptor/crypto_test.go
Normal file
130
cryptor/crypto_test.go
Normal file
@@ -0,0 +1,130 @@
|
||||
package cryptor
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/internal"
|
||||
)
|
||||
|
||||
func TestAesEcbEncrypt(t *testing.T) {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
|
||||
aesEcbEncrypt := AesEcbEncrypt([]byte(data), []byte(key))
|
||||
aesEcbDecrypt := AesEcbDecrypt(aesEcbEncrypt, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestAesEcbEncrypt")
|
||||
assert.Equal(data, string(aesEcbDecrypt))
|
||||
}
|
||||
|
||||
func TestAesCbcEncrypt(t *testing.T) {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
|
||||
aesCbcEncrypt := AesCbcEncrypt([]byte(data), []byte(key))
|
||||
aesCbcDecrypt := AesCbcDecrypt(aesCbcEncrypt, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestAesCbcEncrypt")
|
||||
assert.Equal(data, string(aesCbcDecrypt))
|
||||
}
|
||||
|
||||
func TestAesCtrCrypt(t *testing.T) {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
|
||||
aesCtrCrypt := AesCtrCrypt([]byte(data), []byte(key))
|
||||
aesCtrDeCrypt := AesCtrCrypt(aesCtrCrypt, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestAesCtrCrypt")
|
||||
assert.Equal(data, string(aesCtrDeCrypt))
|
||||
}
|
||||
|
||||
func TestAesCfbEncrypt(t *testing.T) {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
|
||||
aesCfbEncrypt := AesCfbEncrypt([]byte(data), []byte(key))
|
||||
aesCfbDecrypt := AesCfbDecrypt(aesCfbEncrypt, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestAesCfbEncrypt")
|
||||
assert.Equal(data, string(aesCfbDecrypt))
|
||||
}
|
||||
|
||||
func TestAesOfbEncrypt(t *testing.T) {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
|
||||
aesOfbEncrypt := AesOfbEncrypt([]byte(data), []byte(key))
|
||||
aesOfbDecrypt := AesOfbDecrypt(aesOfbEncrypt, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestAesOfbEncrypt")
|
||||
assert.Equal(data, string(aesOfbDecrypt))
|
||||
}
|
||||
|
||||
func TestDesEcbEncrypt(t *testing.T) {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
|
||||
desEcbEncrypt := DesEcbEncrypt([]byte(data), []byte(key))
|
||||
desEcbDecrypt := DesEcbDecrypt(desEcbEncrypt, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestDesEcbEncrypt")
|
||||
assert.Equal(data, string(desEcbDecrypt))
|
||||
}
|
||||
|
||||
func TestDesCbcEncrypt(t *testing.T) {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
|
||||
desCbcEncrypt := DesCbcEncrypt([]byte(data), []byte(key))
|
||||
desCbcDecrypt := DesCbcDecrypt(desCbcEncrypt, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestDesCbcEncrypt")
|
||||
assert.Equal(data, string(desCbcDecrypt))
|
||||
}
|
||||
|
||||
func TestDesCtrCrypt(t *testing.T) {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
|
||||
desCtrCrypt := DesCtrCrypt([]byte(data), []byte(key))
|
||||
desCtrDeCrypt := DesCtrCrypt(desCtrCrypt, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestDesCtrCrypt")
|
||||
assert.Equal(data, string(desCtrDeCrypt))
|
||||
}
|
||||
|
||||
func TestDesCfbEncrypt(t *testing.T) {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
|
||||
desCfbEncrypt := DesCfbEncrypt([]byte(data), []byte(key))
|
||||
desCfbDecrypt := DesCfbDecrypt(desCfbEncrypt, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestDesCfbEncrypt")
|
||||
assert.Equal(data, string(desCfbDecrypt))
|
||||
}
|
||||
|
||||
func TestDesOfbEncrypt(t *testing.T) {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
|
||||
desOfbEncrypt := DesOfbEncrypt([]byte(data), []byte(key))
|
||||
desOfbDecrypt := DesOfbDecrypt(desOfbEncrypt, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestDesOfbEncrypt")
|
||||
assert.Equal(data, string(desOfbDecrypt))
|
||||
}
|
||||
|
||||
func TestRsaEncrypt(t *testing.T) {
|
||||
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
data := []byte("hello world")
|
||||
encrypted := RsaEncrypt(data, "rsa_public.pem")
|
||||
decrypted := RsaDecrypt(encrypted, "rsa_private.pem")
|
||||
|
||||
assert := internal.NewAssert(t, "TestRsaEncrypt")
|
||||
assert.Equal(string(data), string(decrypted))
|
||||
}
|
||||
178
cryptor/des.go
178
cryptor/des.go
@@ -1,178 +0,0 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package cryptor implements some util functions to encrypt and decrypt.
|
||||
package cryptor
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/cipher"
|
||||
"crypto/des"
|
||||
"crypto/rand"
|
||||
"io"
|
||||
)
|
||||
|
||||
// DesEcbEncrypt encrypt data with key use DES ECB algorithm
|
||||
// len(key) should be 8
|
||||
func DesEcbEncrypt(data, key []byte) []byte {
|
||||
cipher, _ := des.NewCipher(generateDesKey(key))
|
||||
length := (len(data) + des.BlockSize) / des.BlockSize
|
||||
plain := make([]byte, length*des.BlockSize)
|
||||
copy(plain, data)
|
||||
|
||||
pad := byte(len(plain) - len(data))
|
||||
for i := len(data); i < len(plain); i++ {
|
||||
plain[i] = pad
|
||||
}
|
||||
|
||||
encrypted := make([]byte, len(plain))
|
||||
for bs, be := 0, cipher.BlockSize(); bs <= len(data); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||||
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
|
||||
}
|
||||
|
||||
return encrypted
|
||||
}
|
||||
|
||||
// DesEcbDecrypt decrypt data with key use DES ECB algorithm
|
||||
// len(key) should be 8
|
||||
func DesEcbDecrypt(encrypted, key []byte) []byte {
|
||||
cipher, _ := des.NewCipher(generateDesKey(key))
|
||||
decrypted := make([]byte, len(encrypted))
|
||||
|
||||
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||||
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
|
||||
}
|
||||
|
||||
trim := 0
|
||||
if len(decrypted) > 0 {
|
||||
trim = len(decrypted) - int(decrypted[len(decrypted)-1])
|
||||
}
|
||||
|
||||
return decrypted[:trim]
|
||||
}
|
||||
|
||||
// DesCbcEncrypt encrypt data with key use DES CBC algorithm
|
||||
// len(key) should be 8
|
||||
func DesCbcEncrypt(data, key []byte) []byte {
|
||||
block, _ := des.NewCipher(key)
|
||||
data = pkcs7Padding(data, block.BlockSize())
|
||||
|
||||
encrypted := make([]byte, des.BlockSize+len(data))
|
||||
iv := encrypted[:des.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
mode := cipher.NewCBCEncrypter(block, iv)
|
||||
mode.CryptBlocks(encrypted[des.BlockSize:], data)
|
||||
|
||||
return encrypted
|
||||
}
|
||||
|
||||
// DesCbcDecrypt decrypt data with key use DES CBC algorithm
|
||||
// len(key) should be 8
|
||||
func DesCbcDecrypt(encrypted, key []byte) []byte {
|
||||
block, _ := des.NewCipher(key)
|
||||
|
||||
iv := encrypted[:des.BlockSize]
|
||||
encrypted = encrypted[des.BlockSize:]
|
||||
|
||||
mode := cipher.NewCBCDecrypter(block, iv)
|
||||
mode.CryptBlocks(encrypted, encrypted)
|
||||
|
||||
decrypted := pkcs7UnPadding(encrypted)
|
||||
return decrypted
|
||||
}
|
||||
|
||||
// DesCtrCrypt encrypt data with key use DES CTR algorithm
|
||||
// len(key) should be 8
|
||||
func DesCtrCrypt(data, key []byte) []byte {
|
||||
block, _ := des.NewCipher(key)
|
||||
|
||||
iv := bytes.Repeat([]byte("1"), block.BlockSize())
|
||||
stream := cipher.NewCTR(block, iv)
|
||||
|
||||
dst := make([]byte, len(data))
|
||||
stream.XORKeyStream(dst, data)
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
// DesCfbEncrypt encrypt data with key use DES CFB algorithm
|
||||
// len(key) should be 8
|
||||
func DesCfbEncrypt(data, key []byte) []byte {
|
||||
block, err := des.NewCipher(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
encrypted := make([]byte, des.BlockSize+len(data))
|
||||
iv := encrypted[:des.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
stream := cipher.NewCFBEncrypter(block, iv)
|
||||
stream.XORKeyStream(encrypted[des.BlockSize:], data)
|
||||
|
||||
return encrypted
|
||||
}
|
||||
|
||||
// DesCfbDecrypt decrypt data with key use DES CFB algorithm
|
||||
// len(encrypted) should be great than 16, len(key) should be 8
|
||||
func DesCfbDecrypt(encrypted, key []byte) []byte {
|
||||
block, _ := des.NewCipher(key)
|
||||
if len(encrypted) < des.BlockSize {
|
||||
panic("encrypted data is too short")
|
||||
}
|
||||
iv := encrypted[:des.BlockSize]
|
||||
encrypted = encrypted[des.BlockSize:]
|
||||
|
||||
stream := cipher.NewCFBDecrypter(block, iv)
|
||||
stream.XORKeyStream(encrypted, encrypted)
|
||||
|
||||
return encrypted
|
||||
}
|
||||
|
||||
// DesOfbEncrypt encrypt data with key use DES OFB algorithm
|
||||
// len(key) should be 16, 24 or 32
|
||||
func DesOfbEncrypt(data, key []byte) []byte {
|
||||
block, err := des.NewCipher(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
data = pkcs7Padding(data, des.BlockSize)
|
||||
encrypted := make([]byte, des.BlockSize+len(data))
|
||||
iv := encrypted[:des.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
stream := cipher.NewOFB(block, iv)
|
||||
stream.XORKeyStream(encrypted[des.BlockSize:], data)
|
||||
|
||||
return encrypted
|
||||
}
|
||||
|
||||
// DesOfbDecrypt decrypt data with key use DES OFB algorithm
|
||||
// len(key) should be 8
|
||||
func DesOfbDecrypt(data, key []byte) []byte {
|
||||
block, err := des.NewCipher(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
iv := data[:des.BlockSize]
|
||||
data = data[des.BlockSize:]
|
||||
if len(data)%des.BlockSize != 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
decrypted := make([]byte, len(data))
|
||||
mode := cipher.NewOFB(block, iv)
|
||||
mode.XORKeyStream(decrypted, data)
|
||||
|
||||
decrypted = pkcs7UnPadding(decrypted)
|
||||
|
||||
return decrypted
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package cryptor
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/internal"
|
||||
)
|
||||
|
||||
func TestDesEcbEncrypt(t *testing.T) {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
|
||||
desEcbEncrypt := DesEcbEncrypt([]byte(data), []byte(key))
|
||||
desEcbDecrypt := DesEcbDecrypt(desEcbEncrypt, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestDesEcbEncrypt")
|
||||
assert.Equal(data, string(desEcbDecrypt))
|
||||
}
|
||||
|
||||
func TestDesCbcEncrypt(t *testing.T) {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
|
||||
desCbcEncrypt := DesCbcEncrypt([]byte(data), []byte(key))
|
||||
desCbcDecrypt := DesCbcDecrypt(desCbcEncrypt, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestDesCbcEncrypt")
|
||||
assert.Equal(data, string(desCbcDecrypt))
|
||||
}
|
||||
|
||||
func TestDesCtrCrypt(t *testing.T) {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
|
||||
desCtrCrypt := DesCtrCrypt([]byte(data), []byte(key))
|
||||
desCtrDeCrypt := DesCtrCrypt(desCtrCrypt, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestDesCtrCrypt")
|
||||
assert.Equal(data, string(desCtrDeCrypt))
|
||||
}
|
||||
|
||||
func TestDesCfbEncrypt(t *testing.T) {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
|
||||
desCfbEncrypt := DesCfbEncrypt([]byte(data), []byte(key))
|
||||
desCfbDecrypt := DesCfbDecrypt(desCfbEncrypt, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestDesCfbEncrypt")
|
||||
assert.Equal(data, string(desCfbDecrypt))
|
||||
}
|
||||
|
||||
func TestDesOfbEncrypt(t *testing.T) {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
|
||||
desOfbEncrypt := DesOfbEncrypt([]byte(data), []byte(key))
|
||||
desOfbDecrypt := DesOfbDecrypt(desOfbEncrypt, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestDesOfbEncrypt")
|
||||
assert.Equal(data, string(desOfbDecrypt))
|
||||
}
|
||||
118
cryptor/rsa.go
118
cryptor/rsa.go
@@ -1,118 +0,0 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package cryptor implements some util functions to encrypt and decrypt.
|
||||
package cryptor
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"os"
|
||||
)
|
||||
|
||||
// GenerateRsaKey make a rsa private key, and return key file name
|
||||
// Generated key file is `rsa_private.pem` and `rsa_public.pem` in current path
|
||||
func GenerateRsaKey(keySize int, priKeyFile, pubKeyFile string) error {
|
||||
// private key
|
||||
privateKey, err := rsa.GenerateKey(rand.Reader, keySize)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
derText := x509.MarshalPKCS1PrivateKey(privateKey)
|
||||
|
||||
block := pem.Block{
|
||||
Type: "rsa private key",
|
||||
Bytes: derText,
|
||||
}
|
||||
|
||||
//file,err := os.Create("rsa_private.pem")
|
||||
file, err := os.Create(priKeyFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
pem.Encode(file, &block)
|
||||
file.Close()
|
||||
|
||||
// public key
|
||||
publicKey := privateKey.PublicKey
|
||||
|
||||
derpText, err := x509.MarshalPKIXPublicKey(&publicKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
block = pem.Block{
|
||||
Type: "rsa public key",
|
||||
Bytes: derpText,
|
||||
}
|
||||
|
||||
//file,err = os.Create("rsa_public.pem")
|
||||
file, err = os.Create(pubKeyFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pem.Encode(file, &block)
|
||||
file.Close()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RsaEncrypt encrypt data with ras algorithm
|
||||
func RsaEncrypt(data []byte, pubKeyFileName string) []byte {
|
||||
file, err := os.Open(pubKeyFileName)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fileInfo, err := file.Stat()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer file.Close()
|
||||
buf := make([]byte, fileInfo.Size())
|
||||
file.Read(buf)
|
||||
|
||||
block, _ := pem.Decode(buf)
|
||||
|
||||
pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
pubKey := pubInterface.(*rsa.PublicKey)
|
||||
|
||||
cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, pubKey, data)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return cipherText
|
||||
}
|
||||
|
||||
// RsaDecrypt decrypt data with ras algorithm
|
||||
func RsaDecrypt(data []byte, privateKeyFileName string) []byte {
|
||||
file, err := os.Open(privateKeyFileName)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fileInfo, err := file.Stat()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
buf := make([]byte, fileInfo.Size())
|
||||
defer file.Close()
|
||||
file.Read(buf)
|
||||
|
||||
block, _ := pem.Decode(buf)
|
||||
|
||||
priKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
plainText, err := rsa.DecryptPKCS1v15(rand.Reader, priKey, data)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return plainText
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package cryptor
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/internal"
|
||||
)
|
||||
|
||||
func TestRsaEncrypt(t *testing.T) {
|
||||
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
data := []byte("hello world")
|
||||
encrypted := RsaEncrypt(data, "rsa_public.pem")
|
||||
decrypted := RsaDecrypt(encrypted, "rsa_private.pem")
|
||||
|
||||
assert := internal.NewAssert(t, "TestRsaEncrypt")
|
||||
assert.Equal(string(data), string(decrypted))
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
// Package datetime implements some functions to format date and time.
|
||||
// Note:
|
||||
// 1. `format` param in FormatTimeToStr function should be as flow:
|
||||
// 1. `format` param in FormatTimeToStr function should be as flow (case no sensitive):
|
||||
// "yyyy-mm-dd hh:mm:ss"
|
||||
// "yyyy-mm-dd hh:mm"
|
||||
// "yyyy-mm-dd hh"
|
||||
@@ -18,14 +18,20 @@
|
||||
// "yyyy/mm"
|
||||
// "mm/dd"
|
||||
// "dd/mm/yy hh:mm:ss"
|
||||
// "yyyymmdd"
|
||||
// "mmddyy"
|
||||
// "yyyy"
|
||||
// "yy"
|
||||
// "mm"
|
||||
// "hh:mm:ss"
|
||||
// "hh:mm"
|
||||
// "mm:ss"
|
||||
|
||||
package datetime
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -47,9 +53,13 @@ func init() {
|
||||
"yyyy/mm": "2006/01",
|
||||
"mm/dd": "01/02",
|
||||
"dd/mm/yy hh:mm:ss": "02/01/06 15:04:05",
|
||||
"yyyymmdd": "20060102",
|
||||
"mmddyy": "010206",
|
||||
"yyyy": "2006",
|
||||
"yy": "06",
|
||||
"mm": "01",
|
||||
"hh:mm:ss": "15:04:05",
|
||||
"hh:mm": "15:04",
|
||||
"mm:ss": "04:05",
|
||||
}
|
||||
}
|
||||
@@ -102,18 +112,39 @@ func GetNightTimestamp() int64 {
|
||||
}
|
||||
|
||||
// FormatTimeToStr convert time to string
|
||||
func FormatTimeToStr(t time.Time, format string) string {
|
||||
return t.Format(timeFormat[format])
|
||||
func FormatTimeToStr(t time.Time, format string, timezone ...string) string {
|
||||
tf, ok := timeFormat[strings.ToLower(format)]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
|
||||
if timezone != nil && timezone[0] != "" {
|
||||
loc, err := time.LoadLocation(timezone[0])
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return t.In(loc).Format(tf)
|
||||
}
|
||||
return t.Format(tf)
|
||||
}
|
||||
|
||||
// FormatStrToTime convert string to time
|
||||
func FormatStrToTime(str, format string) (time.Time, error) {
|
||||
v, ok := timeFormat[format]
|
||||
func FormatStrToTime(str, format string, timezone ...string) (time.Time, error) {
|
||||
tf, ok := timeFormat[strings.ToLower(format)]
|
||||
if !ok {
|
||||
return time.Time{}, fmt.Errorf("format %s not found", format)
|
||||
return time.Time{}, fmt.Errorf("format %s not support", format)
|
||||
}
|
||||
|
||||
return time.Parse(v, str)
|
||||
if timezone != nil && timezone[0] != "" {
|
||||
loc, err := time.LoadLocation(timezone[0])
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
|
||||
return time.ParseInLocation(tf, str, loc)
|
||||
}
|
||||
|
||||
return time.Parse(tf, str)
|
||||
}
|
||||
|
||||
// BeginOfMinute return beginning minute time of day
|
||||
@@ -210,3 +241,83 @@ func DayOfYear(t time.Time) int {
|
||||
func IsWeekend(t time.Time) bool {
|
||||
return time.Saturday == t.Weekday() || time.Sunday == t.Weekday()
|
||||
}
|
||||
|
||||
// NowDateOrTime return current datetime with specific format and timezone.
|
||||
func NowDateOrTime(format string, timezone ...string) string {
|
||||
tf, ok := timeFormat[strings.ToLower(format)]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
|
||||
if timezone != nil && timezone[0] != "" {
|
||||
loc, err := time.LoadLocation(timezone[0])
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return time.Now().In(loc).Format(tf)
|
||||
}
|
||||
|
||||
return time.Now().Format(tf)
|
||||
}
|
||||
|
||||
// Timestamp return current second timestamp.
|
||||
func Timestamp(timezone ...string) int64 {
|
||||
t := time.Now()
|
||||
|
||||
if timezone != nil && timezone[0] != "" {
|
||||
loc, err := time.LoadLocation(timezone[0])
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
t = t.In(loc)
|
||||
}
|
||||
|
||||
return t.Unix()
|
||||
}
|
||||
|
||||
// TimestampMilli return current mill second timestamp.
|
||||
func TimestampMilli(timezone ...string) int64 {
|
||||
t := time.Now()
|
||||
|
||||
if timezone != nil && timezone[0] != "" {
|
||||
loc, err := time.LoadLocation(timezone[0])
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
t = t.In(loc)
|
||||
}
|
||||
|
||||
return int64(time.Nanosecond) * t.UnixNano() / int64(time.Millisecond)
|
||||
}
|
||||
|
||||
// TimestampMicro return current micro second timestamp.
|
||||
func TimestampMicro(timezone ...string) int64 {
|
||||
t := time.Now()
|
||||
|
||||
if timezone != nil && timezone[0] != "" {
|
||||
loc, err := time.LoadLocation(timezone[0])
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
t = t.In(loc)
|
||||
}
|
||||
|
||||
return int64(time.Nanosecond) * t.UnixNano() / int64(time.Microsecond)
|
||||
}
|
||||
|
||||
// TimestampNano return current nano second timestamp.
|
||||
func TimestampNano(timezone ...string) int64 {
|
||||
t := time.Now()
|
||||
|
||||
if timezone != nil && timezone[0] != "" {
|
||||
loc, err := time.LoadLocation(timezone[0])
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
t = t.In(loc)
|
||||
}
|
||||
|
||||
return t.UnixNano()
|
||||
}
|
||||
|
||||
@@ -298,3 +298,38 @@ func TestIsWeekend(t *testing.T) {
|
||||
result2 := IsWeekend(date2)
|
||||
assert.Equal(false, result2)
|
||||
}
|
||||
|
||||
func TestNowDateOrTime(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
formats := []string{
|
||||
"yyyy-mm-dd hh:mm:ss",
|
||||
"yyyy-mm-dd",
|
||||
"dd-mm-yy hh:mm:ss",
|
||||
"yyyy/mm/dd hh:mm:ss",
|
||||
"hh:mm:ss",
|
||||
"yyyy/mm",
|
||||
"yyyy-mm-dd hh",
|
||||
}
|
||||
|
||||
for i := 0; i < len(formats); i++ {
|
||||
result := NowDateOrTime(formats[i], "UTC")
|
||||
t.Log(result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimestamp(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ts1 := Timestamp()
|
||||
t.Log(ts1)
|
||||
|
||||
ts2 := TimestampMilli()
|
||||
t.Log(ts2)
|
||||
|
||||
ts3 := TimestampMicro()
|
||||
t.Log(ts3)
|
||||
|
||||
ts4 := TimestampNano()
|
||||
t.Log(ts4)
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ import (
|
||||
- [DeepClone](#DeepClone)
|
||||
- [CopyProperties](#CopyProperties)
|
||||
- [ToInterface](#ToInterface)
|
||||
- [Utf8ToGbk](#Utf8ToGbk)
|
||||
- [GbkToUtf8](#GbkToUtf8)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
@@ -606,15 +608,82 @@ import (
|
||||
|
||||
func main() {
|
||||
val := reflect.ValueOf("abc")
|
||||
iVal, ok := convertor.ToInterface(val)
|
||||
iVal, ok := convertor.ToInterface(val)
|
||||
|
||||
fmt.Printf("%T\n", iVal)
|
||||
fmt.Printf("%v\n", iVal)
|
||||
fmt.Println(ok)
|
||||
fmt.Printf("%T\n", iVal)
|
||||
fmt.Printf("%v\n", iVal)
|
||||
fmt.Println(ok)
|
||||
|
||||
// Output:
|
||||
// string
|
||||
// abc
|
||||
// true
|
||||
// Output:
|
||||
// string
|
||||
// abc
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Utf8ToGbk">Utf8ToGbk</span>
|
||||
|
||||
<p>Converts utf8 encoding data to GBK encoding data.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Utf8ToGbk(bs []byte) ([]byte, error)
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/convertor"
|
||||
"github.com/duke-git/lancet/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
utf8Data := []byte("hello")
|
||||
gbkData, _ := convertor.Utf8ToGbk(utf8Data)
|
||||
|
||||
fmt.Println(utf8.Valid(utf8Data))
|
||||
fmt.Println(validator.IsGBK(gbkData))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="GbkToUtf8">GbkToUtf8</span>
|
||||
|
||||
<p>Converts GBK encoding data to utf8 encoding data.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func GbkToUtf8(bs []byte) ([]byte, error)
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
gbkData, _ := convertor.Utf8ToGbk([]byte("hello"))
|
||||
utf8Data, _ := convertor.GbkToUtf8(gbkData)
|
||||
|
||||
fmt.Println(utf8.Valid(utf8Data))
|
||||
fmt.Println(string(utf8Data))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// hello
|
||||
}
|
||||
```
|
||||
@@ -38,6 +38,8 @@ import (
|
||||
- [DeepClone](#DeepClone)
|
||||
- [CopyProperties](#CopyProperties)
|
||||
- [ToInterface](#ToInterface)
|
||||
- [Utf8ToGbk](#Utf8ToGbk)
|
||||
- [GbkToUtf8](#GbkToUtf8)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -606,15 +608,82 @@ import (
|
||||
|
||||
func main() {
|
||||
val := reflect.ValueOf("abc")
|
||||
iVal, ok := convertor.ToInterface(val)
|
||||
iVal, ok := convertor.ToInterface(val)
|
||||
|
||||
fmt.Printf("%T\n", iVal)
|
||||
fmt.Printf("%v\n", iVal)
|
||||
fmt.Println(ok)
|
||||
fmt.Printf("%T\n", iVal)
|
||||
fmt.Printf("%v\n", iVal)
|
||||
fmt.Println(ok)
|
||||
|
||||
// Output:
|
||||
// string
|
||||
// abc
|
||||
// true
|
||||
// Output:
|
||||
// string
|
||||
// abc
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Utf8ToGbk">Utf8ToGbk</span>
|
||||
|
||||
<p>utf8编码转GBK编码。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Utf8ToGbk(bs []byte) ([]byte, error)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/convertor"
|
||||
"github.com/duke-git/lancet/validator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
utf8Data := []byte("hello")
|
||||
gbkData, _ := convertor.Utf8ToGbk(utf8Data)
|
||||
|
||||
fmt.Println(utf8.Valid(utf8Data))
|
||||
fmt.Println(validator.IsGBK(gbkData))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="GbkToUtf8">GbkToUtf8</span>
|
||||
|
||||
<p>GBK编码转utf8编码。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GbkToUtf8(bs []byte) ([]byte, error)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
gbkData, _ := convertor.Utf8ToGbk([]byte("hello"))
|
||||
utf8Data, _ := convertor.GbkToUtf8(gbkData)
|
||||
|
||||
fmt.Println(utf8.Valid(utf8Data))
|
||||
fmt.Println(string(utf8Data))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// hello
|
||||
}
|
||||
```
|
||||
309
docs/cryptor.md
309
docs/cryptor.md
@@ -6,10 +6,8 @@ Package cryptor contains some functions for data encryption and decryption. Supp
|
||||
|
||||
## Source:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/v1/cryptor/aes.go](https://github.com/duke-git/lancet/blob/v1/cryptor/aes.go)
|
||||
- [https://github.com/duke-git/lancet/blob/v1/cryptor/des.go](https://github.com/duke-git/lancet/blob/v1/cryptor/des.go)
|
||||
- [https://github.com/duke-git/lancet/blob/v1/cryptor/basic.go](https://github.com/duke-git/lancet/blob/v1/cryptor/basic.go)
|
||||
- [https://github.com/duke-git/lancet/blob/v1/cryptor/rsa.go](https://github.com/duke-git/lancet/blob/v1/cryptor/rsa.go)
|
||||
- [https://github.com/duke-git/lancet/blob/v1/cryptor/crypto.go](https://github.com/duke-git/lancet/blob/v1/cryptor/crypto.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -46,14 +44,24 @@ import (
|
||||
- [DesOfbEncrypt](#DesOfbEncrypt)
|
||||
- [DesOfbDecrypt](#DesOfbDecrypt)
|
||||
- [HmacMd5](#HmacMd5)
|
||||
- [HmacMd5WithBase64](#HmacMd5WithBase64)
|
||||
- [HmacSha1](#HmacSha1)
|
||||
- [HmacSha1WithBase64](#HmacSha1WithBase64)
|
||||
- [HmacSha256](#HmacSha256)
|
||||
- [HmacSha256WithBase64](#HmacSha256WithBase64)
|
||||
- [HmacSha512](#HmacSha512)
|
||||
- [HmacSha512WithBase64](#HmacSha512WithBase64)
|
||||
- [Md5String](#Md5String)
|
||||
- [Md5StringWithBase64](#Md5StringWithBase64)
|
||||
- [Md5Byte](#Md5Byte)
|
||||
- [Md5ByteWithBase64](#Md5ByteWithBase64)
|
||||
- [Md5File](#Md5File)
|
||||
- [Sha1](#Sha1)
|
||||
- [Sha1WithBase64](#Sha1WithBase64)
|
||||
- [Sha256](#Sha256)
|
||||
- [Sha256WithBase64](#Sha256WithBase64)
|
||||
- [Sha512](#Sha512)
|
||||
- [Sha512WithBase64](#Sha512WithBase64)
|
||||
- [GenerateRsaKey](#GenerateRsaKey)
|
||||
- [RsaEncrypt](#RsaEncrypt)
|
||||
- [RsaDecrypt](#RsaDecrypt)
|
||||
@@ -664,6 +672,32 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HmacMd5WithBase64">HmacMd5WithBase64</span>
|
||||
|
||||
<p>Return the hmac hash of string use md5 with base64.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func HmacMd5WithBase64(data, key string) string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.HmacMd5WithBase64("hello", "12345"))
|
||||
fmt.Println(s) //6DQwbquJLYclJdSRinpjmg==
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HmacSha1">HmacSha1</span>
|
||||
|
||||
<p>Get the sha1 hmac hash of string.</p>
|
||||
@@ -689,6 +723,37 @@ func main() {
|
||||
fmt.Println(s) //3826f812255d8683f051ee97346d1359234d5dbd
|
||||
}
|
||||
```
|
||||
### <span id="HmacSha1WithBase64">HmacSha1WithBase64</span>
|
||||
|
||||
<p>Return the hmac hash of string use sha1 with base64.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func HmacSha1WithBase64(str, key string) string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "hello"
|
||||
key := "12345"
|
||||
|
||||
hms := cryptor.HmacSha1WithBase64(str, key)
|
||||
fmt.Println(hms)
|
||||
|
||||
// Output:
|
||||
// XGqdsMzLkuNu0DI/0Jt/k23prOA=
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HmacSha256">HmacSha256</span>
|
||||
|
||||
@@ -716,6 +781,38 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HmacSha256WithBase64">HmacSha256WithBase64</span>
|
||||
|
||||
<p>Return the hmac hash of string use sha256 with base64.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func HmacSha256WithBase64(str, key string) string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "hello"
|
||||
key := "12345"
|
||||
|
||||
hms := cryptor.HmacSha256WithBase64(str, key)
|
||||
fmt.Println(hms)
|
||||
|
||||
// Output:
|
||||
// MVu5PE6YmGK6Ccti4F1zpfN2yzbw14btqwwyDQWf3nU=
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HmacSha512">HmacSha512</span>
|
||||
|
||||
<p>Get the sha512 hmac hash of string.</p>
|
||||
@@ -742,6 +839,38 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HmacSha512WithBase64">HmacSha512WithBase64</span>
|
||||
|
||||
<p>Return the hmac hash of string use sha512 with base64.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func HmacSha512WithBase64(str, key string) string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "hello"
|
||||
key := "12345"
|
||||
|
||||
hms := cryptor.HmacSha512WithBase64(str, key)
|
||||
fmt.Println(hms)
|
||||
|
||||
// Output:
|
||||
// 3Y8SkKndI9NU4lJtmi6c6M///dN8syCADRxsE9Lvw2Mog3ahlsVFja9T+OGqa0Wm2FYwPVwKIGS/+XhYYdSM/A==
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Md5String">Md5String</span>
|
||||
|
||||
<p>Get the md5 value of string.</p>
|
||||
@@ -768,6 +897,93 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Md5StringWithBase64">Md5StringWithBase64</span>
|
||||
|
||||
<p>Return the md5 value of string with base64.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Md5StringWithBase64(s string) string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
md5Str := cryptor.Md5StringWithBase64("hello")
|
||||
fmt.Println(md5Str)
|
||||
|
||||
// Output:
|
||||
// XUFAKrxLKna5cZ2REBfFkg==
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Md5Byte">Md5Byte</span>
|
||||
|
||||
<p>Return the md5 string of byte slice.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Md5Byte(data []byte) string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
md5Str := cryptor.Md5Byte([]byte{'a'})
|
||||
fmt.Println(md5Str)
|
||||
|
||||
// Output:
|
||||
// 0cc175b9c0f1b6a831c399e269772661
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Md5ByteWithBase64">Md5ByteWithBase64</span>
|
||||
|
||||
<p>Return the md5 string of byte slice with base64.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Md5ByteWithBase64(data []byte) string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
md5Str := cryptor.Md5ByteWithBase64([]byte("hello"))
|
||||
fmt.Println(md5Str)
|
||||
|
||||
// Output:
|
||||
// XUFAKrxLKna5cZ2REBfFkg==
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Md5File">Md5File</span>
|
||||
|
||||
<p>Get the md5 value of file.</p>
|
||||
@@ -820,6 +1036,35 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Sha1WithBase64">Sha1WithBase64</span>
|
||||
|
||||
<p>Return the sha1 value (SHA-1 hash algorithm) of base64 string.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Sha1WithBase64(str string) string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := cryptor.Sha1WithBase64("hello")
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// qvTGHdzF6KLavt4PO0gs2a6pQ00=
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Sha256">Sha256</span>
|
||||
|
||||
<p>Get the sha256 value of string.</p>
|
||||
@@ -846,6 +1091,35 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Sha256WithBase64">Sha256WithBase64</span>
|
||||
|
||||
<p>Return the sha256 value (SHA256 hash algorithm) of base64 string.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Sha256WithBase64(str string) string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := cryptor.Sha256WithBase64("hello")
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Sha512">Sha512</span>
|
||||
|
||||
<p>Get the sha512 value of string.</p>
|
||||
@@ -872,6 +1146,35 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Sha512WithBase64">Sha512WithBase64</span>
|
||||
|
||||
<p>Get the sha512 value of string with base64.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Sha512WithBase64(str string) string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := cryptor.Sha512WithBase64("hello")
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// m3HSJL1i83hdltRq0+o9czGb+8KJDKra4t/3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw==
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="GenerateRsaKey">GenerateRsaKey</span>
|
||||
|
||||
<p>Create the rsa public and private key file in current directory.</p>
|
||||
|
||||
@@ -6,10 +6,8 @@ cryptor 加密包支持数据加密和解密,获取 md5,hash 值。支持 ba
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/v1/cryptor/aes.go](https://github.com/duke-git/lancet/blob/v1/cryptor/aes.go)
|
||||
- [https://github.com/duke-git/lancet/blob/v1/cryptor/des.go](https://github.com/duke-git/lancet/blob/v1/cryptor/des.go)
|
||||
- [https://github.com/duke-git/lancet/blob/v1/cryptor/basic.go](https://github.com/duke-git/lancet/blob/v1/cryptor/basic.go)
|
||||
- [https://github.com/duke-git/lancet/blob/v1/cryptor/rsa.go](https://github.com/duke-git/lancet/blob/v1/cryptor/rsa.go)
|
||||
- [https://github.com/duke-git/lancet/blob/v1/cryptor/crypto.go](https://github.com/duke-git/lancet/blob/v1/cryptor/crypto.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -47,13 +45,22 @@ import (
|
||||
- [DesOfbDecrypt](#DesOfbDecrypt)
|
||||
- [HmacMd5](#HmacMd5)
|
||||
- [HmacSha1](#HmacSha1)
|
||||
- [HmacSha1WithBase64](#HmacSha1WithBase64)
|
||||
- [HmacSha256](#HmacSha256)
|
||||
- [HmacSha256WithBase64](#HmacSha256WithBase64)
|
||||
- [HmacSha512](#HmacSha512)
|
||||
- [HmacSha512WithBase64](#HmacSha512WithBase64)
|
||||
- [Md5String](#Md5String)
|
||||
- [Md5StringWithBase64](#Md5StringWithBase64)
|
||||
- [Md5Byte](#Md5Byte)
|
||||
- [Md5ByteWithBase64](#Md5ByteWithBase64)
|
||||
- [Md5File](#Md5File)
|
||||
- [Sha1](#Sha1)
|
||||
- [Sha1WithBase64](#Sha1WithBase64)
|
||||
- [Sha256](#Sha256)
|
||||
- [Sha256WithBase64](#Sha256WithBase64)
|
||||
- [Sha512](#Sha512)
|
||||
- [Sha512WithBase64](#Sha512WithBase64)
|
||||
- [GenerateRsaKey](#GenerateRsaKey)
|
||||
- [RsaEncrypt](#RsaEncrypt)
|
||||
- [RsaDecrypt](#RsaDecrypt)
|
||||
@@ -663,6 +670,32 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HmacMd5WithBase64">HmacMd5WithBase64</span>
|
||||
|
||||
<p>获取字符串md5 hmac base64值.</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func HmacMd5WithBase64(data, key string) string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.HmacMd5WithBase64("hello", "12345"))
|
||||
fmt.Println(s) //6DQwbquJLYclJdSRinpjmg==
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HmacSha1">HmacSha1</span>
|
||||
|
||||
<p>获取字符串sha1 hmac值</p>
|
||||
@@ -689,17 +722,17 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HmacSha256">HmacSha256</span>
|
||||
### <span id="HmacSha1WithBase64">HmacSha1WithBase64</span>
|
||||
|
||||
<p>获取字符串sha256 hmac值</p>
|
||||
<p>获取字符串的sha1 base64值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func HmacSha256(data, key string) string
|
||||
func HmacSha1WithBase64(str, key string) string
|
||||
```
|
||||
|
||||
<b>列子:</b>
|
||||
<b>实例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -710,22 +743,93 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.HmacSha256("hello world", "12345"))
|
||||
fmt.Println(s) //9dce2609f2d67d41f74c7f9efc8ccd44370d41ad2de52982627588dfe7289ab8
|
||||
str := "hello"
|
||||
key := "12345"
|
||||
|
||||
hms := cryptor.HmacSha1WithBase64(str, key)
|
||||
fmt.Println(hms)
|
||||
|
||||
// Output:
|
||||
// XGqdsMzLkuNu0DI/0Jt/k23prOA=
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="HmacSha256">HmacSha256</span>
|
||||
|
||||
<p>获取字符串sha256 hmac值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func HmacSha256(str, key string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "hello"
|
||||
key := "12345"
|
||||
|
||||
hms := cryptor.HmacSha256(str, key)
|
||||
fmt.Println(hms)
|
||||
|
||||
// Output:
|
||||
// 315bb93c4e989862ba09cb62e05d73a5f376cb36f0d786edab0c320d059fde75
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HmacSha256WithBase64">HmacSha256WithBase64</span>
|
||||
|
||||
<p>获取字符串sha256 hmac base64值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func HmacSha256WithBase64(str, key string) string
|
||||
```
|
||||
|
||||
<b>实例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "hello"
|
||||
key := "12345"
|
||||
|
||||
hms := cryptor.HmacSha256WithBase64(str, key)
|
||||
fmt.Println(hms)
|
||||
|
||||
// Output:
|
||||
// MVu5PE6YmGK6Ccti4F1zpfN2yzbw14btqwwyDQWf3nU=
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HmacSha512">HmacSha512</span>
|
||||
|
||||
<p>获取字符串sha512 hmac值</p>
|
||||
<p>获取字符串sha512 hmac值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func HmacSha512(data, key string) string
|
||||
func HmacSha512(str, key string) string
|
||||
```
|
||||
|
||||
<b>列子:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -736,23 +840,28 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.HmacSha512("hello world", "12345"))
|
||||
fmt.Println(s)
|
||||
//5b1563ac4e9b49c9ada8ccb232588fc4f0c30fd12f756b3a0b95af4985c236ca60925253bae10ce2c6bf9af1c1679b51e5395ff3d2826c0a2c7c0d72225d4175
|
||||
str := "hello"
|
||||
key := "12345"
|
||||
|
||||
hms := cryptor.HmacSha512(str, key)
|
||||
fmt.Println(hms)
|
||||
|
||||
// Output:
|
||||
// dd8f1290a9dd23d354e2526d9a2e9ce8cffffdd37cb320800d1c6c13d2efc363288376a196c5458daf53f8e1aa6b45a6d856303d5c0a2064bff9785861d48cfc
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Md5String">Md5String</span>
|
||||
### <span id="HmacSha512WithBase64">HmacSha512WithBase64</span>
|
||||
|
||||
<p>获取字符串md5值</p>
|
||||
<p>获取字符串sha512 hmac base64值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Md5String(s string) string
|
||||
func HmacSha512WithBase64(str, key string) string
|
||||
```
|
||||
|
||||
<b>列子:</b>
|
||||
<b>实例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -763,14 +872,139 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.Md5String("hello"))
|
||||
fmt.Println(s) //5d41402abc4b2a76b9719d911017c592
|
||||
str := "hello"
|
||||
key := "12345"
|
||||
|
||||
hms := cryptor.HmacSha512WithBase64(str, key)
|
||||
fmt.Println(hms)
|
||||
|
||||
// Output:
|
||||
// 3Y8SkKndI9NU4lJtmi6c6M///dN8syCADRxsE9Lvw2Mog3ahlsVFja9T+OGqa0Wm2FYwPVwKIGS/+XhYYdSM/A==
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Md5String">Md5String</span>
|
||||
|
||||
<p>获取字符串md5值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Md5String(str string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "hello"
|
||||
|
||||
md5Str := cryptor.Md5String(str)
|
||||
fmt.Println(md5Str)
|
||||
|
||||
// Output:
|
||||
// 5d41402abc4b2a76b9719d911017c592
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Md5StringWithBase64">Md5StringWithBase64</span>
|
||||
|
||||
<p>获取字符串md5 base64值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Md5StringWithBase64(s string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
md5Str := cryptor.Md5StringWithBase64("hello")
|
||||
fmt.Println(md5Str)
|
||||
|
||||
// Output:
|
||||
// XUFAKrxLKna5cZ2REBfFkg==
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Md5Byte">Md5Byte</span>
|
||||
|
||||
<p>获取byte slice的md5值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Md5Byte(data []byte) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
md5Str := cryptor.Md5Byte([]byte{'a'})
|
||||
fmt.Println(md5Str)
|
||||
|
||||
// Output:
|
||||
// 0cc175b9c0f1b6a831c399e269772661
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Md5ByteWithBase64">Md5ByteWithBase64</span>
|
||||
|
||||
<p>获取byte slice的md5 base64值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Md5ByteWithBase64(data []byte) string
|
||||
```
|
||||
|
||||
<b>实例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
md5Str := cryptor.Md5ByteWithBase64([]byte("hello"))
|
||||
fmt.Println(md5Str)
|
||||
|
||||
// Output:
|
||||
// XUFAKrxLKna5cZ2REBfFkg==
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Md5File">Md5File</span>
|
||||
|
||||
<p>获取文件md5值.</p>
|
||||
<p>获取文件md5值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -778,7 +1012,7 @@ func main() {
|
||||
func Md5File(filepath string) (string, error)
|
||||
```
|
||||
|
||||
<b>列子:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -796,15 +1030,15 @@ func main() {
|
||||
|
||||
### <span id="Sha1">Sha1</span>
|
||||
|
||||
<p>获取字符串sha1值</p>
|
||||
<p>获取字符串sha1值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Sha1(data string) string
|
||||
func Sha1(str string) string
|
||||
```
|
||||
|
||||
<b>列子:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -815,22 +1049,56 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.Sha1("hello world"))
|
||||
fmt.Println(s) //2aae6c35c94fcfb415dbe95f408b9ce91ee846ed
|
||||
str := "hello"
|
||||
|
||||
result := cryptor.Sha1(str)
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Sha1WithBase64">Sha1WithBase64</span>
|
||||
|
||||
<p>获取字符串sha1 base64值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Sha1WithBase64(str string) string
|
||||
```
|
||||
|
||||
<b>实例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := cryptor.Sha1WithBase64("hello")
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// qvTGHdzF6KLavt4PO0gs2a6pQ00=
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Sha256">Sha256</span>
|
||||
|
||||
<p>获取字符串sha256值</p>
|
||||
<p>获取字符串sha256值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Sha256(data string) string
|
||||
func Sha256(str string) string
|
||||
```
|
||||
|
||||
<b>列子:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -841,22 +1109,56 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.Sha256("hello world"))
|
||||
fmt.Println(s) //b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
|
||||
str := "hello"
|
||||
|
||||
result := cryptor.Sha256(str)
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Sha256WithBase64">Sha256WithBase64</span>
|
||||
|
||||
<p>获取字符串sha256 base64值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Sha256WithBase64(str string) string
|
||||
```
|
||||
|
||||
<b>实例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := cryptor.Sha256WithBase64("hello")
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Sha512">Sha512</span>
|
||||
|
||||
<p>获取字符串sha512值</p>
|
||||
<p>获取字符串sha512值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Sha512(data string) string
|
||||
func Sha512(str string) string
|
||||
```
|
||||
|
||||
<b>列子:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -867,8 +1169,42 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := cryptor.Sha512("hello world"))
|
||||
fmt.Println(s) //309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f
|
||||
str := "hello"
|
||||
|
||||
result := cryptor.Sha512(str)
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// 9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Sha512WithBase64">Sha512WithBase64</span>
|
||||
|
||||
<p>获取字符串sha512 base64值。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Sha512WithBase64(str string) string
|
||||
```
|
||||
|
||||
<b>实例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/cryptor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := cryptor.Sha512WithBase64("hello")
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// m3HSJL1i83hdltRq0+o9czGb+8KJDKra4t/3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw==
|
||||
}
|
||||
```
|
||||
|
||||
@@ -958,7 +1294,7 @@ func main() {
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
|
||||
data := []byte("hello world")
|
||||
encrypted := cryptor.RsaEncrypt(data, "rsa_public.pem")
|
||||
decrypted := cryptor.RsaDecrypt(encrypted, "rsa_private.pem")
|
||||
|
||||
227
docs/datetime.md
227
docs/datetime.md
@@ -57,6 +57,11 @@ import (
|
||||
- [BetweenSeconds](#BetweenSeconds)
|
||||
- [DayOfYear](#DayOfYear)
|
||||
- [IsWeekend](#IsWeekend)
|
||||
- [NowDateOrTime](#NowDateOrTime)
|
||||
- [Timestamp](#Timestamp)
|
||||
- [TimestampMilli](#TimestampMilli)
|
||||
- [TimestampMicro](#TimestampMicro)
|
||||
- [TimestampNano](#TimestampNano)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -64,7 +69,7 @@ import (
|
||||
|
||||
## Note:
|
||||
|
||||
1. 'format' string param in func FormatTimeToStr and FormatStrToTime function should be one of flows:
|
||||
1. In below functions, the `format` string param should be one of flows value (case no sensitive):
|
||||
|
||||
- yyyy-mm-dd hh:mm:ss
|
||||
- yyyy-mm-dd hh:mm
|
||||
@@ -75,14 +80,18 @@ import (
|
||||
- dd-mm-yy hh:mm:ss
|
||||
- yyyy/mm/dd hh:mm:ss
|
||||
- yyyy/mm/dd hh:mm
|
||||
- yyyy-mm-dd hh
|
||||
- yyyy/mm/dd hh
|
||||
- yyyy/mm/dd
|
||||
- yyyy/mm
|
||||
- mm/dd
|
||||
- dd/mm/yy hh:mm:ss
|
||||
- yyyymmdd
|
||||
- mmddyy
|
||||
- yyyy
|
||||
- yy
|
||||
- mm
|
||||
- hh:mm:ss
|
||||
- hh:mm
|
||||
- mm:ss
|
||||
|
||||
### <span id="AddDay">AddDay</span>
|
||||
@@ -199,18 +208,18 @@ import (
|
||||
func main() {
|
||||
now := time.Now()
|
||||
|
||||
after1Year := datetime.AddYear(now, 1)
|
||||
diff1 := after1Year.Sub(now)
|
||||
after1Year := datetime.AddYear(now, 1)
|
||||
diff1 := after1Year.Sub(now)
|
||||
|
||||
before1Year := datetime.AddYear(now, -1)
|
||||
diff2 := before1Year.Sub(now)
|
||||
before1Year := datetime.AddYear(now, -1)
|
||||
diff2 := before1Year.Sub(now)
|
||||
|
||||
fmt.Println(diff1)
|
||||
fmt.Println(diff2)
|
||||
fmt.Println(diff1)
|
||||
fmt.Println(diff2)
|
||||
|
||||
// Output:
|
||||
// 8760h0m0s
|
||||
// -8760h0m0s
|
||||
// Output:
|
||||
// 8760h0m0s
|
||||
// -8760h0m0s
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1036,7 +1045,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="DayOfYear">DayOfYear</span>
|
||||
|
||||
<p>Returns which day of the year the parameter date `t` is.</p>
|
||||
@@ -1157,3 +1165,198 @@ func main() {
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsWeekend">IsWeekend</span>
|
||||
|
||||
<p>Checks if passed time is weekend or not.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsWeekend(t time.Time) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
date1 := time.Date(2023, 06, 03, 0, 0, 0, 0, time.Local)
|
||||
date2 := time.Date(2023, 06, 04, 0, 0, 0, 0, time.Local)
|
||||
date3 := time.Date(2023, 06, 02, 0, 0, 0, 0, time.Local)
|
||||
|
||||
result1 := datetime.IsWeekend(date1)
|
||||
result2 := datetime.IsWeekend(date2)
|
||||
result3 := datetime.IsWeekend(date3)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="NowDateOrTime">NowDateOrTime</span>
|
||||
|
||||
<p>Return current datetime with specific format and timezone.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func NowDateOrTime(format string, timezone ...string) string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := datetime.NowDateOrTime("yyyy-mm-dd hh:mm:ss")
|
||||
|
||||
result2 := datetime.NowDateOrTime("yyyy-mm-dd hh:mm:ss", "EST")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 2023-07-26 15:01:30
|
||||
// 2023-07-26 02:01:30
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Timestamp">Timestamp</span>
|
||||
|
||||
<p>Return current second timestamp.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Timestamp(timezone ...string) int64
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ts := datetime.Timestamp()
|
||||
|
||||
fmt.Println(ts)
|
||||
|
||||
// Output:
|
||||
// 1690363051
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="TimestampMilli">TimestampMilli</span>
|
||||
|
||||
<p>Return current mill second timestamp.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func TimestampMilli(timezone ...string) int64
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ts := datetime.TimestampMilli()
|
||||
|
||||
fmt.Println(ts)
|
||||
|
||||
// Output:
|
||||
// 1690363051331
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="TimestampMicro">TimestampMicro</span>
|
||||
|
||||
<p>Return current micro second timestamp.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func TimestampMicro(timezone ...string) int64
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ts := datetime.TimestampMicro()
|
||||
|
||||
fmt.Println(ts)
|
||||
|
||||
// Output:
|
||||
// 1690363051331784
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="TimestampNano">TimestampNano</span>
|
||||
|
||||
<p>Return current nano second timestamp.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func TimestampNano(timezone ...string) int64
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ts := datetime.TimestampNano()
|
||||
|
||||
fmt.Println(ts)
|
||||
|
||||
// Output:
|
||||
// 1690363051331788000
|
||||
}
|
||||
```
|
||||
|
||||
@@ -57,7 +57,11 @@ import (
|
||||
- [BetweenSeconds](#BetweenSeconds)
|
||||
- [DayOfYear](#DayOfYear)
|
||||
- [IsWeekend](#IsWeekend)
|
||||
|
||||
- [NowDateOrTime](#NowDateOrTime)
|
||||
- [Timestamp](#Timestamp)
|
||||
- [TimestampMilli](#TimestampMilli)
|
||||
- [TimestampMicro](#TimestampMicro)
|
||||
- [TimestampNano](#TimestampNano)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -65,7 +69,7 @@ import (
|
||||
|
||||
## 注:
|
||||
|
||||
1. 方法 FormatTimeToStr 和 FormatStrToTime 中的 format 参数值需要传以下类型之一:
|
||||
1. 函数中`format`参数值需要传以下值之一 (忽略大小写):
|
||||
|
||||
- yyyy-mm-dd hh:mm:ss
|
||||
- yyyy-mm-dd hh:mm
|
||||
@@ -76,14 +80,18 @@ import (
|
||||
- dd-mm-yy hh:mm:ss
|
||||
- yyyy/mm/dd hh:mm:ss
|
||||
- yyyy/mm/dd hh:mm
|
||||
- yyyy-mm-dd hh
|
||||
- yyyy/mm/dd hh
|
||||
- yyyy/mm/dd
|
||||
- yyyy/mm
|
||||
- mm/dd
|
||||
- dd/mm/yy hh:mm:ss
|
||||
- yyyymmdd
|
||||
- mmddyy
|
||||
- yyyy
|
||||
- yy
|
||||
- mm
|
||||
- hh:mm:ss
|
||||
- hh:mm
|
||||
- mm:ss
|
||||
|
||||
### <span id="AddDay">AddDay</span>
|
||||
@@ -200,18 +208,18 @@ import (
|
||||
func main() {
|
||||
now := time.Now()
|
||||
|
||||
after1Year := datetime.AddYear(now, 1)
|
||||
diff1 := after1Year.Sub(now)
|
||||
after1Year := datetime.AddYear(now, 1)
|
||||
diff1 := after1Year.Sub(now)
|
||||
|
||||
before1Year := datetime.AddYear(now, -1)
|
||||
diff2 := before1Year.Sub(now)
|
||||
before1Year := datetime.AddYear(now, -1)
|
||||
diff2 := before1Year.Sub(now)
|
||||
|
||||
fmt.Println(diff1)
|
||||
fmt.Println(diff2)
|
||||
fmt.Println(diff1)
|
||||
fmt.Println(diff2)
|
||||
|
||||
// Output:
|
||||
// 8760h0m0s
|
||||
// -8760h0m0s
|
||||
// Output:
|
||||
// 8760h0m0s
|
||||
// -8760h0m0s
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1077,3 +1085,198 @@ func main() {
|
||||
// 0
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsWeekend">IsWeekend</span>
|
||||
|
||||
<p>判断日期是否是周末。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsWeekend(t time.Time) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
date1 := time.Date(2023, 06, 03, 0, 0, 0, 0, time.Local)
|
||||
date2 := time.Date(2023, 06, 04, 0, 0, 0, 0, time.Local)
|
||||
date3 := time.Date(2023, 06, 02, 0, 0, 0, 0, time.Local)
|
||||
|
||||
result1 := datetime.IsWeekend(date1)
|
||||
result2 := datetime.IsWeekend(date2)
|
||||
result3 := datetime.IsWeekend(date3)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="NowDateOrTime">NowDateOrTime</span>
|
||||
|
||||
<p>根据指定的格式和时区返回当前时间字符串。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func NowDateOrTime(format string, timezone ...string) string
|
||||
```
|
||||
|
||||
<b>实例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := datetime.NowDateOrTime("yyyy-mm-dd hh:mm:ss")
|
||||
|
||||
result2 := datetime.NowDateOrTime("yyyy-mm-dd hh:mm:ss", "EST")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 2023-07-26 15:01:30
|
||||
// 2023-07-26 02:01:30
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Timestamp">Timestamp</span>
|
||||
|
||||
<p>返回当前秒级时间戳。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Timestamp(timezone ...string) int64
|
||||
```
|
||||
|
||||
<b>实例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ts := datetime.Timestamp()
|
||||
|
||||
fmt.Println(ts)
|
||||
|
||||
// Output:
|
||||
// 1690363051
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="TimestampMilli">TimestampMilli</span>
|
||||
|
||||
<p>返回当前毫秒级时间戳。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func TimestampMilli(timezone ...string) int64
|
||||
```
|
||||
|
||||
<b>实例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ts := datetime.TimestampMilli()
|
||||
|
||||
fmt.Println(ts)
|
||||
|
||||
// Output:
|
||||
// 1690363051331
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="TimestampMicro">TimestampMicro</span>
|
||||
|
||||
<p>返回当前微秒级时间戳。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func TimestampMicro(timezone ...string) int64
|
||||
```
|
||||
|
||||
<b>实例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ts := datetime.TimestampMicro()
|
||||
|
||||
fmt.Println(ts)
|
||||
|
||||
// Output:
|
||||
// 1690363051331784
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="TimestampNano">TimestampNano</span>
|
||||
|
||||
<p>返回当前纳秒级时间戳。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func TimestampNano(timezone ...string) int64
|
||||
```
|
||||
|
||||
<b>实例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ts := datetime.TimestampNano()
|
||||
|
||||
fmt.Println(ts)
|
||||
|
||||
// Output:
|
||||
// 1690363051331788000
|
||||
}
|
||||
```
|
||||
138
docs/fileutil.md
138
docs/fileutil.md
@@ -37,12 +37,14 @@ import (
|
||||
- [ReadFileByLine](#ReadFileByLine)
|
||||
- [Zip](#Zip)
|
||||
- [UnZip](#UnZip)
|
||||
- [ZipAppendEntry](#ZipAppendEntry)
|
||||
- [CurrentPath](#CurrentPath)
|
||||
- [IsZipFile](#IsZipFile)
|
||||
- [FileSize](#FileSize)
|
||||
- [MTime](#MTime)
|
||||
- [Sha](#Sha)
|
||||
- [ReadCsvFile](#ReadCsvFile)
|
||||
- [WriteCsvFile](#WriteCsvFile)
|
||||
- [WriteStringToFile](#WriteStringToFile)
|
||||
- [WriteBytesToFile](#WriteBytesToFile)
|
||||
|
||||
@@ -477,6 +479,34 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ZipAppendEntry">ZipAppendEntry</span>
|
||||
|
||||
<p>Append a single file or directory by fpath to an existing zip file.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ZipAppendEntry(fpath string, destPath string) error
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.ZipAppendEntry("./test.txt", "./test.zip")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="CurrentPath">CurrentPath</span>
|
||||
|
||||
<p>return current absolute path.</p>
|
||||
@@ -503,7 +533,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="IsZipFile">IsZipFile</span>
|
||||
|
||||
<p>Checks if file is zip file or not.</p>
|
||||
@@ -664,6 +693,42 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="WriteCsvFile">WriteCsvFile</span>
|
||||
|
||||
<p>Write content to target csv file.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func WriteCsvFile(filepath string, records [][]string, append bool) error
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
data := [][]string{
|
||||
{"Lili", "22", "female"},
|
||||
{"Jim", "21", "male"},
|
||||
}
|
||||
err := WriteCsvFile("./testdata/test2.csv", data, false)
|
||||
fmt.Println(err)
|
||||
|
||||
content, _ := ReadCsvFile("./testdata/test2.csv")
|
||||
fmt.Println(content)
|
||||
|
||||
// Output:
|
||||
// <nil>
|
||||
// [[Lili 22 female] [Jim 21 male]]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="WriteBytesToFile">WriteBytesToFile</span>
|
||||
|
||||
@@ -688,33 +753,32 @@ import (
|
||||
func main() {
|
||||
filepath := "./bytes.txt"
|
||||
|
||||
file, err := os.Create(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
file, err := os.Create(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
defer file.Close()
|
||||
|
||||
err = fileutil.WriteBytesToFile(filepath, []byte("hello"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = fileutil.WriteBytesToFile(filepath, []byte("hello"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
content, err := fileutil.ReadFileToString(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
content, err := fileutil.ReadFileToString(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
os.Remove(filepath)
|
||||
os.Remove(filepath)
|
||||
|
||||
fmt.Println(content)
|
||||
fmt.Println(content)
|
||||
|
||||
// Output:
|
||||
// hello
|
||||
// Output:
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="WriteStringToFile">WriteStringToFile</span>
|
||||
|
||||
<p>Writes string to target file.</p>
|
||||
@@ -738,28 +802,28 @@ import (
|
||||
func main() {
|
||||
filepath := "./test.txt"
|
||||
|
||||
file, err := os.Create(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
file, err := os.Create(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
defer file.Close()
|
||||
|
||||
err = fileutil.WriteStringToFile(filepath, "hello", true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = fileutil.WriteStringToFile(filepath, "hello", true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
content, err := fileutil.ReadFileToString(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
content, err := fileutil.ReadFileToString(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
os.Remove(filepath)
|
||||
os.Remove(filepath)
|
||||
|
||||
fmt.Println(content)
|
||||
fmt.Println(content)
|
||||
|
||||
// Output:
|
||||
// hello
|
||||
// Output:
|
||||
// hello
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
@@ -30,19 +30,21 @@ import (
|
||||
- [MiMeType](#MiMeType)
|
||||
- [IsExist](#IsExist)
|
||||
- [IsLink](#IsLink)
|
||||
- [IsDir](#IsDir)
|
||||
- [IsDir](#IsDir)画
|
||||
- [ListFileNames](#ListFileNames)
|
||||
- [RemoveFile](#RemoveFile)
|
||||
- [ReadFileToString](#ReadFileToString)
|
||||
- [ReadFileByLine](#ReadFileByLine)
|
||||
- [Zip](#Zip)
|
||||
- [UnZip](#UnZip)
|
||||
- [ZipAppendEntry](#ZipAppendEntry)
|
||||
- [CurrentPath](#CurrentPath)
|
||||
- [IsZipFile](#IsZipFile)
|
||||
- [FileSize](#FileSize)
|
||||
- [MTime](#MTime)
|
||||
- [Sha](#Sha)
|
||||
- [ReadCsvFile](#ReadCsvFile)
|
||||
- [WriteCsvFile](#WriteCsvFile)
|
||||
- [WriteStringToFile](#WriteStringToFile)
|
||||
- [WriteBytesToFile](#WriteBytesToFile)
|
||||
|
||||
@@ -477,6 +479,34 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ZipAppendEntry">ZipAppendEntry</span>
|
||||
|
||||
<p>通过将单个文件或目录追加到现有的zip文件</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ZipAppendEntry(fpath string, destPath string) error
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.ZipAppendEntry("./test.txt", "./test.zip")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="CurrentPath">CurrentPath</span>
|
||||
|
||||
<p>返回当前位置的绝对路径。</p>
|
||||
@@ -503,7 +533,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="IsZipFile">IsZipFile</span>
|
||||
|
||||
<p>判断文件是否是zip压缩文件。</p>
|
||||
@@ -664,6 +693,43 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="WriteCsvFile">WriteCsvFile</span>
|
||||
|
||||
<p>向csv文件写入内容。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func WriteCsvFile(filepath string, records [][]string, append bool) error
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
data := [][]string{
|
||||
{"Lili", "22", "female"},
|
||||
{"Jim", "21", "male"},
|
||||
}
|
||||
err := WriteCsvFile("./testdata/test2.csv", data, false)
|
||||
fmt.Println(err)
|
||||
|
||||
content, _ := ReadCsvFile("./testdata/test2.csv")
|
||||
fmt.Println(content)
|
||||
|
||||
// Output:
|
||||
// <nil>
|
||||
// [[Lili 22 female] [Jim 21 male]]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="WriteBytesToFile">WriteBytesToFile</span>
|
||||
|
||||
<p>将bytes写入文件。</p>
|
||||
@@ -687,33 +753,32 @@ import (
|
||||
func main() {
|
||||
filepath := "./bytes.txt"
|
||||
|
||||
file, err := os.Create(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
file, err := os.Create(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
defer file.Close()
|
||||
|
||||
err = fileutil.WriteBytesToFile(filepath, []byte("hello"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = fileutil.WriteBytesToFile(filepath, []byte("hello"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
content, err := fileutil.ReadFileToString(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
content, err := fileutil.ReadFileToString(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
os.Remove(filepath)
|
||||
os.Remove(filepath)
|
||||
|
||||
fmt.Println(content)
|
||||
fmt.Println(content)
|
||||
|
||||
// Output:
|
||||
// hello
|
||||
// Output:
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="WriteStringToFile">WriteStringToFile</span>
|
||||
|
||||
<p>将字符串写入文件。</p>
|
||||
@@ -737,28 +802,28 @@ import (
|
||||
func main() {
|
||||
filepath := "./test.txt"
|
||||
|
||||
file, err := os.Create(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
file, err := os.Create(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
defer file.Close()
|
||||
|
||||
err = fileutil.WriteStringToFile(filepath, "hello", true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = fileutil.WriteStringToFile(filepath, "hello", true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
content, err := fileutil.ReadFileToString(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
content, err := fileutil.ReadFileToString(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
os.Remove(filepath)
|
||||
os.Remove(filepath)
|
||||
|
||||
fmt.Println(content)
|
||||
fmt.Println(content)
|
||||
|
||||
// Output:
|
||||
// hello
|
||||
// Output:
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
@@ -323,16 +323,16 @@ import (
|
||||
|
||||
func main() {
|
||||
addOne := func(x interface{}) interface{} {
|
||||
return x.(int) + 1
|
||||
}
|
||||
double := func(x interface{}) interface{} {
|
||||
return 2 * x.(int)
|
||||
}
|
||||
square := func(x interface{}) interface{} {
|
||||
return x.(int) * x.(int)
|
||||
}
|
||||
return x.(int) + 1
|
||||
}
|
||||
double := func(x interface{}) interface{} {
|
||||
return 2 * x.(int)
|
||||
}
|
||||
square := func(x interface{}) interface{} {
|
||||
return x.(int) * x.(int)
|
||||
}
|
||||
|
||||
f := function.Pipeline(addOne, double, square)
|
||||
f := function.Pipeline(addOne, double, square)
|
||||
|
||||
result := fn(2)
|
||||
|
||||
|
||||
@@ -322,16 +322,16 @@ import (
|
||||
|
||||
func main() {
|
||||
addOne := func(x interface{}) interface{} {
|
||||
return x.(int) + 1
|
||||
}
|
||||
double := func(x interface{}) interface{} {
|
||||
return 2 * x.(int)
|
||||
}
|
||||
square := func(x interface{}) interface{} {
|
||||
return x.(int) * x.(int)
|
||||
}
|
||||
return x.(int) + 1
|
||||
}
|
||||
double := func(x interface{}) interface{} {
|
||||
return 2 * x.(int)
|
||||
}
|
||||
square := func(x interface{}) interface{} {
|
||||
return x.(int) * x.(int)
|
||||
}
|
||||
|
||||
f := function.Pipeline(addOne, double, square)
|
||||
f := function.Pipeline(addOne, double, square)
|
||||
|
||||
result := fn(2)
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ import (
|
||||
- [LCM](#LCM)
|
||||
- [Cos](#Cos)
|
||||
- [Sin](#Sin)
|
||||
- [Log](#Log)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -363,20 +364,20 @@ import (
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.IsPrime(-1)
|
||||
result2 := mathutil.IsPrime(0)
|
||||
result3 := mathutil.IsPrime(1)
|
||||
result4 := mathutil.IsPrime(2)
|
||||
result2 := mathutil.IsPrime(0)
|
||||
result3 := mathutil.IsPrime(1)
|
||||
result4 := mathutil.IsPrime(2)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// false
|
||||
// false
|
||||
// false
|
||||
// true
|
||||
// Output:
|
||||
// false
|
||||
// false
|
||||
// false
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
@@ -458,7 +459,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Cos">Cos</span>
|
||||
|
||||
<p>Returns the cosine of the radian argument.</p>
|
||||
@@ -501,7 +501,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Sin">Sin</span>
|
||||
|
||||
<p>Returns the sine of the radian argument.</p>
|
||||
@@ -542,4 +541,40 @@ func main() {
|
||||
// 0
|
||||
// 1
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
### <span id="Log">Log</span>
|
||||
|
||||
<p>Returns the logarithm of base n.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Log(n, base float64) float64
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Log(8, 2)
|
||||
result2 := mathutil.TruncRound(mathutil.Log(5, 2), 2)
|
||||
result3 := mathutil.TruncRound(mathutil.Log(27, 3), 0)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 3
|
||||
// 2.32
|
||||
// 3
|
||||
}
|
||||
```
|
||||
|
||||
@@ -37,6 +37,7 @@ import (
|
||||
- [LCM](#LCM)
|
||||
- [Cos](#Cos)
|
||||
- [Sin](#Sin)
|
||||
- [Log](#Log)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -363,20 +364,20 @@ import (
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.IsPrime(-1)
|
||||
result2 := mathutil.IsPrime(0)
|
||||
result3 := mathutil.IsPrime(1)
|
||||
result4 := mathutil.IsPrime(2)
|
||||
result2 := mathutil.IsPrime(0)
|
||||
result3 := mathutil.IsPrime(1)
|
||||
result4 := mathutil.IsPrime(2)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// false
|
||||
// false
|
||||
// false
|
||||
// true
|
||||
// Output:
|
||||
// false
|
||||
// false
|
||||
// false
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
@@ -543,4 +544,40 @@ func main() {
|
||||
// 0
|
||||
// 1
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Log">Log</span>
|
||||
|
||||
<p>计算以base为底n的对数。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Log(n, base float64) float64
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Log(8, 2)
|
||||
result2 := mathutil.TruncRound(mathutil.Log(5, 2), 2)
|
||||
result3 := mathutil.TruncRound(mathutil.Log(27, 3), 0)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 3
|
||||
// 2.32
|
||||
// 3
|
||||
}
|
||||
```
|
||||
@@ -658,24 +658,24 @@ import (
|
||||
func main() {
|
||||
url := "https://jsonplaceholder.typicode.com/todos"
|
||||
header := map[string]string{
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
// "Content-Type": "multipart/form-data",
|
||||
}
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
// "Content-Type": "multipart/form-data",
|
||||
}
|
||||
|
||||
postData := url.Values{}
|
||||
postData.Add("userId", "1")
|
||||
postData.Add("title", "TestToDo")
|
||||
postData := url.Values{}
|
||||
postData.Add("userId", "1")
|
||||
postData.Add("title", "TestToDo")
|
||||
|
||||
// postData := make(map[string]string)
|
||||
// postData["userId"] = "1"
|
||||
// postData["title"] = "title"
|
||||
// postData := make(map[string]string)
|
||||
// postData["userId"] = "1"
|
||||
// postData["title"] = "title"
|
||||
|
||||
resp, err := netutil.HttpPost(apiUrl, header, nil, postData)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
t.Log("response: ", resp.StatusCode, string(body))
|
||||
resp, err := netutil.HttpPost(apiUrl, header, nil, postData)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
t.Log("response: ", resp.StatusCode, string(body))
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -657,23 +657,23 @@ import (
|
||||
func main() {
|
||||
url := "https://jsonplaceholder.typicode.com/todos"
|
||||
header := map[string]string{
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
// "Content-Type": "multipart/form-data",
|
||||
}
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
// "Content-Type": "multipart/form-data",
|
||||
}
|
||||
|
||||
postData := url.Values{}
|
||||
postData.Add("userId", "1")
|
||||
postData.Add("title", "TestToDo")
|
||||
postData := url.Values{}
|
||||
postData.Add("userId", "1")
|
||||
postData.Add("title", "TestToDo")
|
||||
|
||||
// postData := make(map[string]string)
|
||||
// postData["userId"] = "1"
|
||||
// postData["title"] = "title"
|
||||
// postData := make(map[string]string)
|
||||
// postData["userId"] = "1"
|
||||
// postData["title"] = "title"
|
||||
|
||||
resp, err := netutil.HttpPost(apiUrl, header, nil, postData)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
resp, err := netutil.HttpPost(apiUrl, header, nil, postData)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
fmt.Println(body)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -30,6 +30,7 @@ import (
|
||||
- [RandNumeral](#RandNumeral)
|
||||
- [RandNumeralOrLetter](#RandNumeralOrLetter)
|
||||
- [UUIdV4](#UUIdV4)
|
||||
- [RandUniqueIntSlice](#RandUniqueIntSlice)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -245,3 +246,29 @@ func main() {
|
||||
fmt.Println(uuid)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RandUniqueIntSlice">RandUniqueIntSlice</span>
|
||||
|
||||
<p>Generate a slice of random int of length n that do not repeat.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RandUniqueIntSlice(n, min, max int) []int
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := RandUniqueIntSlice(5, 0, 10)
|
||||
fmt.Println(result) //[0 4 7 1 5] (random)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -30,6 +30,7 @@ import (
|
||||
- [RandNumeral](#RandNumeral)
|
||||
- [RandNumeralOrLetter](#RandNumeralOrLetter)
|
||||
- [UUIdV4](#UUIdV4)
|
||||
- [RandUniqueIntSlice](#RandUniqueIntSlice)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -245,3 +246,29 @@ func main() {
|
||||
fmt.Println(uuid)
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RandUniqueIntSlice">RandUniqueIntSlice</span>
|
||||
|
||||
<p>生成一个不重复的长度为n的随机int切片。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RandUniqueIntSlice(n, min, max int) []int
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := RandUniqueIntSlice(5, 0, 10)
|
||||
fmt.Println(result) //[0 4 7 1 5] (random)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -62,6 +62,7 @@ import (
|
||||
- [Union](#Union)
|
||||
- [UpdateByIndex](#UpdateByIndex)
|
||||
- [Without](#Without)
|
||||
- [Join](#Join)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -1172,3 +1173,36 @@ func main() {
|
||||
fmt.Println(res) //[]int{3, 4, 5}
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Join">Join</span>
|
||||
|
||||
<p>Join the slice item with specify separator.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Join(slice interface{}, separator string) string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
|
||||
result1 := slice.Join(nums, ",")
|
||||
result2 := slice.Join(nums, "-")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 1,2,3,4,5
|
||||
// 1-2-3-4-5
|
||||
}
|
||||
```
|
||||
|
||||
@@ -62,6 +62,8 @@ import (
|
||||
- [Union](#Union)
|
||||
- [UpdateByIndex](#UpdateByIndex)
|
||||
- [Without](#Without)
|
||||
- [Join](#Join)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -1168,3 +1170,36 @@ func main() {
|
||||
fmt.Println(res) //[]int{3, 4, 5}
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Join">Join</span>
|
||||
|
||||
<p>用指定的分隔符链接切片元素。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Join(slice interface{}, separator string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
|
||||
result1 := slice.Join(nums, ",")
|
||||
result2 := slice.Join(nums, "-")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 1,2,3,4,5
|
||||
// 1-2-3-4-5
|
||||
}
|
||||
```
|
||||
|
||||
204
docs/strutil.md
204
docs/strutil.md
@@ -57,6 +57,7 @@ import (
|
||||
- [Trim](#Trim)
|
||||
- [SplitAndTrim](#SplitAndTrim)
|
||||
- [HideString](#HideString)
|
||||
- [RemoveWhiteSpace](#RemoveWhiteSpace)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -857,13 +858,13 @@ import (
|
||||
|
||||
func main() {
|
||||
result1 := strutil.StringToBytes("abc")
|
||||
result2 := reflect.DeepEqual(result1, []byte{'a', 'b', 'c'})
|
||||
result2 := reflect.DeepEqual(result1, []byte{'a', 'b', 'c'})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
// Output:
|
||||
// [97 98 99]
|
||||
// true
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
// Output:
|
||||
// [97 98 99]
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
@@ -887,11 +888,11 @@ import (
|
||||
|
||||
func main() {
|
||||
bytes := []byte{'a', 'b', 'c'}
|
||||
result := strutil.BytesToString(bytes)
|
||||
result := strutil.BytesToString(bytes)
|
||||
|
||||
fmt.Println(result)
|
||||
// Output:
|
||||
// abc
|
||||
fmt.Println(result)
|
||||
// Output:
|
||||
// abc
|
||||
}
|
||||
```
|
||||
|
||||
@@ -915,16 +916,16 @@ import (
|
||||
|
||||
func main() {
|
||||
result1 := strutil.IsBlank("")
|
||||
result2 := strutil.IsBlank("\t\v\f\n")
|
||||
result3 := strutil.IsBlank(" 中文")
|
||||
result2 := strutil.IsBlank("\t\v\f\n")
|
||||
result3 := strutil.IsBlank(" 中文")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
@@ -948,13 +949,13 @@ import (
|
||||
|
||||
func main() {
|
||||
result1 := strutil.HasPrefixAny("foo bar", []string{"fo", "xyz", "hello"})
|
||||
result2 := strutil.HasPrefixAny("foo bar", []string{"oom", "world"})
|
||||
result2 := strutil.HasPrefixAny("foo bar", []string{"oom", "world"})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
@@ -978,13 +979,13 @@ import (
|
||||
|
||||
func main() {
|
||||
result1 := strutil.HasSuffixAny("foo bar", []string{"bar", "xyz", "hello"})
|
||||
result2 := strutil.HasSuffixAny("foo bar", []string{"oom", "world"})
|
||||
result2 := strutil.HasSuffixAny("foo bar", []string{"oom", "world"})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1009,23 +1010,23 @@ import (
|
||||
func main() {
|
||||
str := "foo bar hello world"
|
||||
|
||||
result1 := strutil.IndexOffset(str, "o", 5)
|
||||
result2 := strutil.IndexOffset(str, "o", 0)
|
||||
result3 := strutil.IndexOffset(str, "d", len(str)-1)
|
||||
result4 := strutil.IndexOffset(str, "d", len(str))
|
||||
result5 := strutil.IndexOffset(str, "f", -1)
|
||||
result1 := strutil.IndexOffset(str, "o", 5)
|
||||
result2 := strutil.IndexOffset(str, "o", 0)
|
||||
result3 := strutil.IndexOffset(str, "d", len(str)-1)
|
||||
result4 := strutil.IndexOffset(str, "d", len(str))
|
||||
result5 := strutil.IndexOffset(str, "f", -1)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
// Output:
|
||||
// 12
|
||||
// 1
|
||||
// 18
|
||||
// -1
|
||||
// -1
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
// Output:
|
||||
// 12
|
||||
// 1
|
||||
// 18
|
||||
// -1
|
||||
// -1
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1049,16 +1050,16 @@ import (
|
||||
|
||||
func main() {
|
||||
str := "ac ab ab ac"
|
||||
replaces := map[string]string{
|
||||
"a": "1",
|
||||
"b": "2",
|
||||
}
|
||||
replaces := map[string]string{
|
||||
"a": "1",
|
||||
"b": "2",
|
||||
}
|
||||
|
||||
result := strutil.ReplaceWithMap(str, replaces)
|
||||
result := strutil.ReplaceWithMap(str, replaces)
|
||||
|
||||
fmt.Println(result)
|
||||
// Output:
|
||||
// 1c 12 12 1c
|
||||
fmt.Println(result)
|
||||
// Output:
|
||||
// 1c 12 12 1c
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1083,19 +1084,19 @@ import (
|
||||
func main() {
|
||||
result1 := strutil.Trim("\nabcd")
|
||||
|
||||
str := "$ ab cd $ "
|
||||
str := "$ ab cd $ "
|
||||
|
||||
result2 := strutil.Trim(str)
|
||||
result3 := strutil.Trim(str, "$")
|
||||
result2 := strutil.Trim(str)
|
||||
result3 := strutil.Trim(str, "$")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// abcd
|
||||
// $ ab cd $
|
||||
// ab cd
|
||||
// Output:
|
||||
// abcd
|
||||
// $ ab cd $
|
||||
// ab cd
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1120,15 +1121,15 @@ import (
|
||||
func main() {
|
||||
str := " a,b, c,d,$1 "
|
||||
|
||||
result1 := strutil.SplitAndTrim(str, ",")
|
||||
result2 := strutil.SplitAndTrim(str, ",", "$")
|
||||
result1 := strutil.SplitAndTrim(str, ",")
|
||||
result2 := strutil.SplitAndTrim(str, ",", "$")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// [a b c d $1]
|
||||
// [a b c d 1]
|
||||
// Output:
|
||||
// [a b c d $1]
|
||||
// [a b c d 1]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1153,21 +1154,21 @@ import (
|
||||
func main() {
|
||||
str := "13242658976"
|
||||
|
||||
result1 := strutil.HideString(str, 3, 3, "*")
|
||||
result2 := strutil.HideString(str, 3, 4, "*")
|
||||
result3 := strutil.HideString(str, 3, 7, "*")
|
||||
result4 := strutil.HideString(str, 7, 11, "*")
|
||||
result1 := strutil.HideString(str, 3, 3, "*")
|
||||
result2 := strutil.HideString(str, 3, 4, "*")
|
||||
result3 := strutil.HideString(str, 3, 7, "*")
|
||||
result4 := strutil.HideString(str, 7, 11, "*")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// 13242658976
|
||||
// 132*2658976
|
||||
// 132****8976
|
||||
// 1324265****
|
||||
// Output:
|
||||
// 13242658976
|
||||
// 132*2658976
|
||||
// 132****8976
|
||||
// 1324265****
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1240,3 +1241,36 @@ func main() {
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RemoveWhiteSpace">RemoveWhiteSpace</span>
|
||||
|
||||
<p>Remove whitespace characters from a string. when set repalceAll is true removes all whitespace, false only replaces consecutive whitespace characters with one space.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func RemoveWhiteSpace(str string, repalceAll bool) string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := " hello \r\n \t world"
|
||||
|
||||
result1 := strutil.RemoveWhiteSpace(str, true)
|
||||
result2 := strutil.RemoveWhiteSpace(str, false)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// helloworld
|
||||
// hello world
|
||||
}
|
||||
```
|
||||
|
||||
@@ -57,6 +57,8 @@ import (
|
||||
- [Trim](#Trim)
|
||||
- [SplitAndTrim](#SplitAndTrim)
|
||||
- [HideString](#HideString)
|
||||
- [RemoveWhiteSpace](#RemoveWhiteSpace)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -888,13 +890,13 @@ import (
|
||||
|
||||
func main() {
|
||||
result1 := strutil.StringToBytes("abc")
|
||||
result2 := reflect.DeepEqual(result1, []byte{'a', 'b', 'c'})
|
||||
result2 := reflect.DeepEqual(result1, []byte{'a', 'b', 'c'})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
// Output:
|
||||
// [97 98 99]
|
||||
// true
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
// Output:
|
||||
// [97 98 99]
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
@@ -918,11 +920,11 @@ import (
|
||||
|
||||
func main() {
|
||||
bytes := []byte{'a', 'b', 'c'}
|
||||
result := strutil.BytesToString(bytes)
|
||||
result := strutil.BytesToString(bytes)
|
||||
|
||||
fmt.Println(result)
|
||||
// Output:
|
||||
// abc
|
||||
fmt.Println(result)
|
||||
// Output:
|
||||
// abc
|
||||
}
|
||||
```
|
||||
|
||||
@@ -946,16 +948,16 @@ import (
|
||||
|
||||
func main() {
|
||||
result1 := strutil.IsBlank("")
|
||||
result2 := strutil.IsBlank("\t\v\f\n")
|
||||
result3 := strutil.IsBlank(" 中文")
|
||||
result2 := strutil.IsBlank("\t\v\f\n")
|
||||
result3 := strutil.IsBlank(" 中文")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
@@ -979,13 +981,13 @@ import (
|
||||
|
||||
func main() {
|
||||
result1 := strutil.HasPrefixAny("foo bar", []string{"fo", "xyz", "hello"})
|
||||
result2 := strutil.HasPrefixAny("foo bar", []string{"oom", "world"})
|
||||
result2 := strutil.HasPrefixAny("foo bar", []string{"oom", "world"})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1009,13 +1011,13 @@ import (
|
||||
|
||||
func main() {
|
||||
result1 := strutil.HasSuffixAny("foo bar", []string{"bar", "xyz", "hello"})
|
||||
result2 := strutil.HasSuffixAny("foo bar", []string{"oom", "world"})
|
||||
result2 := strutil.HasSuffixAny("foo bar", []string{"oom", "world"})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1040,23 +1042,23 @@ import (
|
||||
func main() {
|
||||
str := "foo bar hello world"
|
||||
|
||||
result1 := strutil.IndexOffset(str, "o", 5)
|
||||
result2 := strutil.IndexOffset(str, "o", 0)
|
||||
result3 := strutil.IndexOffset(str, "d", len(str)-1)
|
||||
result4 := strutil.IndexOffset(str, "d", len(str))
|
||||
result5 := strutil.IndexOffset(str, "f", -1)
|
||||
result1 := strutil.IndexOffset(str, "o", 5)
|
||||
result2 := strutil.IndexOffset(str, "o", 0)
|
||||
result3 := strutil.IndexOffset(str, "d", len(str)-1)
|
||||
result4 := strutil.IndexOffset(str, "d", len(str))
|
||||
result5 := strutil.IndexOffset(str, "f", -1)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
// Output:
|
||||
// 12
|
||||
// 1
|
||||
// 18
|
||||
// -1
|
||||
// -1
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
// Output:
|
||||
// 12
|
||||
// 1
|
||||
// 18
|
||||
// -1
|
||||
// -1
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1080,16 +1082,16 @@ import (
|
||||
|
||||
func main() {
|
||||
str := "ac ab ab ac"
|
||||
replaces := map[string]string{
|
||||
"a": "1",
|
||||
"b": "2",
|
||||
}
|
||||
replaces := map[string]string{
|
||||
"a": "1",
|
||||
"b": "2",
|
||||
}
|
||||
|
||||
result := strutil.ReplaceWithMap(str, replaces)
|
||||
result := strutil.ReplaceWithMap(str, replaces)
|
||||
|
||||
fmt.Println(result)
|
||||
// Output:
|
||||
// 1c 12 12 1c
|
||||
fmt.Println(result)
|
||||
// Output:
|
||||
// 1c 12 12 1c
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1114,19 +1116,19 @@ import (
|
||||
func main() {
|
||||
result1 := strutil.Trim("\nabcd")
|
||||
|
||||
str := "$ ab cd $ "
|
||||
str := "$ ab cd $ "
|
||||
|
||||
result2 := strutil.Trim(str)
|
||||
result3 := strutil.Trim(str, "$")
|
||||
result2 := strutil.Trim(str)
|
||||
result3 := strutil.Trim(str, "$")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// abcd
|
||||
// $ ab cd $
|
||||
// ab cd
|
||||
// Output:
|
||||
// abcd
|
||||
// $ ab cd $
|
||||
// ab cd
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1152,15 +1154,15 @@ import (
|
||||
func main() {
|
||||
str := " a,b, c,d,$1 "
|
||||
|
||||
result1 := strutil.SplitAndTrim(str, ",")
|
||||
result2 := strutil.SplitAndTrim(str, ",", "$")
|
||||
result1 := strutil.SplitAndTrim(str, ",")
|
||||
result2 := strutil.SplitAndTrim(str, ",", "$")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// [a b c d $1]
|
||||
// [a b c d 1]
|
||||
// Output:
|
||||
// [a b c d $1]
|
||||
// [a b c d 1]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1186,21 +1188,21 @@ import (
|
||||
func main() {
|
||||
str := "13242658976"
|
||||
|
||||
result1 := strutil.HideString(str, 3, 3, "*")
|
||||
result2 := strutil.HideString(str, 3, 4, "*")
|
||||
result3 := strutil.HideString(str, 3, 7, "*")
|
||||
result4 := strutil.HideString(str, 7, 11, "*")
|
||||
result1 := strutil.HideString(str, 3, 3, "*")
|
||||
result2 := strutil.HideString(str, 3, 4, "*")
|
||||
result3 := strutil.HideString(str, 3, 7, "*")
|
||||
result4 := strutil.HideString(str, 7, 11, "*")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// 13242658976
|
||||
// 132*2658976
|
||||
// 132****8976
|
||||
// 1324265****
|
||||
// Output:
|
||||
// 13242658976
|
||||
// 132*2658976
|
||||
// 132****8976
|
||||
// 1324265****
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1272,3 +1274,36 @@ func main() {
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="RemoveWhiteSpace">RemoveWhiteSpace</span>
|
||||
|
||||
<p>删除字符串中的空格,当设置repalceAll为true时,删除全部空格,为false时,替换多个空格为1个空格。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func RemoveWhiteSpace(str string, repalceAll bool) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := " hello \r\n \t world"
|
||||
|
||||
result1 := strutil.RemoveWhiteSpace(str, true)
|
||||
result2 := strutil.RemoveWhiteSpace(str, false)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// helloworld
|
||||
// hello world
|
||||
}
|
||||
```
|
||||
|
||||
157
fileutil/file.go
157
fileutil/file.go
@@ -50,7 +50,7 @@ func CreateFile(path string) bool {
|
||||
|
||||
// CreateDir create directory in absolute path. param `absPath` like /a/, /a/b/
|
||||
func CreateDir(absPath string) error {
|
||||
return os.MkdirAll(path.Dir(absPath), os.ModePerm)
|
||||
return os.MkdirAll(absPath, os.ModePerm)
|
||||
}
|
||||
|
||||
// IsDir checks if the path is directory or not
|
||||
@@ -178,44 +178,7 @@ func Zip(fpath string, destPath string) error {
|
||||
archive := zip.NewWriter(zipFile)
|
||||
defer archive.Close()
|
||||
|
||||
filepath.Walk(fpath, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
header, err := zip.FileInfoHeader(info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
header.Name = strings.TrimPrefix(path, filepath.Dir(fpath)+"/")
|
||||
|
||||
if info.IsDir() {
|
||||
header.Name += "/"
|
||||
} else {
|
||||
header.Method = zip.Deflate
|
||||
}
|
||||
|
||||
writer, err := archive.CreateHeader(header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !info.IsDir() {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
_, err = io.Copy(writer, file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
return nil
|
||||
return addFileToArchive(fpath, archive)
|
||||
}
|
||||
|
||||
// UnZip unzip the file and save it to destPath
|
||||
@@ -260,6 +223,99 @@ func UnZip(zipFile string, destPath string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ZipAppendEntry append a single file or directory by fpath to an existing zip file.
|
||||
// Play: https://go.dev/play/p/cxvaT8TRNQp
|
||||
func ZipAppendEntry(fpath string, destPath string) error {
|
||||
tempFile, err := os.CreateTemp("", "temp.zip")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove(tempFile.Name())
|
||||
|
||||
zipReader, err := zip.OpenReader(destPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
archive := zip.NewWriter(tempFile)
|
||||
|
||||
for _, zipItem := range zipReader.File {
|
||||
zipItemReader, err := zipItem.Open()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
header, err := zip.FileInfoHeader(zipItem.FileInfo())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
header.Name = zipItem.Name
|
||||
targetItem, err := archive.CreateHeader(header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = io.Copy(targetItem, zipItemReader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = addFileToArchive(fpath, archive)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = zipReader.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = archive.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = tempFile.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return CopyFile(tempFile.Name(), destPath)
|
||||
}
|
||||
|
||||
func addFileToArchive(fpath string, archive *zip.Writer) error {
|
||||
err := filepath.Walk(fpath, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
header, err := zip.FileInfoHeader(info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
header.Name = strings.TrimPrefix(path, filepath.Dir(fpath)+"/")
|
||||
|
||||
if info.IsDir() {
|
||||
header.Name += "/"
|
||||
} else {
|
||||
header.Method = zip.Deflate
|
||||
writer, err := archive.CreateHeader(header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
if _, err := io.Copy(writer, file); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func safeFilepathJoin(path1, path2 string) (string, error) {
|
||||
relPath, err := filepath.Rel(".", path2)
|
||||
if err != nil || strings.HasPrefix(relPath, "..") {
|
||||
@@ -370,7 +426,7 @@ func MTime(filepath string) (int64, error) {
|
||||
return f.ModTime().Unix(), nil
|
||||
}
|
||||
|
||||
// MTime returns file sha value, param `shaType` should be 1, 256 or 512.
|
||||
// Sha returns file sha value, param `shaType` should be 1, 256 or 512.
|
||||
func Sha(filepath string, shaType ...int) (string, error) {
|
||||
file, err := os.Open(filepath)
|
||||
if err != nil {
|
||||
@@ -420,6 +476,27 @@ func ReadCsvFile(filepath string) ([][]string, error) {
|
||||
return records, nil
|
||||
}
|
||||
|
||||
// WriteCsvFile write content to target csv file.
|
||||
func WriteCsvFile(filepath string, records [][]string, append bool) error {
|
||||
flag := os.O_RDWR | os.O_CREATE
|
||||
|
||||
if append {
|
||||
flag = flag | os.O_APPEND
|
||||
}
|
||||
|
||||
f, err := os.OpenFile(filepath, flag, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
|
||||
writer := csv.NewWriter(f)
|
||||
writer.Comma = ','
|
||||
|
||||
return writer.WriteAll(records)
|
||||
}
|
||||
|
||||
// WriteStringToFile write string to target file.
|
||||
func WriteStringToFile(filepath string, content string, append bool) error {
|
||||
flag := os.O_RDWR | os.O_CREATE
|
||||
|
||||
@@ -182,6 +182,44 @@ func TestZipAndUnZip(t *testing.T) {
|
||||
os.RemoveAll(unZipPath)
|
||||
}
|
||||
|
||||
func TestZipAppendEntry(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestZipAppendEntry")
|
||||
|
||||
zipFile := "./text.zip"
|
||||
err := CopyFile("./testdata/file.go.zip", zipFile)
|
||||
assert.IsNil(err)
|
||||
|
||||
srcFile := "./text.txt"
|
||||
CreateFile(srcFile)
|
||||
|
||||
file, _ := os.OpenFile(srcFile, os.O_WRONLY|os.O_TRUNC, os.ModePerm)
|
||||
|
||||
_, err = file.WriteString("hello\nworld")
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
file.Close()
|
||||
|
||||
err = ZipAppendEntry(srcFile, zipFile)
|
||||
assert.IsNil(err)
|
||||
|
||||
err = ZipAppendEntry("./testdata", zipFile)
|
||||
assert.IsNil(err)
|
||||
|
||||
unZipPath := "./unzip"
|
||||
err = UnZip(zipFile, unZipPath)
|
||||
assert.IsNil(err)
|
||||
|
||||
assert.Equal(true, IsExist("./unzip/text.txt"))
|
||||
assert.Equal(true, IsExist("./unzip/file.go"))
|
||||
assert.Equal(true, IsExist("./unzip/testdata/file.go.zip"))
|
||||
assert.Equal(true, IsExist("./unzip/testdata/test.txt"))
|
||||
|
||||
os.Remove(srcFile)
|
||||
os.Remove(zipFile)
|
||||
os.RemoveAll(unZipPath)
|
||||
}
|
||||
|
||||
func TestFileMode(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestFileMode")
|
||||
|
||||
@@ -268,7 +306,7 @@ func TestSha(t *testing.T) {
|
||||
func TestReadCsvFile(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestReadCsvFile")
|
||||
|
||||
content, err := ReadCsvFile("./testdata/test.csv")
|
||||
content, err := ReadCsvFile("./testdata/demo.csv")
|
||||
t.Log(content)
|
||||
|
||||
assert.IsNil(err)
|
||||
@@ -278,6 +316,27 @@ func TestReadCsvFile(t *testing.T) {
|
||||
assert.Equal("Bob", content[0][0])
|
||||
}
|
||||
|
||||
func TestWriteCsvFile(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestWriteCsvFile")
|
||||
|
||||
csvFilePath := "./testdata/test1.csv"
|
||||
content := [][]string{
|
||||
{"Lili", "22", "female"},
|
||||
{"Jim", "21", "male"},
|
||||
}
|
||||
|
||||
err := WriteCsvFile(csvFilePath, content, false)
|
||||
assert.IsNil(err)
|
||||
|
||||
readContent, err := ReadCsvFile(csvFilePath)
|
||||
|
||||
assert.IsNil(err)
|
||||
|
||||
assert.Equal(2, len(readContent))
|
||||
assert.Equal(3, len(readContent[0]))
|
||||
assert.Equal("Lili", content[0][0])
|
||||
}
|
||||
|
||||
func TestWriteStringToFile(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestWriteStringToFile")
|
||||
|
||||
|
||||
2
fileutil/testdata/test1.csv
vendored
Normal file
2
fileutil/testdata/test1.csv
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
Lili,22,female
|
||||
Jim,21,male
|
||||
|
@@ -189,3 +189,8 @@ func Cos(radian float64, precision ...int) float64 {
|
||||
func Sin(radian float64, precision ...int) float64 {
|
||||
return Cos((math.Pi / 2) - radian)
|
||||
}
|
||||
|
||||
// Log returns the logarithm of base n.
|
||||
func Log(n, base float64) float64 {
|
||||
return math.Log(n) / math.Log(base)
|
||||
}
|
||||
|
||||
@@ -172,3 +172,11 @@ func TestSin(t *testing.T) {
|
||||
assert.EqualValues(0, Sin(math.Pi))
|
||||
assert.EqualValues(1, Sin(math.Pi/2))
|
||||
}
|
||||
|
||||
func TestLog(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestLog")
|
||||
|
||||
assert.EqualValues(3, Log(8, 2))
|
||||
assert.EqualValues(3, TruncRound(Log(27, 3), 0))
|
||||
assert.EqualValues(2.32, TruncRound(Log(5, 2), 2))
|
||||
}
|
||||
|
||||
@@ -18,9 +18,11 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
@@ -93,6 +95,7 @@ type HttpRequest struct {
|
||||
Headers http.Header
|
||||
QueryParams url.Values
|
||||
FormData url.Values
|
||||
File *File
|
||||
Body []byte
|
||||
}
|
||||
|
||||
@@ -180,7 +183,11 @@ func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, err
|
||||
client.setQueryParam(req, rawUrl, request.QueryParams)
|
||||
|
||||
if request.FormData != nil {
|
||||
client.setFormData(req, request.FormData)
|
||||
if request.File != nil {
|
||||
err = client.setFormData(req, request.FormData, setFile(request.File))
|
||||
} else {
|
||||
err = client.setFormData(req, request.FormData, nil)
|
||||
}
|
||||
}
|
||||
|
||||
client.Request = req
|
||||
@@ -244,10 +251,79 @@ func (client *HttpClient) setQueryParam(req *http.Request, reqUrl string, queryP
|
||||
return nil
|
||||
}
|
||||
|
||||
func (client *HttpClient) setFormData(req *http.Request, values url.Values) {
|
||||
formData := []byte(values.Encode())
|
||||
req.Body = ioutil.NopCloser(bytes.NewReader(formData))
|
||||
req.ContentLength = int64(len(formData))
|
||||
func (client *HttpClient) setFormData(req *http.Request, values url.Values, setFile SetFileFunc) error {
|
||||
if setFile != nil {
|
||||
err := setFile(req, values)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
formData := []byte(values.Encode())
|
||||
req.Body = io.NopCloser(bytes.NewReader(formData))
|
||||
req.ContentLength = int64(len(formData))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type SetFileFunc func(req *http.Request, values url.Values) error
|
||||
|
||||
// File struct is a combination of file attributes
|
||||
type File struct {
|
||||
Content []byte
|
||||
Path string
|
||||
FieldName string
|
||||
FileName string
|
||||
}
|
||||
|
||||
// setFile set parameters for http request formdata file upload
|
||||
func setFile(f *File) SetFileFunc {
|
||||
return func(req *http.Request, values url.Values) error {
|
||||
body := &bytes.Buffer{}
|
||||
writer := multipart.NewWriter(body)
|
||||
|
||||
for key, vals := range values {
|
||||
for _, val := range vals {
|
||||
err := writer.WriteField(key, val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if f.Content != nil {
|
||||
part, err := writer.CreateFormFile(f.FieldName, f.FileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
part.Write(f.Content)
|
||||
} else if f.Path != "" {
|
||||
file, err := os.Open(f.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
part, err := writer.CreateFormFile(f.FieldName, f.FileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = io.Copy(part, file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err := writer.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.Body = io.NopCloser(body)
|
||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
req.ContentLength = int64(body.Len())
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// validateRequest check if a request has url, and valid method.
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package netutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/internal"
|
||||
@@ -250,3 +253,108 @@ func TestStructToUrlValues(t *testing.T) {
|
||||
assert.Equal("456", queryValues2.Get("userId"))
|
||||
assert.Equal("", queryValues2.Get("name"))
|
||||
}
|
||||
|
||||
func handleFileRequest(t *testing.T, w http.ResponseWriter, r *http.Request) {
|
||||
err := r.ParseMultipartForm(1024)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
key1 := r.FormValue("key1")
|
||||
expectedKey1 := "value1"
|
||||
if key1 != expectedKey1 {
|
||||
t.Fatalf("expected %s, got %s", expectedKey1, key1)
|
||||
}
|
||||
|
||||
key2 := r.FormValue("key2")
|
||||
expectedKey2 := "value2"
|
||||
if key2 != expectedKey2 {
|
||||
t.Fatalf("expected %s, got %s", expectedKey2, key2)
|
||||
}
|
||||
|
||||
file, header, err := r.FormFile("image")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
expectedFileName := "testImage.jpg"
|
||||
if header.Filename != expectedFileName {
|
||||
t.Fatalf("expected %s, got %s", expectedFileName, header.Filename)
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
content, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
expectedContent := []byte("file content")
|
||||
if !bytes.Equal(content, expectedContent) {
|
||||
t.Fatalf("expected %s, got %s", string(expectedContent), string(content))
|
||||
}
|
||||
}
|
||||
|
||||
func TestSendRequestWithFileContent(t *testing.T) {
|
||||
handler := http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
|
||||
handleFileRequest(t, writer, request)
|
||||
})
|
||||
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
client := NewHttpClient()
|
||||
request := &HttpRequest{
|
||||
RawURL: server.URL,
|
||||
Method: "POST",
|
||||
File: &File{Content: []byte("file content"), FieldName: "image", FileName: "testImage.jpg"},
|
||||
FormData: url.Values{"key1": {"value1"}, "key2": {"value2"}},
|
||||
}
|
||||
|
||||
resp, err := client.SendRequest(request)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Fatalf("expected %d, got %d", http.StatusOK, resp.StatusCode)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSendRequestWithFilePath(t *testing.T) {
|
||||
handler := http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
|
||||
handleFileRequest(t, writer, request)
|
||||
})
|
||||
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
tmpFile, err := ioutil.TempFile("", "testImage.jpg")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
defer os.Remove(tmpFile.Name())
|
||||
|
||||
tmpFile.Write([]byte("file content"))
|
||||
tmpFile.Close()
|
||||
|
||||
client := NewHttpClient()
|
||||
request := &HttpRequest{
|
||||
RawURL: server.URL,
|
||||
Method: "POST",
|
||||
File: &File{Path: tmpFile.Name(), FieldName: "image", FileName: "testImage.jpg"},
|
||||
FormData: url.Values{"key1": {"value1"}, "key2": {"value2"}},
|
||||
}
|
||||
|
||||
resp, err := client.SendRequest(request)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Fatalf("expected %d, got %d", http.StatusOK, resp.StatusCode)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,10 +72,3 @@ func TestTelnetConnected(t *testing.T) {
|
||||
result2 := IsTelnetConnected("www.baidu.com", "123")
|
||||
assert.Equal(false, result2)
|
||||
}
|
||||
|
||||
// func TestDownloadFile(t *testing.T) {
|
||||
// assert := internal.NewAssert(t, "TestDownloadFile")
|
||||
|
||||
// err := DownloadFile("./lancet_logo.jpg", "https://picx.zhimg.com/v2-fc82a4199749de9cfb71e32e54f489d3_720w.jpg?source=172ae18b")
|
||||
// assert.IsNil(err)
|
||||
// }
|
||||
|
||||
@@ -101,3 +101,27 @@ func UUIdV4() (string, error) {
|
||||
|
||||
return fmt.Sprintf("%x-%x-%x-%x-%x", uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:]), nil
|
||||
}
|
||||
|
||||
// RandUniqueIntSlice generate a slice of random int of length n that do not repeat.
|
||||
func RandUniqueIntSlice(n, min, max int) []int {
|
||||
if min > max {
|
||||
return []int{}
|
||||
}
|
||||
if n > max-min {
|
||||
n = max - min
|
||||
}
|
||||
|
||||
nums := make([]int, n)
|
||||
used := make(map[int]struct{}, n)
|
||||
for i := 0; i < n; {
|
||||
r := RandInt(min, max)
|
||||
if _, use := used[r]; use {
|
||||
continue
|
||||
}
|
||||
used[r] = struct{}{}
|
||||
nums[i] = r
|
||||
i++
|
||||
}
|
||||
|
||||
return nums
|
||||
}
|
||||
|
||||
@@ -105,3 +105,36 @@ func TestUUIdV4(t *testing.T) {
|
||||
isUUiDV4 := regexp.MustCompile(`^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$`)
|
||||
assert.Equal(true, isUUiDV4.MatchString(uuid))
|
||||
}
|
||||
|
||||
func TestRandUniqueIntSlice(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestRandUniqueIntSlice")
|
||||
|
||||
r1 := RandUniqueIntSlice(5, 0, 9)
|
||||
assert.Equal(len(r1), 5)
|
||||
if hasDuplicate(r1) {
|
||||
t.Error("hasDuplicate int")
|
||||
}
|
||||
|
||||
r2 := RandUniqueIntSlice(20, 0, 10)
|
||||
assert.Equal(len(r2), 10)
|
||||
if hasDuplicate(r2) {
|
||||
t.Error("hasDuplicate int")
|
||||
}
|
||||
|
||||
r3 := RandUniqueIntSlice(10, 20, 10)
|
||||
assert.Equal(len(r3), 0)
|
||||
|
||||
r4 := RandUniqueIntSlice(0, 20, 10)
|
||||
assert.Equal(len(r4), 0)
|
||||
}
|
||||
|
||||
func hasDuplicate(arr []int) bool {
|
||||
elements := make(map[int]bool)
|
||||
for _, v := range arr {
|
||||
if elements[v] {
|
||||
return true
|
||||
}
|
||||
elements[v] = true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -968,3 +968,16 @@ func AppendIfAbsent(slice interface{}, value interface{}) interface{} {
|
||||
}
|
||||
return out.Interface()
|
||||
}
|
||||
|
||||
// AppendIfAbsent only absent append the value
|
||||
func Join(slice interface{}, separator string) string {
|
||||
sv := sliceValue(slice)
|
||||
|
||||
strs := make([]string, sv.Len())
|
||||
|
||||
for i := 0; i < sv.Len(); i++ {
|
||||
strs[i] = fmt.Sprint(sv.Index(i).Interface())
|
||||
}
|
||||
|
||||
return strings.Join(strs, separator)
|
||||
}
|
||||
|
||||
@@ -624,3 +624,15 @@ func TestAppendIfAbsent(t *testing.T) {
|
||||
assert.Equal([]string{"a", "b"}, AppendIfAbsent(str1, "a"))
|
||||
assert.Equal([]string{"a", "b", "c"}, AppendIfAbsent(str1, "c"))
|
||||
}
|
||||
|
||||
func TestJoin(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestJoin")
|
||||
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
|
||||
result1 := Join(nums, ",")
|
||||
result2 := Join(nums, "-")
|
||||
|
||||
assert.Equal("1,2,3,4,5", result1)
|
||||
assert.Equal("1-2-3-4-5", result2)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ package strutil
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
@@ -503,3 +504,21 @@ func ContainsAny(str string, substrs []string) bool {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
var (
|
||||
whitespaceRegexMatcher *regexp.Regexp = regexp.MustCompile(`\s`)
|
||||
mutiWhitespaceRegexMatcher *regexp.Regexp = regexp.MustCompile(`[[:space:]]{2,}|[\s\p{Zs}]{2,}`)
|
||||
)
|
||||
|
||||
// RemoveWhiteSpace remove whitespace characters from a string.
|
||||
// when set repalceAll is true removes all whitespace, false only replaces consecutive whitespace characters with one space.
|
||||
func RemoveWhiteSpace(str string, repalceAll bool) string {
|
||||
if repalceAll && str != "" {
|
||||
return strings.Join(strings.Fields(str), "")
|
||||
} else if str != "" {
|
||||
str = mutiWhitespaceRegexMatcher.ReplaceAllString(str, " ")
|
||||
str = whitespaceRegexMatcher.ReplaceAllString(str, " ")
|
||||
}
|
||||
|
||||
return strings.TrimSpace(str)
|
||||
}
|
||||
|
||||
@@ -455,3 +455,13 @@ func TestContainsAny(t *testing.T) {
|
||||
assert.Equal(true, ContainsAny("hello world", []string{"hello", "abc"}))
|
||||
assert.Equal(false, ContainsAny("hello world", []string{"123", "abc"}))
|
||||
}
|
||||
|
||||
func TestRemoveWhiteSpace(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestRemoveWhiteSpace")
|
||||
|
||||
str := " hello \r\n \t world"
|
||||
|
||||
assert.Equal("", RemoveWhiteSpace("", true))
|
||||
assert.Equal("helloworld", RemoveWhiteSpace(str, true))
|
||||
assert.Equal("hello world", RemoveWhiteSpace(str, false))
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ func TestExecCommand(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestExecCommand")
|
||||
|
||||
// linux or mac
|
||||
stdout, stderr, err := ExecCommand("ls", WithForeground())
|
||||
stdout, stderr, err := ExecCommand("ls")
|
||||
t.Log("std out: ", stdout)
|
||||
t.Log("std err: ", stderr)
|
||||
assert.Equal("", stderr)
|
||||
|
||||
Reference in New Issue
Block a user