mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-23 13:52:26 +08:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c01b7e675 | ||
|
|
0247ac232a | ||
|
|
e77354d7ff | ||
|
|
8998dc35bb | ||
|
|
ad9fd196ce | ||
|
|
c8a65c33a4 | ||
|
|
69a797f8ed | ||
|
|
1e5b69e9bf | ||
|
|
275abcc8c2 | ||
|
|
065b3b84fe | ||
|
|
4bc43f3278 | ||
|
|
f3382ceac9 | ||
|
|
d20f8783b2 | ||
|
|
8432a4e1ee |
11
README.md
11
README.md
@@ -4,7 +4,7 @@
|
|||||||
<br/>
|
<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://pkg.go.dev/github.com/duke-git/lancet)
|
||||||
[](https://goreportcard.com/report/github.com/duke-git/lancet)
|
[](https://goreportcard.com/report/github.com/duke-git/lancet)
|
||||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
[](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)
|
- [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)
|
- [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)
|
- [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.
|
### 3. Cryptor package is for data encryption and decryption.
|
||||||
|
|
||||||
@@ -208,6 +211,7 @@ import "github.com/duke-git/lancet/fileutil"
|
|||||||
- [ReadFileToString](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#ReadFileToString)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [IsZipFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#IsZipFile)
|
||||||
@@ -215,6 +219,7 @@ import "github.com/duke-git/lancet/fileutil"
|
|||||||
- [MTime](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#MTime)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [WriteBytesToFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#WriteBytesToFile)
|
||||||
|
|
||||||
@@ -275,6 +280,7 @@ import "github.com/duke-git/lancet/mathutil"
|
|||||||
- [LCM](https://github.com/duke-git/lancet/blob/v1/docs/mathutil.md#LCM)
|
- [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)
|
- [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)
|
- [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.
|
### 9. Netutil package contains functions to get net information and send http request.
|
||||||
|
|
||||||
@@ -320,6 +326,7 @@ import "github.com/duke-git/lancet/random"
|
|||||||
- [RandNumeral](https://github.com/duke-git/lancet/blob/v1/docs/random.md#RandNumeral)
|
- [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)
|
- [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)
|
- [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.
|
### 11. Retry package is for executing a function repeatedly until it was successful or canceled by the context.
|
||||||
|
|
||||||
@@ -427,7 +434,7 @@ import "github.com/duke-git/lancet/strutil"
|
|||||||
- [Trim](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#Trim)
|
- [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)
|
- [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)
|
- [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.
|
### 14. System package contain some functions about os, runtime, shell command.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<br/>
|
<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://pkg.go.dev/github.com/duke-git/lancet)
|
||||||
[](https://goreportcard.com/report/github.com/duke-git/lancet)
|
[](https://goreportcard.com/report/github.com/duke-git/lancet)
|
||||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
[](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)
|
- [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)
|
- [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)
|
- [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。
|
### 3. cryptor 加密包支持数据加密和解密,获取 md5,hash 值。支持 base64, md5, hmac, aes, des, rsa。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -207,6 +209,7 @@ import "github.com/duke-git/lancet/fileutil"
|
|||||||
- [ReadFileToString](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#ReadFileToString)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [IsZipFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#IsZipFile)
|
||||||
@@ -214,6 +217,7 @@ import "github.com/duke-git/lancet/fileutil"
|
|||||||
- [MTime](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#MTime)
|
- [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)
|
- [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)
|
- [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)
|
- [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)
|
- [WriteBytesToFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#WriteBytesToFile)
|
||||||
|
|
||||||
@@ -274,7 +278,7 @@ import "github.com/duke-git/lancet/mathutil"
|
|||||||
- [LCM](https://github.com/duke-git/lancet/blob/v1/docs/mathutil_zh-CN.md#LCM)
|
- [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)
|
- [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)
|
- [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 请求。
|
### 9. netutil 网络包支持获取 ip 地址,发送 http 请求。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -319,6 +323,7 @@ import "github.com/duke-git/lancet/random"
|
|||||||
- [RandNumeral](https://github.com/duke-git/lancet/blob/v1/docs/random_zh-CN.md#RandNumeral)
|
- [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)
|
- [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)
|
- [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。
|
### 11. retry 重试执行函数直到函数运行成功或被 context cancel。
|
||||||
|
|
||||||
@@ -426,6 +431,7 @@ import "github.com/duke-git/lancet/strutil"
|
|||||||
- [Trim](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#Trim)
|
- [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)
|
- [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)
|
- [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 相关函数。
|
### 14. system 包含 os, runtime, shell command 相关函数。
|
||||||
|
|
||||||
|
|||||||
@@ -11,11 +11,15 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/text/encoding/simplifiedchinese"
|
||||||
|
"golang.org/x/text/transform"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ToBool convert string to a boolean
|
// ToBool convert string to a boolean
|
||||||
@@ -78,33 +82,45 @@ func ToChar(s string) []string {
|
|||||||
|
|
||||||
// ToString convert value to string
|
// ToString convert value to string
|
||||||
func ToString(value interface{}) string {
|
func ToString(value interface{}) string {
|
||||||
res := ""
|
|
||||||
if value == nil {
|
if value == nil {
|
||||||
return res
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
v := reflect.ValueOf(value)
|
switch val := value.(type) {
|
||||||
|
case float32:
|
||||||
switch value.(type) {
|
return strconv.FormatFloat(float64(val), 'f', -1, 32)
|
||||||
case float32, float64:
|
case float64:
|
||||||
res = strconv.FormatFloat(v.Float(), 'f', -1, 64)
|
return strconv.FormatFloat(val, 'f', -1, 64)
|
||||||
return res
|
case int:
|
||||||
case int, int8, int16, int32, int64:
|
return strconv.FormatInt(int64(val), 10)
|
||||||
res = strconv.FormatInt(v.Int(), 10)
|
case int8:
|
||||||
return res
|
return strconv.FormatInt(int64(val), 10)
|
||||||
case uint, uint8, uint16, uint32, uint64:
|
case int16:
|
||||||
res = strconv.FormatUint(v.Uint(), 10)
|
return strconv.FormatInt(int64(val), 10)
|
||||||
return res
|
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:
|
case string:
|
||||||
res = v.String()
|
return val
|
||||||
return res
|
|
||||||
case []byte:
|
case []byte:
|
||||||
res = string(v.Bytes())
|
return string(val)
|
||||||
return res
|
|
||||||
default:
|
default:
|
||||||
newValue, _ := json.Marshal(value)
|
b, err := json.Marshal(val)
|
||||||
res = string(newValue)
|
if err != nil {
|
||||||
return res
|
return ""
|
||||||
|
}
|
||||||
|
return string(b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,3 +390,17 @@ func ToInterface(v reflect.Value) (value interface{}, ok bool) {
|
|||||||
return nil, false
|
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"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/internal"
|
"github.com/duke-git/lancet/internal"
|
||||||
|
"github.com/duke-git/lancet/validator"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestToChar(t *testing.T) {
|
func TestToChar(t *testing.T) {
|
||||||
@@ -119,7 +121,7 @@ func TestToString(t *testing.T) {
|
|||||||
"", "",
|
"", "",
|
||||||
"0", "1", "-1",
|
"0", "1", "-1",
|
||||||
"123", "123", "123", "123", "123", "123", "123",
|
"123", "123", "123", "123", "123", "123", "123",
|
||||||
"12.3", "12.300000190734863",
|
"12.3", "12.3",
|
||||||
"true", "false",
|
"true", "false",
|
||||||
"[1,2,3]", "{\"a\":1,\"b\":2,\"c\":3}", "{\"Name\":\"TestStruct\"}", "hello"}
|
"[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.EqualValues(nil, nilVal)
|
||||||
assert.Equal(false, ok)
|
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))
|
||||||
|
}
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ import (
|
|||||||
- [DeepClone](#DeepClone)
|
- [DeepClone](#DeepClone)
|
||||||
- [CopyProperties](#CopyProperties)
|
- [CopyProperties](#CopyProperties)
|
||||||
- [ToInterface](#ToInterface)
|
- [ToInterface](#ToInterface)
|
||||||
|
- [Utf8ToGbk](#Utf8ToGbk)
|
||||||
|
- [GbkToUtf8](#GbkToUtf8)
|
||||||
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
@@ -606,15 +608,82 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
val := reflect.ValueOf("abc")
|
val := reflect.ValueOf("abc")
|
||||||
iVal, ok := convertor.ToInterface(val)
|
iVal, ok := convertor.ToInterface(val)
|
||||||
|
|
||||||
fmt.Printf("%T\n", iVal)
|
fmt.Printf("%T\n", iVal)
|
||||||
fmt.Printf("%v\n", iVal)
|
fmt.Printf("%v\n", iVal)
|
||||||
fmt.Println(ok)
|
fmt.Println(ok)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// string
|
// string
|
||||||
// abc
|
// abc
|
||||||
// true
|
// 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)
|
- [DeepClone](#DeepClone)
|
||||||
- [CopyProperties](#CopyProperties)
|
- [CopyProperties](#CopyProperties)
|
||||||
- [ToInterface](#ToInterface)
|
- [ToInterface](#ToInterface)
|
||||||
|
- [Utf8ToGbk](#Utf8ToGbk)
|
||||||
|
- [GbkToUtf8](#GbkToUtf8)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -606,15 +608,82 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
val := reflect.ValueOf("abc")
|
val := reflect.ValueOf("abc")
|
||||||
iVal, ok := convertor.ToInterface(val)
|
iVal, ok := convertor.ToInterface(val)
|
||||||
|
|
||||||
fmt.Printf("%T\n", iVal)
|
fmt.Printf("%T\n", iVal)
|
||||||
fmt.Printf("%v\n", iVal)
|
fmt.Printf("%v\n", iVal)
|
||||||
fmt.Println(ok)
|
fmt.Println(ok)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// string
|
// string
|
||||||
// abc
|
// abc
|
||||||
// true
|
// 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
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -199,18 +199,18 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
||||||
after1Year := datetime.AddYear(now, 1)
|
after1Year := datetime.AddYear(now, 1)
|
||||||
diff1 := after1Year.Sub(now)
|
diff1 := after1Year.Sub(now)
|
||||||
|
|
||||||
before1Year := datetime.AddYear(now, -1)
|
before1Year := datetime.AddYear(now, -1)
|
||||||
diff2 := before1Year.Sub(now)
|
diff2 := before1Year.Sub(now)
|
||||||
|
|
||||||
fmt.Println(diff1)
|
fmt.Println(diff1)
|
||||||
fmt.Println(diff2)
|
fmt.Println(diff2)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// 8760h0m0s
|
// 8760h0m0s
|
||||||
// -8760h0m0s
|
// -8760h0m0s
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -200,18 +200,18 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
||||||
after1Year := datetime.AddYear(now, 1)
|
after1Year := datetime.AddYear(now, 1)
|
||||||
diff1 := after1Year.Sub(now)
|
diff1 := after1Year.Sub(now)
|
||||||
|
|
||||||
before1Year := datetime.AddYear(now, -1)
|
before1Year := datetime.AddYear(now, -1)
|
||||||
diff2 := before1Year.Sub(now)
|
diff2 := before1Year.Sub(now)
|
||||||
|
|
||||||
fmt.Println(diff1)
|
fmt.Println(diff1)
|
||||||
fmt.Println(diff2)
|
fmt.Println(diff2)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// 8760h0m0s
|
// 8760h0m0s
|
||||||
// -8760h0m0s
|
// -8760h0m0s
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
138
docs/fileutil.md
138
docs/fileutil.md
@@ -37,12 +37,14 @@ import (
|
|||||||
- [ReadFileByLine](#ReadFileByLine)
|
- [ReadFileByLine](#ReadFileByLine)
|
||||||
- [Zip](#Zip)
|
- [Zip](#Zip)
|
||||||
- [UnZip](#UnZip)
|
- [UnZip](#UnZip)
|
||||||
|
- [ZipAppendEntry](#ZipAppendEntry)
|
||||||
- [CurrentPath](#CurrentPath)
|
- [CurrentPath](#CurrentPath)
|
||||||
- [IsZipFile](#IsZipFile)
|
- [IsZipFile](#IsZipFile)
|
||||||
- [FileSize](#FileSize)
|
- [FileSize](#FileSize)
|
||||||
- [MTime](#MTime)
|
- [MTime](#MTime)
|
||||||
- [Sha](#Sha)
|
- [Sha](#Sha)
|
||||||
- [ReadCsvFile](#ReadCsvFile)
|
- [ReadCsvFile](#ReadCsvFile)
|
||||||
|
- [WriteCsvFile](#WriteCsvFile)
|
||||||
- [WriteStringToFile](#WriteStringToFile)
|
- [WriteStringToFile](#WriteStringToFile)
|
||||||
- [WriteBytesToFile](#WriteBytesToFile)
|
- [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>
|
### <span id="CurrentPath">CurrentPath</span>
|
||||||
|
|
||||||
<p>return current absolute path.</p>
|
<p>return current absolute path.</p>
|
||||||
@@ -503,7 +533,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="IsZipFile">IsZipFile</span>
|
### <span id="IsZipFile">IsZipFile</span>
|
||||||
|
|
||||||
<p>Checks if file is zip file or not.</p>
|
<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>
|
### <span id="WriteBytesToFile">WriteBytesToFile</span>
|
||||||
|
|
||||||
@@ -688,33 +753,32 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
filepath := "./bytes.txt"
|
filepath := "./bytes.txt"
|
||||||
|
|
||||||
file, err := os.Create(filepath)
|
file, err := os.Create(filepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
err = fileutil.WriteBytesToFile(filepath, []byte("hello"))
|
err = fileutil.WriteBytesToFile(filepath, []byte("hello"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
content, err := fileutil.ReadFileToString(filepath)
|
content, err := fileutil.ReadFileToString(filepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Remove(filepath)
|
os.Remove(filepath)
|
||||||
|
|
||||||
fmt.Println(content)
|
fmt.Println(content)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// hello
|
// hello
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="WriteStringToFile">WriteStringToFile</span>
|
### <span id="WriteStringToFile">WriteStringToFile</span>
|
||||||
|
|
||||||
<p>Writes string to target file.</p>
|
<p>Writes string to target file.</p>
|
||||||
@@ -738,28 +802,28 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
filepath := "./test.txt"
|
filepath := "./test.txt"
|
||||||
|
|
||||||
file, err := os.Create(filepath)
|
file, err := os.Create(filepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
err = fileutil.WriteStringToFile(filepath, "hello", true)
|
err = fileutil.WriteStringToFile(filepath, "hello", true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
content, err := fileutil.ReadFileToString(filepath)
|
content, err := fileutil.ReadFileToString(filepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Remove(filepath)
|
os.Remove(filepath)
|
||||||
|
|
||||||
fmt.Println(content)
|
fmt.Println(content)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// hello
|
// hello
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -30,19 +30,21 @@ import (
|
|||||||
- [MiMeType](#MiMeType)
|
- [MiMeType](#MiMeType)
|
||||||
- [IsExist](#IsExist)
|
- [IsExist](#IsExist)
|
||||||
- [IsLink](#IsLink)
|
- [IsLink](#IsLink)
|
||||||
- [IsDir](#IsDir)
|
- [IsDir](#IsDir)画
|
||||||
- [ListFileNames](#ListFileNames)
|
- [ListFileNames](#ListFileNames)
|
||||||
- [RemoveFile](#RemoveFile)
|
- [RemoveFile](#RemoveFile)
|
||||||
- [ReadFileToString](#ReadFileToString)
|
- [ReadFileToString](#ReadFileToString)
|
||||||
- [ReadFileByLine](#ReadFileByLine)
|
- [ReadFileByLine](#ReadFileByLine)
|
||||||
- [Zip](#Zip)
|
- [Zip](#Zip)
|
||||||
- [UnZip](#UnZip)
|
- [UnZip](#UnZip)
|
||||||
|
- [ZipAppendEntry](#ZipAppendEntry)
|
||||||
- [CurrentPath](#CurrentPath)
|
- [CurrentPath](#CurrentPath)
|
||||||
- [IsZipFile](#IsZipFile)
|
- [IsZipFile](#IsZipFile)
|
||||||
- [FileSize](#FileSize)
|
- [FileSize](#FileSize)
|
||||||
- [MTime](#MTime)
|
- [MTime](#MTime)
|
||||||
- [Sha](#Sha)
|
- [Sha](#Sha)
|
||||||
- [ReadCsvFile](#ReadCsvFile)
|
- [ReadCsvFile](#ReadCsvFile)
|
||||||
|
- [WriteCsvFile](#WriteCsvFile)
|
||||||
- [WriteStringToFile](#WriteStringToFile)
|
- [WriteStringToFile](#WriteStringToFile)
|
||||||
- [WriteBytesToFile](#WriteBytesToFile)
|
- [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>
|
### <span id="CurrentPath">CurrentPath</span>
|
||||||
|
|
||||||
<p>返回当前位置的绝对路径。</p>
|
<p>返回当前位置的绝对路径。</p>
|
||||||
@@ -503,7 +533,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="IsZipFile">IsZipFile</span>
|
### <span id="IsZipFile">IsZipFile</span>
|
||||||
|
|
||||||
<p>判断文件是否是zip压缩文件。</p>
|
<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>
|
### <span id="WriteBytesToFile">WriteBytesToFile</span>
|
||||||
|
|
||||||
<p>将bytes写入文件。</p>
|
<p>将bytes写入文件。</p>
|
||||||
@@ -687,33 +753,32 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
filepath := "./bytes.txt"
|
filepath := "./bytes.txt"
|
||||||
|
|
||||||
file, err := os.Create(filepath)
|
file, err := os.Create(filepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
err = fileutil.WriteBytesToFile(filepath, []byte("hello"))
|
err = fileutil.WriteBytesToFile(filepath, []byte("hello"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
content, err := fileutil.ReadFileToString(filepath)
|
content, err := fileutil.ReadFileToString(filepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Remove(filepath)
|
os.Remove(filepath)
|
||||||
|
|
||||||
fmt.Println(content)
|
fmt.Println(content)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// hello
|
// hello
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="WriteStringToFile">WriteStringToFile</span>
|
### <span id="WriteStringToFile">WriteStringToFile</span>
|
||||||
|
|
||||||
<p>将字符串写入文件。</p>
|
<p>将字符串写入文件。</p>
|
||||||
@@ -737,28 +802,28 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
filepath := "./test.txt"
|
filepath := "./test.txt"
|
||||||
|
|
||||||
file, err := os.Create(filepath)
|
file, err := os.Create(filepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
err = fileutil.WriteStringToFile(filepath, "hello", true)
|
err = fileutil.WriteStringToFile(filepath, "hello", true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
content, err := fileutil.ReadFileToString(filepath)
|
content, err := fileutil.ReadFileToString(filepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Remove(filepath)
|
os.Remove(filepath)
|
||||||
|
|
||||||
fmt.Println(content)
|
fmt.Println(content)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// hello
|
// hello
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -323,16 +323,16 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
addOne := func(x interface{}) interface{} {
|
addOne := func(x interface{}) interface{} {
|
||||||
return x.(int) + 1
|
return x.(int) + 1
|
||||||
}
|
}
|
||||||
double := func(x interface{}) interface{} {
|
double := func(x interface{}) interface{} {
|
||||||
return 2 * x.(int)
|
return 2 * x.(int)
|
||||||
}
|
}
|
||||||
square := func(x interface{}) interface{} {
|
square := func(x interface{}) interface{} {
|
||||||
return x.(int) * x.(int)
|
return x.(int) * x.(int)
|
||||||
}
|
}
|
||||||
|
|
||||||
f := function.Pipeline(addOne, double, square)
|
f := function.Pipeline(addOne, double, square)
|
||||||
|
|
||||||
result := fn(2)
|
result := fn(2)
|
||||||
|
|
||||||
|
|||||||
@@ -322,16 +322,16 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
addOne := func(x interface{}) interface{} {
|
addOne := func(x interface{}) interface{} {
|
||||||
return x.(int) + 1
|
return x.(int) + 1
|
||||||
}
|
}
|
||||||
double := func(x interface{}) interface{} {
|
double := func(x interface{}) interface{} {
|
||||||
return 2 * x.(int)
|
return 2 * x.(int)
|
||||||
}
|
}
|
||||||
square := func(x interface{}) interface{} {
|
square := func(x interface{}) interface{} {
|
||||||
return x.(int) * x.(int)
|
return x.(int) * x.(int)
|
||||||
}
|
}
|
||||||
|
|
||||||
f := function.Pipeline(addOne, double, square)
|
f := function.Pipeline(addOne, double, square)
|
||||||
|
|
||||||
result := fn(2)
|
result := fn(2)
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import (
|
|||||||
- [LCM](#LCM)
|
- [LCM](#LCM)
|
||||||
- [Cos](#Cos)
|
- [Cos](#Cos)
|
||||||
- [Sin](#Sin)
|
- [Sin](#Sin)
|
||||||
|
- [Log](#Log)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -363,20 +364,20 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
result1 := mathutil.IsPrime(-1)
|
result1 := mathutil.IsPrime(-1)
|
||||||
result2 := mathutil.IsPrime(0)
|
result2 := mathutil.IsPrime(0)
|
||||||
result3 := mathutil.IsPrime(1)
|
result3 := mathutil.IsPrime(1)
|
||||||
result4 := mathutil.IsPrime(2)
|
result4 := mathutil.IsPrime(2)
|
||||||
|
|
||||||
fmt.Println(result1)
|
fmt.Println(result1)
|
||||||
fmt.Println(result2)
|
fmt.Println(result2)
|
||||||
fmt.Println(result3)
|
fmt.Println(result3)
|
||||||
fmt.Println(result4)
|
fmt.Println(result4)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// false
|
// false
|
||||||
// false
|
// false
|
||||||
// false
|
// false
|
||||||
// true
|
// true
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -458,7 +459,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="Cos">Cos</span>
|
### <span id="Cos">Cos</span>
|
||||||
|
|
||||||
<p>Returns the cosine of the radian argument.</p>
|
<p>Returns the cosine of the radian argument.</p>
|
||||||
@@ -501,7 +501,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="Sin">Sin</span>
|
### <span id="Sin">Sin</span>
|
||||||
|
|
||||||
<p>Returns the sine of the radian argument.</p>
|
<p>Returns the sine of the radian argument.</p>
|
||||||
@@ -542,4 +541,40 @@ func main() {
|
|||||||
// 0
|
// 0
|
||||||
// 1
|
// 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)
|
- [LCM](#LCM)
|
||||||
- [Cos](#Cos)
|
- [Cos](#Cos)
|
||||||
- [Sin](#Sin)
|
- [Sin](#Sin)
|
||||||
|
- [Log](#Log)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -363,20 +364,20 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
result1 := mathutil.IsPrime(-1)
|
result1 := mathutil.IsPrime(-1)
|
||||||
result2 := mathutil.IsPrime(0)
|
result2 := mathutil.IsPrime(0)
|
||||||
result3 := mathutil.IsPrime(1)
|
result3 := mathutil.IsPrime(1)
|
||||||
result4 := mathutil.IsPrime(2)
|
result4 := mathutil.IsPrime(2)
|
||||||
|
|
||||||
fmt.Println(result1)
|
fmt.Println(result1)
|
||||||
fmt.Println(result2)
|
fmt.Println(result2)
|
||||||
fmt.Println(result3)
|
fmt.Println(result3)
|
||||||
fmt.Println(result4)
|
fmt.Println(result4)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// false
|
// false
|
||||||
// false
|
// false
|
||||||
// false
|
// false
|
||||||
// true
|
// true
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -543,4 +544,40 @@ func main() {
|
|||||||
// 0
|
// 0
|
||||||
// 1
|
// 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() {
|
func main() {
|
||||||
url := "https://jsonplaceholder.typicode.com/todos"
|
url := "https://jsonplaceholder.typicode.com/todos"
|
||||||
header := map[string]string{
|
header := map[string]string{
|
||||||
"Content-Type": "application/x-www-form-urlencoded",
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
// "Content-Type": "multipart/form-data",
|
// "Content-Type": "multipart/form-data",
|
||||||
}
|
}
|
||||||
|
|
||||||
postData := url.Values{}
|
postData := url.Values{}
|
||||||
postData.Add("userId", "1")
|
postData.Add("userId", "1")
|
||||||
postData.Add("title", "TestToDo")
|
postData.Add("title", "TestToDo")
|
||||||
|
|
||||||
// postData := make(map[string]string)
|
// postData := make(map[string]string)
|
||||||
// postData["userId"] = "1"
|
// postData["userId"] = "1"
|
||||||
// postData["title"] = "title"
|
// postData["title"] = "title"
|
||||||
|
|
||||||
resp, err := netutil.HttpPost(apiUrl, header, nil, postData)
|
resp, err := netutil.HttpPost(apiUrl, header, nil, postData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
body, _ := io.ReadAll(resp.Body)
|
body, _ := io.ReadAll(resp.Body)
|
||||||
t.Log("response: ", resp.StatusCode, string(body))
|
t.Log("response: ", resp.StatusCode, string(body))
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -657,23 +657,23 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
url := "https://jsonplaceholder.typicode.com/todos"
|
url := "https://jsonplaceholder.typicode.com/todos"
|
||||||
header := map[string]string{
|
header := map[string]string{
|
||||||
"Content-Type": "application/x-www-form-urlencoded",
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
// "Content-Type": "multipart/form-data",
|
// "Content-Type": "multipart/form-data",
|
||||||
}
|
}
|
||||||
|
|
||||||
postData := url.Values{}
|
postData := url.Values{}
|
||||||
postData.Add("userId", "1")
|
postData.Add("userId", "1")
|
||||||
postData.Add("title", "TestToDo")
|
postData.Add("title", "TestToDo")
|
||||||
|
|
||||||
// postData := make(map[string]string)
|
// postData := make(map[string]string)
|
||||||
// postData["userId"] = "1"
|
// postData["userId"] = "1"
|
||||||
// postData["title"] = "title"
|
// postData["title"] = "title"
|
||||||
|
|
||||||
resp, err := netutil.HttpPost(apiUrl, header, nil, postData)
|
resp, err := netutil.HttpPost(apiUrl, header, nil, postData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
body, _ := io.ReadAll(resp.Body)
|
body, _ := io.ReadAll(resp.Body)
|
||||||
fmt.Println(body)
|
fmt.Println(body)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import (
|
|||||||
- [RandNumeral](#RandNumeral)
|
- [RandNumeral](#RandNumeral)
|
||||||
- [RandNumeralOrLetter](#RandNumeralOrLetter)
|
- [RandNumeralOrLetter](#RandNumeralOrLetter)
|
||||||
- [UUIdV4](#UUIdV4)
|
- [UUIdV4](#UUIdV4)
|
||||||
|
- [RandUniqueIntSlice](#RandUniqueIntSlice)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -245,3 +246,29 @@ func main() {
|
|||||||
fmt.Println(uuid)
|
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)
|
- [RandNumeral](#RandNumeral)
|
||||||
- [RandNumeralOrLetter](#RandNumeralOrLetter)
|
- [RandNumeralOrLetter](#RandNumeralOrLetter)
|
||||||
- [UUIdV4](#UUIdV4)
|
- [UUIdV4](#UUIdV4)
|
||||||
|
- [RandUniqueIntSlice](#RandUniqueIntSlice)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -245,3 +246,29 @@ func main() {
|
|||||||
fmt.Println(uuid)
|
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)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
204
docs/strutil.md
204
docs/strutil.md
@@ -57,6 +57,7 @@ import (
|
|||||||
- [Trim](#Trim)
|
- [Trim](#Trim)
|
||||||
- [SplitAndTrim](#SplitAndTrim)
|
- [SplitAndTrim](#SplitAndTrim)
|
||||||
- [HideString](#HideString)
|
- [HideString](#HideString)
|
||||||
|
- [RemoveWhiteSpace](#RemoveWhiteSpace)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -857,13 +858,13 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
result1 := strutil.StringToBytes("abc")
|
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(result1)
|
||||||
fmt.Println(result2)
|
fmt.Println(result2)
|
||||||
// Output:
|
// Output:
|
||||||
// [97 98 99]
|
// [97 98 99]
|
||||||
// true
|
// true
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -887,11 +888,11 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
bytes := []byte{'a', 'b', 'c'}
|
bytes := []byte{'a', 'b', 'c'}
|
||||||
result := strutil.BytesToString(bytes)
|
result := strutil.BytesToString(bytes)
|
||||||
|
|
||||||
fmt.Println(result)
|
fmt.Println(result)
|
||||||
// Output:
|
// Output:
|
||||||
// abc
|
// abc
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -915,16 +916,16 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
result1 := strutil.IsBlank("")
|
result1 := strutil.IsBlank("")
|
||||||
result2 := strutil.IsBlank("\t\v\f\n")
|
result2 := strutil.IsBlank("\t\v\f\n")
|
||||||
result3 := strutil.IsBlank(" 中文")
|
result3 := strutil.IsBlank(" 中文")
|
||||||
|
|
||||||
fmt.Println(result1)
|
fmt.Println(result1)
|
||||||
fmt.Println(result2)
|
fmt.Println(result2)
|
||||||
fmt.Println(result3)
|
fmt.Println(result3)
|
||||||
// Output:
|
// Output:
|
||||||
// true
|
// true
|
||||||
// true
|
// true
|
||||||
// false
|
// false
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -948,13 +949,13 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
result1 := strutil.HasPrefixAny("foo bar", []string{"fo", "xyz", "hello"})
|
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(result1)
|
||||||
fmt.Println(result2)
|
fmt.Println(result2)
|
||||||
// Output:
|
// Output:
|
||||||
// true
|
// true
|
||||||
// false
|
// false
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -978,13 +979,13 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
result1 := strutil.HasSuffixAny("foo bar", []string{"bar", "xyz", "hello"})
|
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(result1)
|
||||||
fmt.Println(result2)
|
fmt.Println(result2)
|
||||||
// Output:
|
// Output:
|
||||||
// true
|
// true
|
||||||
// false
|
// false
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -1009,23 +1010,23 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
str := "foo bar hello world"
|
str := "foo bar hello world"
|
||||||
|
|
||||||
result1 := strutil.IndexOffset(str, "o", 5)
|
result1 := strutil.IndexOffset(str, "o", 5)
|
||||||
result2 := strutil.IndexOffset(str, "o", 0)
|
result2 := strutil.IndexOffset(str, "o", 0)
|
||||||
result3 := strutil.IndexOffset(str, "d", len(str)-1)
|
result3 := strutil.IndexOffset(str, "d", len(str)-1)
|
||||||
result4 := strutil.IndexOffset(str, "d", len(str))
|
result4 := strutil.IndexOffset(str, "d", len(str))
|
||||||
result5 := strutil.IndexOffset(str, "f", -1)
|
result5 := strutil.IndexOffset(str, "f", -1)
|
||||||
|
|
||||||
fmt.Println(result1)
|
fmt.Println(result1)
|
||||||
fmt.Println(result2)
|
fmt.Println(result2)
|
||||||
fmt.Println(result3)
|
fmt.Println(result3)
|
||||||
fmt.Println(result4)
|
fmt.Println(result4)
|
||||||
fmt.Println(result5)
|
fmt.Println(result5)
|
||||||
// Output:
|
// Output:
|
||||||
// 12
|
// 12
|
||||||
// 1
|
// 1
|
||||||
// 18
|
// 18
|
||||||
// -1
|
// -1
|
||||||
// -1
|
// -1
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -1049,16 +1050,16 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
str := "ac ab ab ac"
|
str := "ac ab ab ac"
|
||||||
replaces := map[string]string{
|
replaces := map[string]string{
|
||||||
"a": "1",
|
"a": "1",
|
||||||
"b": "2",
|
"b": "2",
|
||||||
}
|
}
|
||||||
|
|
||||||
result := strutil.ReplaceWithMap(str, replaces)
|
result := strutil.ReplaceWithMap(str, replaces)
|
||||||
|
|
||||||
fmt.Println(result)
|
fmt.Println(result)
|
||||||
// Output:
|
// Output:
|
||||||
// 1c 12 12 1c
|
// 1c 12 12 1c
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -1083,19 +1084,19 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
result1 := strutil.Trim("\nabcd")
|
result1 := strutil.Trim("\nabcd")
|
||||||
|
|
||||||
str := "$ ab cd $ "
|
str := "$ ab cd $ "
|
||||||
|
|
||||||
result2 := strutil.Trim(str)
|
result2 := strutil.Trim(str)
|
||||||
result3 := strutil.Trim(str, "$")
|
result3 := strutil.Trim(str, "$")
|
||||||
|
|
||||||
fmt.Println(result1)
|
fmt.Println(result1)
|
||||||
fmt.Println(result2)
|
fmt.Println(result2)
|
||||||
fmt.Println(result3)
|
fmt.Println(result3)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// abcd
|
// abcd
|
||||||
// $ ab cd $
|
// $ ab cd $
|
||||||
// ab cd
|
// ab cd
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -1120,15 +1121,15 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
str := " a,b, c,d,$1 "
|
str := " a,b, c,d,$1 "
|
||||||
|
|
||||||
result1 := strutil.SplitAndTrim(str, ",")
|
result1 := strutil.SplitAndTrim(str, ",")
|
||||||
result2 := strutil.SplitAndTrim(str, ",", "$")
|
result2 := strutil.SplitAndTrim(str, ",", "$")
|
||||||
|
|
||||||
fmt.Println(result1)
|
fmt.Println(result1)
|
||||||
fmt.Println(result2)
|
fmt.Println(result2)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// [a b c d $1]
|
// [a b c d $1]
|
||||||
// [a b c d 1]
|
// [a b c d 1]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -1153,21 +1154,21 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
str := "13242658976"
|
str := "13242658976"
|
||||||
|
|
||||||
result1 := strutil.HideString(str, 3, 3, "*")
|
result1 := strutil.HideString(str, 3, 3, "*")
|
||||||
result2 := strutil.HideString(str, 3, 4, "*")
|
result2 := strutil.HideString(str, 3, 4, "*")
|
||||||
result3 := strutil.HideString(str, 3, 7, "*")
|
result3 := strutil.HideString(str, 3, 7, "*")
|
||||||
result4 := strutil.HideString(str, 7, 11, "*")
|
result4 := strutil.HideString(str, 7, 11, "*")
|
||||||
|
|
||||||
fmt.Println(result1)
|
fmt.Println(result1)
|
||||||
fmt.Println(result2)
|
fmt.Println(result2)
|
||||||
fmt.Println(result3)
|
fmt.Println(result3)
|
||||||
fmt.Println(result4)
|
fmt.Println(result4)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// 13242658976
|
// 13242658976
|
||||||
// 132*2658976
|
// 132*2658976
|
||||||
// 132****8976
|
// 132****8976
|
||||||
// 1324265****
|
// 1324265****
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -1240,3 +1241,36 @@ func main() {
|
|||||||
// false
|
// 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)
|
- [Trim](#Trim)
|
||||||
- [SplitAndTrim](#SplitAndTrim)
|
- [SplitAndTrim](#SplitAndTrim)
|
||||||
- [HideString](#HideString)
|
- [HideString](#HideString)
|
||||||
|
- [RemoveWhiteSpace](#RemoveWhiteSpace)
|
||||||
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -888,13 +890,13 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
result1 := strutil.StringToBytes("abc")
|
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(result1)
|
||||||
fmt.Println(result2)
|
fmt.Println(result2)
|
||||||
// Output:
|
// Output:
|
||||||
// [97 98 99]
|
// [97 98 99]
|
||||||
// true
|
// true
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -918,11 +920,11 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
bytes := []byte{'a', 'b', 'c'}
|
bytes := []byte{'a', 'b', 'c'}
|
||||||
result := strutil.BytesToString(bytes)
|
result := strutil.BytesToString(bytes)
|
||||||
|
|
||||||
fmt.Println(result)
|
fmt.Println(result)
|
||||||
// Output:
|
// Output:
|
||||||
// abc
|
// abc
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -946,16 +948,16 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
result1 := strutil.IsBlank("")
|
result1 := strutil.IsBlank("")
|
||||||
result2 := strutil.IsBlank("\t\v\f\n")
|
result2 := strutil.IsBlank("\t\v\f\n")
|
||||||
result3 := strutil.IsBlank(" 中文")
|
result3 := strutil.IsBlank(" 中文")
|
||||||
|
|
||||||
fmt.Println(result1)
|
fmt.Println(result1)
|
||||||
fmt.Println(result2)
|
fmt.Println(result2)
|
||||||
fmt.Println(result3)
|
fmt.Println(result3)
|
||||||
// Output:
|
// Output:
|
||||||
// true
|
// true
|
||||||
// true
|
// true
|
||||||
// false
|
// false
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -979,13 +981,13 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
result1 := strutil.HasPrefixAny("foo bar", []string{"fo", "xyz", "hello"})
|
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(result1)
|
||||||
fmt.Println(result2)
|
fmt.Println(result2)
|
||||||
// Output:
|
// Output:
|
||||||
// true
|
// true
|
||||||
// false
|
// false
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -1009,13 +1011,13 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
result1 := strutil.HasSuffixAny("foo bar", []string{"bar", "xyz", "hello"})
|
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(result1)
|
||||||
fmt.Println(result2)
|
fmt.Println(result2)
|
||||||
// Output:
|
// Output:
|
||||||
// true
|
// true
|
||||||
// false
|
// false
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -1040,23 +1042,23 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
str := "foo bar hello world"
|
str := "foo bar hello world"
|
||||||
|
|
||||||
result1 := strutil.IndexOffset(str, "o", 5)
|
result1 := strutil.IndexOffset(str, "o", 5)
|
||||||
result2 := strutil.IndexOffset(str, "o", 0)
|
result2 := strutil.IndexOffset(str, "o", 0)
|
||||||
result3 := strutil.IndexOffset(str, "d", len(str)-1)
|
result3 := strutil.IndexOffset(str, "d", len(str)-1)
|
||||||
result4 := strutil.IndexOffset(str, "d", len(str))
|
result4 := strutil.IndexOffset(str, "d", len(str))
|
||||||
result5 := strutil.IndexOffset(str, "f", -1)
|
result5 := strutil.IndexOffset(str, "f", -1)
|
||||||
|
|
||||||
fmt.Println(result1)
|
fmt.Println(result1)
|
||||||
fmt.Println(result2)
|
fmt.Println(result2)
|
||||||
fmt.Println(result3)
|
fmt.Println(result3)
|
||||||
fmt.Println(result4)
|
fmt.Println(result4)
|
||||||
fmt.Println(result5)
|
fmt.Println(result5)
|
||||||
// Output:
|
// Output:
|
||||||
// 12
|
// 12
|
||||||
// 1
|
// 1
|
||||||
// 18
|
// 18
|
||||||
// -1
|
// -1
|
||||||
// -1
|
// -1
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -1080,16 +1082,16 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
str := "ac ab ab ac"
|
str := "ac ab ab ac"
|
||||||
replaces := map[string]string{
|
replaces := map[string]string{
|
||||||
"a": "1",
|
"a": "1",
|
||||||
"b": "2",
|
"b": "2",
|
||||||
}
|
}
|
||||||
|
|
||||||
result := strutil.ReplaceWithMap(str, replaces)
|
result := strutil.ReplaceWithMap(str, replaces)
|
||||||
|
|
||||||
fmt.Println(result)
|
fmt.Println(result)
|
||||||
// Output:
|
// Output:
|
||||||
// 1c 12 12 1c
|
// 1c 12 12 1c
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -1114,19 +1116,19 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
result1 := strutil.Trim("\nabcd")
|
result1 := strutil.Trim("\nabcd")
|
||||||
|
|
||||||
str := "$ ab cd $ "
|
str := "$ ab cd $ "
|
||||||
|
|
||||||
result2 := strutil.Trim(str)
|
result2 := strutil.Trim(str)
|
||||||
result3 := strutil.Trim(str, "$")
|
result3 := strutil.Trim(str, "$")
|
||||||
|
|
||||||
fmt.Println(result1)
|
fmt.Println(result1)
|
||||||
fmt.Println(result2)
|
fmt.Println(result2)
|
||||||
fmt.Println(result3)
|
fmt.Println(result3)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// abcd
|
// abcd
|
||||||
// $ ab cd $
|
// $ ab cd $
|
||||||
// ab cd
|
// ab cd
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -1152,15 +1154,15 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
str := " a,b, c,d,$1 "
|
str := " a,b, c,d,$1 "
|
||||||
|
|
||||||
result1 := strutil.SplitAndTrim(str, ",")
|
result1 := strutil.SplitAndTrim(str, ",")
|
||||||
result2 := strutil.SplitAndTrim(str, ",", "$")
|
result2 := strutil.SplitAndTrim(str, ",", "$")
|
||||||
|
|
||||||
fmt.Println(result1)
|
fmt.Println(result1)
|
||||||
fmt.Println(result2)
|
fmt.Println(result2)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// [a b c d $1]
|
// [a b c d $1]
|
||||||
// [a b c d 1]
|
// [a b c d 1]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -1186,21 +1188,21 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
str := "13242658976"
|
str := "13242658976"
|
||||||
|
|
||||||
result1 := strutil.HideString(str, 3, 3, "*")
|
result1 := strutil.HideString(str, 3, 3, "*")
|
||||||
result2 := strutil.HideString(str, 3, 4, "*")
|
result2 := strutil.HideString(str, 3, 4, "*")
|
||||||
result3 := strutil.HideString(str, 3, 7, "*")
|
result3 := strutil.HideString(str, 3, 7, "*")
|
||||||
result4 := strutil.HideString(str, 7, 11, "*")
|
result4 := strutil.HideString(str, 7, 11, "*")
|
||||||
|
|
||||||
fmt.Println(result1)
|
fmt.Println(result1)
|
||||||
fmt.Println(result2)
|
fmt.Println(result2)
|
||||||
fmt.Println(result3)
|
fmt.Println(result3)
|
||||||
fmt.Println(result4)
|
fmt.Println(result4)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// 13242658976
|
// 13242658976
|
||||||
// 132*2658976
|
// 132*2658976
|
||||||
// 132****8976
|
// 132****8976
|
||||||
// 1324265****
|
// 1324265****
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -1272,3 +1274,36 @@ func main() {
|
|||||||
// false
|
// 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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
155
fileutil/file.go
155
fileutil/file.go
@@ -178,44 +178,7 @@ func Zip(fpath string, destPath string) error {
|
|||||||
archive := zip.NewWriter(zipFile)
|
archive := zip.NewWriter(zipFile)
|
||||||
defer archive.Close()
|
defer archive.Close()
|
||||||
|
|
||||||
filepath.Walk(fpath, func(path string, info os.FileInfo, err error) error {
|
return addFileToArchive(fpath, archive)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnZip unzip the file and save it to destPath
|
// UnZip unzip the file and save it to destPath
|
||||||
@@ -260,6 +223,99 @@ func UnZip(zipFile string, destPath string) error {
|
|||||||
return nil
|
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) {
|
func safeFilepathJoin(path1, path2 string) (string, error) {
|
||||||
relPath, err := filepath.Rel(".", path2)
|
relPath, err := filepath.Rel(".", path2)
|
||||||
if err != nil || strings.HasPrefix(relPath, "..") {
|
if err != nil || strings.HasPrefix(relPath, "..") {
|
||||||
@@ -370,7 +426,7 @@ func MTime(filepath string) (int64, error) {
|
|||||||
return f.ModTime().Unix(), nil
|
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) {
|
func Sha(filepath string, shaType ...int) (string, error) {
|
||||||
file, err := os.Open(filepath)
|
file, err := os.Open(filepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -420,6 +476,27 @@ func ReadCsvFile(filepath string) ([][]string, error) {
|
|||||||
return records, nil
|
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.
|
// WriteStringToFile write string to target file.
|
||||||
func WriteStringToFile(filepath string, content string, append bool) error {
|
func WriteStringToFile(filepath string, content string, append bool) error {
|
||||||
flag := os.O_RDWR | os.O_CREATE
|
flag := os.O_RDWR | os.O_CREATE
|
||||||
|
|||||||
@@ -182,6 +182,44 @@ func TestZipAndUnZip(t *testing.T) {
|
|||||||
os.RemoveAll(unZipPath)
|
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) {
|
func TestFileMode(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestFileMode")
|
assert := internal.NewAssert(t, "TestFileMode")
|
||||||
|
|
||||||
@@ -268,7 +306,7 @@ func TestSha(t *testing.T) {
|
|||||||
func TestReadCsvFile(t *testing.T) {
|
func TestReadCsvFile(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestReadCsvFile")
|
assert := internal.NewAssert(t, "TestReadCsvFile")
|
||||||
|
|
||||||
content, err := ReadCsvFile("./testdata/test.csv")
|
content, err := ReadCsvFile("./testdata/demo.csv")
|
||||||
t.Log(content)
|
t.Log(content)
|
||||||
|
|
||||||
assert.IsNil(err)
|
assert.IsNil(err)
|
||||||
@@ -278,6 +316,27 @@ func TestReadCsvFile(t *testing.T) {
|
|||||||
assert.Equal("Bob", content[0][0])
|
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) {
|
func TestWriteStringToFile(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestWriteStringToFile")
|
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 {
|
func Sin(radian float64, precision ...int) float64 {
|
||||||
return Cos((math.Pi / 2) - radian)
|
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(0, Sin(math.Pi))
|
||||||
assert.EqualValues(1, Sin(math.Pi/2))
|
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"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
|
"mime/multipart"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -93,6 +95,7 @@ type HttpRequest struct {
|
|||||||
Headers http.Header
|
Headers http.Header
|
||||||
QueryParams url.Values
|
QueryParams url.Values
|
||||||
FormData url.Values
|
FormData url.Values
|
||||||
|
File *File
|
||||||
Body []byte
|
Body []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +183,11 @@ func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, err
|
|||||||
client.setQueryParam(req, rawUrl, request.QueryParams)
|
client.setQueryParam(req, rawUrl, request.QueryParams)
|
||||||
|
|
||||||
if request.FormData != nil {
|
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
|
client.Request = req
|
||||||
@@ -244,10 +251,79 @@ func (client *HttpClient) setQueryParam(req *http.Request, reqUrl string, queryP
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *HttpClient) setFormData(req *http.Request, values url.Values) {
|
func (client *HttpClient) setFormData(req *http.Request, values url.Values, setFile SetFileFunc) error {
|
||||||
formData := []byte(values.Encode())
|
if setFile != nil {
|
||||||
req.Body = ioutil.NopCloser(bytes.NewReader(formData))
|
err := setFile(req, values)
|
||||||
req.ContentLength = int64(len(formData))
|
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.
|
// validateRequest check if a request has url, and valid method.
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
package netutil
|
package netutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/internal"
|
"github.com/duke-git/lancet/internal"
|
||||||
@@ -250,3 +253,108 @@ func TestStructToUrlValues(t *testing.T) {
|
|||||||
assert.Equal("456", queryValues2.Get("userId"))
|
assert.Equal("456", queryValues2.Get("userId"))
|
||||||
assert.Equal("", queryValues2.Get("name"))
|
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")
|
result2 := IsTelnetConnected("www.baidu.com", "123")
|
||||||
assert.Equal(false, result2)
|
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
|
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}$`)
|
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))
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package strutil
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
@@ -503,3 +504,21 @@ func ContainsAny(str string, substrs []string) bool {
|
|||||||
|
|
||||||
return false
|
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(true, ContainsAny("hello world", []string{"hello", "abc"}))
|
||||||
assert.Equal(false, ContainsAny("hello world", []string{"123", "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")
|
assert := internal.NewAssert(t, "TestExecCommand")
|
||||||
|
|
||||||
// linux or mac
|
// linux or mac
|
||||||
stdout, stderr, err := ExecCommand("ls", WithForeground())
|
stdout, stderr, err := ExecCommand("ls")
|
||||||
t.Log("std out: ", stdout)
|
t.Log("std out: ", stdout)
|
||||||
t.Log("std err: ", stderr)
|
t.Log("std err: ", stderr)
|
||||||
assert.Equal("", stderr)
|
assert.Equal("", stderr)
|
||||||
|
|||||||
Reference in New Issue
Block a user