mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-05 05:12:26 +08:00
Compare commits
79 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3050d93703 | ||
|
|
efcfbfb6a1 | ||
|
|
844b7a2c3b | ||
|
|
c8a536eafc | ||
|
|
0fd268face | ||
|
|
8ced7e887f | ||
|
|
957568ed5c | ||
|
|
fffabd0ffa | ||
|
|
e839af3ef9 | ||
|
|
1650e70d04 | ||
|
|
23382b2b76 | ||
|
|
daa3aa3da2 | ||
|
|
be355a23f3 | ||
|
|
95af83b0cb | ||
|
|
1efdbc0973 | ||
|
|
9b829aa695 | ||
|
|
bfa9091c09 | ||
|
|
c11d63c2e2 | ||
|
|
83832daeb1 | ||
|
|
7311f84772 | ||
|
|
a63d78111e | ||
|
|
e2fc2f1bc9 | ||
|
|
23a0135947 | ||
|
|
013b6457bb | ||
|
|
e08a62b0ba | ||
|
|
850800a233 | ||
|
|
a6a8fd88bc | ||
|
|
2f6ee84443 | ||
|
|
b1c6614549 | ||
|
|
a8761eefb0 | ||
|
|
cbf8cfdffa | ||
|
|
286a187942 | ||
|
|
b787e99528 | ||
|
|
e54c9b2850 | ||
|
|
8944109c4c | ||
|
|
10e3732f32 | ||
|
|
a415597c6b | ||
|
|
69b32fd043 | ||
|
|
75ed359084 | ||
|
|
2c71b6375c | ||
|
|
2894bec80c | ||
|
|
09ec5b97a6 | ||
|
|
46ecb117a5 | ||
|
|
388171e739 | ||
|
|
6fbaf2b005 | ||
|
|
53a91cad71 | ||
|
|
a51a182fb2 | ||
|
|
64982f0c89 | ||
|
|
f38f69ce17 | ||
|
|
a33ea3d013 | ||
|
|
e35462fb14 | ||
|
|
af106a4a8e | ||
|
|
ec7232ec40 | ||
|
|
67c1b54b5a | ||
|
|
e149ae2f72 | ||
|
|
b1fcfce188 | ||
|
|
259dbce85e | ||
|
|
78aa679670 | ||
|
|
3beb769f09 | ||
|
|
8af02ff95b | ||
|
|
ba4485d8c0 | ||
|
|
8a1dd40738 | ||
|
|
85e2806531 | ||
|
|
1616d3d1be | ||
|
|
aa8e0d5c12 | ||
|
|
f05477d9cf | ||
|
|
cd91e16b26 | ||
|
|
9fcf046fb3 | ||
|
|
c3f1bc39d7 | ||
|
|
f5784b0f46 | ||
|
|
c86a8a479d | ||
|
|
e2aeb8ec07 | ||
|
|
654ba15aaf | ||
|
|
945c59896b | ||
|
|
219e31d929 | ||
|
|
82cb86b35c | ||
|
|
f93c561f5d | ||
|
|
4888909208 | ||
|
|
33c8875d14 |
112
README.md
112
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/v2)
|
||||
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||
@@ -25,7 +25,7 @@ English | [简体中文](./README_zh-CN.md)
|
||||
|
||||
- 👏 Comprehensive, efficient and reusable.
|
||||
- 💪 500+ go util functions, support string, slice, datetime, net, crypt...
|
||||
- 💅 Only depend on the go standard library.
|
||||
- 💅 Only depends on two kinds of libraries: go standard library and golang.org/x.
|
||||
- 🌍 Unit test for every exported function.
|
||||
|
||||
## Installation
|
||||
@@ -38,7 +38,7 @@ English | [简体中文](./README_zh-CN.md)
|
||||
go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x
|
||||
```
|
||||
|
||||
2. <b>For users who use version below go1.18, you should install v1.x.x. The latest of v1.x.x is v1.3.8. </b>
|
||||
2. <b>For users who use version below go1.18, you should install v1.x.x. The latest of v1.x.x is v1.4.0. </b>
|
||||
|
||||
```go
|
||||
go get github.com/duke-git/lancet // below go1.18, install latest version of v1.x.x
|
||||
@@ -128,16 +128,22 @@ import "github.com/duke-git/lancet/v2/compare"
|
||||
|
||||
- **<big>Equal</big>** : Checks if two values are equal or not. (check both type and value)
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare.md#Equal)]
|
||||
[[play](https://go.dev/play/p/wmVxR-to4lz)]
|
||||
- **<big>EqualValue</big>** : Checks if two values are equal or not. (check value only)
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare.md#EqualValue)]
|
||||
[[play](https://go.dev/play/p/fxnna_LLD9u)]
|
||||
- **<big>LessThan</big>** : Checks if value `left` less than value `right`.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare.md#LessThan)]
|
||||
[[play](https://go.dev/play/p/cYh7FQQj0ne)]
|
||||
- **<big>GreaterThan</big>** : Checks if value `left` greater than value `right`.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare.md#GreaterThan)]
|
||||
[[play](https://go.dev/play/p/9-NYDFZmIMp)]
|
||||
- **<big>LessOrEqual</big>** : Checks if value `left` less than or equal than value `right`.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare.md#LessOrEqual)]
|
||||
[[play](https://go.dev/play/p/e4T_scwoQzp)]
|
||||
- **<big>GreaterOrEqual</big>** : Checks if value `left` less greater or equal than value `right`.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare.md#GreaterOrEqual)]
|
||||
[[play](https://go.dev/play/p/vx8mP0U8DFk)]
|
||||
|
||||
### 3. Concurrency package contain some functions to support concurrent programming. eg, goroutine, channel, async.
|
||||
|
||||
@@ -194,13 +200,13 @@ import "github.com/duke-git/lancet/v2/condition"
|
||||
[[play](https://go.dev/play/p/W1SSUmt6pvr)]
|
||||
- **<big>Or</big>** : returns false if neither a nor b is truthy.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Or)]
|
||||
[[play](https://go.dev/play/p/UlQTxHaeEkq)]]
|
||||
[[play](https://go.dev/play/p/UlQTxHaeEkq)]
|
||||
- **<big>Xor</big>** : returns true if a or b but not both is truthy.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Xor)]
|
||||
[[play](https://go.dev/play/p/gObZrW7ZbG8)]
|
||||
- **<big>Nor</big>** : returns true if neither a nor b is truthy.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Nor)]
|
||||
[[play](https://go.dev/play/p/g2j08F_zZky)
|
||||
[[play](https://go.dev/play/p/g2j08F_zZky)]
|
||||
- **<big>Xnor</big>** : returns true if both a and b or neither a nor b are truthy.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Xnor)]
|
||||
[[play](https://go.dev/play/p/OuDB9g51643)]
|
||||
@@ -272,7 +278,14 @@ import "github.com/duke-git/lancet/v2/convertor"
|
||||
[[play](https://go.dev/play/p/j4DP5dquxnk)]
|
||||
- **<big>CopyProperties</big>** : copies each field from the source struct into the destination struct.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#CopyProperties)]
|
||||
[[play](https://go.dev/play/p/FOVY3XJL-6B)]
|
||||
[[play](https://go.dev/play/p/oZujoB5Sgg5)]
|
||||
- **<big>ToInterface</big>** : converts reflect value to its interface type.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToInterface)]
|
||||
[[play](https://go.dev/play/p/syqw0-WG7Xd)]
|
||||
- **<big>Utf8ToGbk</big>** : converts utf8 encoding data to GBK encoding data
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#Utf8ToGbk)]
|
||||
- **<big>GbkToUtf8</big>** : converts GBK encoding data to utf8 encoding data.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#GbkToUtf8)]
|
||||
|
||||
### 6. Cryptor package is for data encryption and decryption.
|
||||
|
||||
@@ -395,6 +408,9 @@ import "github.com/duke-git/lancet/v2/datetime"
|
||||
- **<big>AddMinute</big>** : add or sub day to the time.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddMinute)]
|
||||
[[play](https://go.dev/play/p/nT1heB1KUUK)]
|
||||
- **<big>AddYear</big>** : add or sub year to the time.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddYear)]
|
||||
[[play](https://go.dev/play/p/MqW2ujnBx10)]
|
||||
- **<big>BeginOfMinute</big>** : return the date time at the begin of minute of specific date.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMinute)]
|
||||
[[play](https://go.dev/play/p/ieOLVJ9CiFT)]
|
||||
@@ -476,6 +492,19 @@ import "github.com/duke-git/lancet/v2/datetime"
|
||||
- **<big>ToIso8601</big>** : return iso8601 time string.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToIso8601)]
|
||||
[[play](https://go.dev/play/p/mkhOHQkdeA2)]
|
||||
- **<big>IsLeapYear</big>** : check if param `year` is leap year or not.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#IsLeapYear)]
|
||||
[[play](https://go.dev/play/p/xS1eS2ejGew)]
|
||||
- **<big>BetweenSeconds</big>** : returns the number of seconds between two times.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BetweenSeconds)]
|
||||
[[play](https://go.dev/play/p/n3YDRyfyXJu)]
|
||||
- **<big>DayOfYear</big>** : returns which day of the year the parameter date `t` is.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#DayOfYear)]
|
||||
[[play](https://go.dev/play/p/0hjqhTwFNlH)]
|
||||
- **<big>IsWeekend</big>** : checks if passed time is weekend or not.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#IsWeekend)]
|
||||
[[play](https://go.dev/play/p/cupRM5aZOIY)]
|
||||
|
||||
|
||||
### 8. Datastructure package constains some common data structure. eg. list, linklist, stack, queue, set, tree, graph.
|
||||
|
||||
@@ -556,9 +585,11 @@ import "github.com/duke-git/lancet/v2/fileutil"
|
||||
- **<big>ReadFileByLine</big>** : read file line by line, return string slice of file content.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ReadFileByLine)]
|
||||
[[play](https://go.dev/play/p/svJP_7ZrBrD)]
|
||||
- **<big>Zip</big>** : create zip file.
|
||||
- **<big>Zip</big>** : create a zip file of fpath, fpath could be a file or a directory.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#Zip)]
|
||||
[[play](https://go.dev/play/p/j-3sWBp8ik_P)]
|
||||
- **<big>ZipAppendEntry</big>** : append a single file or directory by fpath to an existing zip file.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ZipAppendEntry)]
|
||||
- **<big>UnZip</big>** : unzip the zip file and save it to dest path.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#UnZip)]
|
||||
[[play](https://go.dev/play/p/g0w34kS7B8m)]
|
||||
@@ -567,14 +598,28 @@ import "github.com/duke-git/lancet/v2/fileutil"
|
||||
[[play](https://go.dev/play/p/s74a9iBGcSw)]
|
||||
- **<big>IsZipFile</big>** : checks if file is zip file or not.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#IsZipFile)]
|
||||
[[play](https://go.dev/play/p/9M0g2j_uF_e)]
|
||||
- **<big>FileSize</big>** : return file size in bytes.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#FileSize)]
|
||||
[[play](https://go.dev/play/p/H9Z05uD-Jjc)]
|
||||
- **<big>MTime</big>** : return file modified time(unix timestamp).
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#MTime)]
|
||||
[[play](https://go.dev/play/p/s_Tl7lZoAaY)]
|
||||
- **<big>Sha</big>** : return file sha value.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#Sha)]
|
||||
[[play](https://go.dev/play/p/VfEEcO2MJYf)]
|
||||
- **<big>ReadCsvFile</big>** : read file content into slice.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ReadCsvFile)]
|
||||
[[play](https://go.dev/play/p/OExTkhGEd3_u)]
|
||||
- **<big>WriteCsvFile</big>** : write content to target csv file.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#WriteCsvFile)]
|
||||
- **<big>WriteBytesToFile</big>** : write bytes to target file.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#WriteBytesToFile)]
|
||||
[[play](https://go.dev/play/p/s7QlDxMj3P8)]
|
||||
- **<big>WriteStringToFile</big>** : write string to target file.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#WriteStringToFile)]
|
||||
[[play](https://go.dev/play/p/GhLS6d8lH_g)]
|
||||
|
||||
|
||||
### 10. Formatter contains some functions for data formatting.
|
||||
|
||||
@@ -748,7 +793,7 @@ import "github.com/duke-git/lancet/v2/mathutil"
|
||||
[[play](https://go.dev/play/p/N9qgYg_Ho6f)]
|
||||
- **<big>Percent</big>** : calculate the percentage of value to total.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Percent)]
|
||||
[[play](https://go.dev/play/p/QQM9B13coSP)]
|
||||
[[play](https://go.dev/play/p/s0NdFCtwuyd)]
|
||||
- **<big>RoundToFloat</big>** : round up to n decimal places for float64.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#RoundToFloat)]
|
||||
[[play](https://go.dev/play/p/ghyb528JRJL)]
|
||||
@@ -776,6 +821,22 @@ import "github.com/duke-git/lancet/v2/mathutil"
|
||||
- **<big>IsPrime</big>** : checks if number is prime number.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#IsPrime)]
|
||||
[[play](https://go.dev/play/p/Rdd8UTHZJ7u)]
|
||||
- **<big>GCD</big>** : return greatest common divisor (GCD) of integers.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#GCD)]
|
||||
[[play](https://go.dev/play/p/CiEceLSoAKB)]
|
||||
- **<big>LCM</big>** : return Least Common Multiple (LCM) of integers.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#LCM)]
|
||||
[[play](https://go.dev/play/p/EjcZxfY7G_g)]
|
||||
- **<big>Cos</big>** : return the cosine of the radian argument.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Cos)]
|
||||
[[play](https://go.dev/play/p/Sm89LoIfvFq)]
|
||||
- **<big>Sin</big>** : return the sine of the radian argument.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Sin)]
|
||||
[[play](https://go.dev/play/p/TWMQlMywDsP)]
|
||||
- **<big>Log</big>** : returns the logarithm of base n.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Log)]
|
||||
- **<big>Sum</big>** : return sum of passed numbers.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Sum)]
|
||||
|
||||
### 14. Netutil package contains functions to get net information and send http request.
|
||||
|
||||
@@ -845,8 +906,10 @@ import "github.com/duke-git/lancet/v2/netutil"
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#UploadFile)]
|
||||
- **<big>IsPingConnected</big>** : checks if can ping the specified host or not.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#IsPingConnected)]
|
||||
[[play](https://go.dev/play/p/q8OzTijsA87)]
|
||||
- **<big>IsTelnetConnected</big>** : checks if can if can telnet the specified host or not.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#IsTelnetConnected)]
|
||||
[[play](https://go.dev/play/p/yiLCGtQv_ZG)]
|
||||
|
||||
### 15. Random package implements some basic functions to generate random int and string.
|
||||
|
||||
@@ -880,6 +943,8 @@ import "github.com/duke-git/lancet/v2/random"
|
||||
- **<big>UUIdV4</big>** : generate a random UUID of version 4 according to RFC 4122.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random.md#UUIdV4)]
|
||||
[[play](https://go.dev/play/p/_Z9SFmr28ft)]
|
||||
- **<big>RandUniqueIntSlice</big>** : generate a slice of random int of length n that do not repeat.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandUniqueIntSlice)]
|
||||
|
||||
### 16. Retry package is for executing a function repeatedly until it was successful or canceled by the context.
|
||||
|
||||
@@ -984,11 +1049,13 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
[[play](https://go.dev/play/p/CBKeBoHVLgq)]
|
||||
- **<big>FindBy</big>** : iterates over elements of slice, returning the first one that passes a truth test on predicate function.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FindBy)]
|
||||
[[play](https://go.dev/play/p/n1lysBYl-GB)]
|
||||
- **<big>FindLast<sup>deprecated</sup></big>** : return the last item that passes a truth test on predicate function.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FindLast)]
|
||||
[[play](https://go.dev/play/p/FFDPV_j7URd)]
|
||||
- **<big>FindLastBy</big>** : iterates over elements of slice, returning the last one that passes a truth test on predicate function.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FindLastBy)]
|
||||
[[play](https://go.dev/play/p/8iqomzyCl_s)]
|
||||
- **<big>Flatten</big>** : flattens slice one level.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Flatten)]
|
||||
[[play](https://go.dev/play/p/hYa3cBEevtm)]
|
||||
@@ -1178,6 +1245,9 @@ import "github.com/duke-git/lancet/v2/stream"
|
||||
- **<big>FindFirst</big>** : returns the first element of this stream and true, or zero value and false if the stream is empty.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#FindFirst)]
|
||||
[[play](https://go.dev/play/p/9xEf0-6C1e3)]
|
||||
- **<big>FindLast</big>** : returns the last element of this stream and true, or zero value and false if the stream is empty.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#FindLast)]
|
||||
[[play](https://go.dev/play/p/WZD2rDAW-2h)]
|
||||
- **<big>Max</big>** : returns the maximum element of this stream according to the provided less function. less fuction: a > b
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Max)]
|
||||
[[play](https://go.dev/play/p/fm-1KOPtGzn)]
|
||||
@@ -1258,6 +1328,12 @@ import "github.com/duke-git/lancet/v2/strutil"
|
||||
- **<big>Capitalize</big>** : converts the first character of source string to upper case and the remaining to lower case.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Capitalize)]
|
||||
[[play](https://go.dev/play/p/2OAjgbmAqHZ)]
|
||||
- **<big>ContainsAll</big>** : return true if target string contains all the substrings.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#ContainsAll)]
|
||||
[[play](https://go.dev/play/p/KECtK2Os4zq)]
|
||||
- **<big>ContainsAny</big>** : return true if target string contains any one of the substrings.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#ContainsAny)]
|
||||
[[play](https://go.dev/play/p/dZGSSMB3LXE)]
|
||||
- **<big>IsString</big>** : checks if the parameter value data type is string or not.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#IsString)]
|
||||
[[play](https://go.dev/play/p/IOgq7oF9ERm)]
|
||||
@@ -1314,16 +1390,36 @@ import "github.com/duke-git/lancet/v2/strutil"
|
||||
[[play](https://go.dev/play/p/og47F5x_jTZ)]
|
||||
- **<big>StringToBytes</big>** : converts a string to byte slice without a memory allocation.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#StringToBytes)]
|
||||
[[play](https://go.dev/play/p/7OyFBrf9AxA)]
|
||||
- **<big>BytesToString</big>** : converts a byte slice to string without a memory allocation.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#BytesToString)]
|
||||
[[play](https://go.dev/play/p/6c68HRvJecH)]
|
||||
- **<big>IsBlank</big>** : checks if a string is whitespace or empty.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#IsBlank)]
|
||||
[[play](https://go.dev/play/p/6zXRH_c0Qd3)]
|
||||
- **<big>HasPrefixAny</big>** : checks if a string starts with any of an array of specified strings.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#HasPrefixAny)]
|
||||
[[play](https://go.dev/play/p/8UUTl2C5slo)]
|
||||
- **<big>HasSuffixAny</big>** : checks if a string ends with any of an array of specified strings.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#HasSuffixAny)]
|
||||
[[play](https://go.dev/play/p/sKWpCQdOVkx)]
|
||||
- **<big>IndexOffset</big>** : returns the index of the first instance of substr in string after offsetting the string by `idxFrom`.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#IndexOffset)]
|
||||
[[play](https://go.dev/play/p/qZo4lV2fomB)]
|
||||
- **<big>ReplaceWithMap</big>** : returns a copy of `str`, which is replaced by a map in unordered way, case-sensitively.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#ReplaceWithMap)]
|
||||
[[play](https://go.dev/play/p/h3t7CNj2Vvu)]
|
||||
- **<big>Trim</big>** : strips whitespace (or other characters) from the beginning and end of a string.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Trim)]
|
||||
[[play](https://go.dev/play/p/Y0ilP0NRV3j)]
|
||||
- **<big>SplitAndTrim</big>** : splits string `str` by a string `delimiter` to a slice, and calls Trim to every element of slice.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SplitAndTrim)]
|
||||
[[play](https://go.dev/play/p/ZNL6o4SkYQ7)]
|
||||
- **<big>HideString</big>** : Hide some chars in source string with param `replaceChar`.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#HideString)]
|
||||
[[play](https://go.dev/play/p/pzbaIVCTreZ)]
|
||||
- **<big>RemoveWhiteSpace</big>** : remove whitespace characters from a string.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#RemoveWhiteSpace)]
|
||||
|
||||
### 21. System package contain some functions about os, runtime, shell command.
|
||||
|
||||
|
||||
137
README_zh-CN.md
137
README_zh-CN.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/v2)
|
||||
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||
@@ -22,10 +22,10 @@
|
||||
|
||||
## 特性
|
||||
|
||||
- 👏 全面、高效、可复用
|
||||
- 👏 全面、高效、可复用。
|
||||
- 💪 500+常用 go 工具函数,支持 string、slice、datetime、net、crypt...
|
||||
- 💅 只依赖 go 标准库
|
||||
- 🌍 所有导出函数单元测试覆盖率 100%
|
||||
- 💅 只依赖 go 标准库和 golang.org/x。
|
||||
- 🌍 所有导出函数单元测试覆盖率 100%。
|
||||
|
||||
## 安装
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
go get github.com/duke-git/lancet/v2 //安装v2最新版本v2.x.x
|
||||
```
|
||||
|
||||
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.3.7。</b>
|
||||
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.4.0。</b>
|
||||
|
||||
```go
|
||||
go get github.com/duke-git/lancet// 使用go1.18以下版本, 必须安装v1.x.x版本
|
||||
@@ -127,16 +127,22 @@ import "github.com/duke-git/lancet/v2/compare"
|
||||
|
||||
- **<big>Equal</big>** : 检查两个值是否相等(检查类型和值)。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare_zh-CN.md#Equal)]
|
||||
[[play](https://go.dev/play/p/wmVxR-to4lz)]
|
||||
- **<big>EqualValue</big>** : 检查两个值是否相等(只检查值)。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare_zh-CN.md#EqualValue)]
|
||||
[[play](https://go.dev/play/p/fxnna_LLD9u)]
|
||||
- **<big>LessThan</big>** : 验证参数`left`的值是否小于参数`right`的值。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare_zh-CN.md#LessThan)]
|
||||
[[play](https://go.dev/play/p/cYh7FQQj0ne)]
|
||||
- **<big>GreaterThan</big>** : 验证参数`left`的值是否大于参数`right`的值。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare_zh-CN.md#GreaterThan)]
|
||||
[[play](https://go.dev/play/p/9-NYDFZmIMp)]
|
||||
- **<big>LessOrEqual</big>** : 验证参数`left`的值是否小于或等于参数`right`的值。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare_zh-CN.md#LessOrEqual)]
|
||||
[[play](https://go.dev/play/p/e4T_scwoQzp)]
|
||||
- **<big>GreaterOrEqual</big>** : 验证参数`left`的值是否大于或等于参数`right`的值。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare_zh-CN.md#GreaterOrEqual)]
|
||||
[[play](https://go.dev/play/p/vx8mP0U8DFk)]
|
||||
|
||||
### 3. concurrency 包含一些支持并发编程的功能。例如:goroutine, channel, async 等。
|
||||
|
||||
@@ -199,10 +205,10 @@ import "github.com/duke-git/lancet/v2/condition"
|
||||
[[play](https://go.dev/play/p/gObZrW7ZbG8)]
|
||||
- **<big>Nor</big>** : 异或的取反操作。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Nor)]
|
||||
[[play](https://go.dev/play/p/g2j08F_zZky)
|
||||
[[play](https://go.dev/play/p/g2j08F_zZky)]
|
||||
- **<big>Xnor</big>** : 如果 a 和 b 都是真的或 a 和 b 均是假的,则返回 true。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Xnor)]
|
||||
[[play](https://go.dev/play/p/OuDB9g51643)]]
|
||||
[[play](https://go.dev/play/p/OuDB9g51643)]
|
||||
- **<big>Nand</big>** : 如果 a 和 b 都为真,返回 false,否则返回 true
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Nand)]
|
||||
[[play](https://go.dev/play/p/vSRMLxLIbq8)]
|
||||
@@ -271,7 +277,14 @@ import "github.com/duke-git/lancet/v2/convertor"
|
||||
[[play](https://go.dev/play/p/j4DP5dquxnk)]
|
||||
- **<big>CopyProperties</big>** : 拷贝不同结构体之间的同名字段。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#CopyProperties)]
|
||||
[[play](https://go.dev/play/p/FOVY3XJL-6B)]
|
||||
[[play](https://go.dev/play/p/oZujoB5Sgg5)]
|
||||
- **<big>ToInterface</big>** : 将反射值转换成对应的 interface 类型。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToInterface)]
|
||||
[[play](https://go.dev/play/p/syqw0-WG7Xd)]
|
||||
- **<big>Utf8ToGbk</big>** : utf8 编码转 GBK 编码。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#Utf8ToGbk)]
|
||||
- **<big>GbkToUtf8</big>** : GBK 编码转 utf8 编码。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#GbkToUtf8)]
|
||||
|
||||
### 6. cryptor 加密包支持数据加密和解密,获取 md5,hash 值。支持 base64, md5, hmac, aes, des, rsa。
|
||||
|
||||
@@ -394,6 +407,9 @@ import "github.com/duke-git/lancet/v2/datetime"
|
||||
- **<big>AddMinute</big>** : 将日期加/减分钟数。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddMinute)]
|
||||
[[play](https://go.dev/play/p/nT1heB1KUUK)]
|
||||
- **<big>AddYear</big>** : 将日期加/减分年数。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddYear)]
|
||||
[[play](https://go.dev/play/p/MqW2ujnBx10)]
|
||||
- **<big>BeginOfMinute</big>** : 返回指定时间的分钟开始时间。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#BeginOfMinute)]
|
||||
[[play](https://go.dev/play/p/ieOLVJ9CiFT)]
|
||||
@@ -475,6 +491,21 @@ import "github.com/duke-git/lancet/v2/datetime"
|
||||
- **<big>ToIso8601</big>** : 返回 iso8601 日期字符串。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToIso8601)]
|
||||
[[play](https://go.dev/play/p/mkhOHQkdeA2)]
|
||||
- **<big>IsLeapYear</big>** :验证是否是闰年。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#IsLeapYear)]
|
||||
[[play](https://go.dev/play/p/xS1eS2ejGew)]
|
||||
- **<big>IsLeapYear</big>** : check if param `year` is leap year or not.
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#IsLeapYear)]
|
||||
[[play](https://go.dev/play/p/xS1eS2ejGew)]
|
||||
- **<big>BetweenSeconds</big>** : 返回两个时间的间隔秒数。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#BetweenSeconds)]
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BetweenSeconds)]
|
||||
- **<big>DayOfYear</big>** : 返回参数日期是一年中的第几天。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#DayOfYear)]
|
||||
[[play](https://go.dev/play/p/0hjqhTwFNlH)]
|
||||
- **<big>IsWeekend</big>** : 判断日期是否是周末。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#IsWeekend)]
|
||||
[[play](https://go.dev/play/p/cupRM5aZOIY)]
|
||||
|
||||
### 8. datastructure 包含一些普通的数据结构实现。例如:list, linklist, stack, queue, set, tree, graph.
|
||||
|
||||
@@ -558,22 +589,37 @@ import "github.com/duke-git/lancet/v2/fileutil"
|
||||
- **<big>Zip</big>** : zip 压缩文件, 参数可以是文件或目录。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#Zip)]
|
||||
[[play](https://go.dev/play/p/j-3sWBp8ik_P)]
|
||||
- **<big>ZipAppendEntry</big>** : 通过将单个文件或目录追加到现有的 zip 文件。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ZipAppendEntry)]
|
||||
- **<big>UnZip</big>** : zip 解压缩文件并保存在目录中。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#UnZip)]
|
||||
[[play](https://go.dev/play/p/g0w34kS7B8m)]
|
||||
- **<big>CurrentPath</big>** : 返回当前位置的绝对路径。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#CurrentPath)]
|
||||
[[play](https://go.dev/play/p/s74a9iBGcSw)]
|
||||
- **<big>IsZipFile</big>** : 判断文件是否是zip压缩文件。
|
||||
- **<big>IsZipFile</big>** : 判断文件是否是 zip 压缩文件。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#IsZipFile)]
|
||||
[[play](https://go.dev/play/p/9M0g2j_uF_e)]
|
||||
- **<big>FileSize</big>** : 返回文件字节大小。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#FileSize)]
|
||||
[[play](https://go.dev/play/p/H9Z05uD-Jjc)]
|
||||
- **<big>MTime</big>** : 返回文件修改时间(unix timestamp)。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#MTime)]
|
||||
- **<big>Sha</big>** : 返回文件sha值。
|
||||
[[play](https://go.dev/play/p/s_Tl7lZoAaY)]
|
||||
- **<big>Sha</big>** : 返回文件 sha 值。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#Sha)]
|
||||
- **<big>ReadCsvFile</big>** : 读取csv文件内容到切片。
|
||||
[[play](https://go.dev/play/p/VfEEcO2MJYf)]
|
||||
- **<big>ReadCsvFile</big>** : 读取 csv 文件内容到切片。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ReadCsvFile)]
|
||||
[[play](https://go.dev/play/p/OExTkhGEd3_u)]
|
||||
- **<big>WriteCsvFile</big>** : 向 csv 文件写入内容。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#WriteCsvFile)]
|
||||
- **<big>WriteBytesToFile</big>** : 将 bytes 写入文件。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#WriteBytesToFile)]
|
||||
[[play](https://go.dev/play/p/s7QlDxMj3P8)]
|
||||
- **<big>WriteStringToFile</big>** : 将字符串写入文件。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#WriteStringToFile)]
|
||||
[[play](https://go.dev/play/p/GhLS6d8lH_g)]
|
||||
|
||||
### 10. formatter 格式化器包含一些数据格式化处理方法。
|
||||
|
||||
@@ -747,7 +793,7 @@ import "github.com/duke-git/lancet/v2/mathutil"
|
||||
[[play](https://go.dev/play/p/N9qgYg_Ho6f)]
|
||||
- **<big>Percent</big>** : 计算百分比,可以指定保留 n 位小数。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Percent)]
|
||||
[[play](https://go.dev/play/p/QQM9B13coSP)]
|
||||
[[play](https://go.dev/play/p/s0NdFCtwuyd)]
|
||||
- **<big>RoundToFloat</big>** : 四舍五入,保留 n 位小数,返回 float64。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RoundToFloat)]
|
||||
[[play](https://go.dev/play/p/ghyb528JRJL)]
|
||||
@@ -775,6 +821,22 @@ import "github.com/duke-git/lancet/v2/mathutil"
|
||||
- **<big>IsPrime</big>** : 判断质数。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#IsPrime)]
|
||||
[[play](https://go.dev/play/p/Rdd8UTHZJ7u)]
|
||||
- **<big>GCD</big>** : 求最大公约数。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#GCD)]
|
||||
[[play](https://go.dev/play/p/CiEceLSoAKB)]
|
||||
- **<big>LCM</big>** : 求最小公倍数。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#LCM)]
|
||||
[[play](https://go.dev/play/p/EjcZxfY7G_g)]
|
||||
- **<big>Cos</big>** : 计算弧度的余弦值。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Cos)]
|
||||
[[play](https://go.dev/play/p/Sm89LoIfvFq)]
|
||||
- **<big>Sin</big>** : 计算弧度的正弦值。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Sin)]
|
||||
[[play](https://go.dev/play/p/TWMQlMywDsP)]
|
||||
- **<big>Log</big>** : 计算以 base 为底 n 的对数。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Log)]
|
||||
- **<big>Sum</big>** : 求传入参数之和。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Sum)]
|
||||
|
||||
### 14. netutil 网络包支持获取 ip 地址,发送 http 请求。
|
||||
|
||||
@@ -836,16 +898,18 @@ import "github.com/duke-git/lancet/v2/netutil"
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPut)]
|
||||
- **<big>HttpPatch<sup>deprecated</sup></big>** : 发送 http patch 请求(已弃用:SendRequest 代替)。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPatch)]
|
||||
- **<big>ParseHttpResponse</big>** : 解析http响应体到目标结构体。
|
||||
- **<big>ParseHttpResponse</big>** : 解析 http 响应体到目标结构体。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#ParseHttpResponse)]
|
||||
- **<big>DownloadFile</big>** : 从指定的server地址下载文件。
|
||||
- **<big>DownloadFile</big>** : 从指定的 server 地址下载文件。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#DownloadFile)]
|
||||
- **<big>UploadFile</big>** : 将文件上传指定的server地址。
|
||||
- **<big>UploadFile</big>** : 将文件上传指定的 server 地址。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#UploadFile)]
|
||||
- **<big>IsPingConnected</big>** : 检查能否ping通主机。
|
||||
- **<big>IsPingConnected</big>** : 检查能否 ping 通主机。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#IsPingConnected)]
|
||||
- **<big>IsTelnetConnected</big>** : 检查能否telnet到主机。
|
||||
[[play](https://go.dev/play/p/q8OzTijsA87)]
|
||||
- **<big>IsTelnetConnected</big>** : 检查能否 telnet 到主机。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#IsTelnetConnected)]
|
||||
[[play](https://go.dev/play/p/yiLCGtQv_ZG)]
|
||||
|
||||
### 15. random 随机数生成器包,可以生成随机[]bytes, int, string。
|
||||
|
||||
@@ -879,6 +943,8 @@ import "github.com/duke-git/lancet/v2/random"
|
||||
- **<big>UUIdV4</big>** : 生成 UUID v4 字符串。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#UUIdV4)]
|
||||
[[play](https://go.dev/play/p/_Z9SFmr28ft)]
|
||||
- **<big>RandUniqueIntSlice</big>** : 生成一个不重复的长度为n的随机int切片。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandUniqueIntSlice)]
|
||||
|
||||
### 16. retry 重试执行函数直到函数运行成功或被 context cancel。
|
||||
|
||||
@@ -983,11 +1049,13 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
[[play](https://go.dev/play/p/CBKeBoHVLgq)]
|
||||
- **<big>FindBy</big>** : 遍历切片的元素,返回第一个通过 predicate 函数真值测试的元素。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FindBy)]
|
||||
[[play](https://go.dev/play/p/n1lysBYl-GB)]
|
||||
- **<big>FindLast<sup>deprecated</sup></big>** : 从头到尾遍历 slice 的元素,返回最后一个通过 predicate 函数真值测试的元素。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FindLast)]
|
||||
[[play](https://go.dev/play/p/FFDPV_j7URd)]
|
||||
- **<big>FindLastBy</big>** : 从遍历slice的元素,返回最后一个通过predicate函数真值测试的元素。
|
||||
- **<big>FindLastBy</big>** : 从遍历 slice 的元素,返回最后一个通过 predicate 函数真值测试的元素。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FindLastBy)]
|
||||
[[play](https://go.dev/play/p/8iqomzyCl_s)]
|
||||
- **<big>Flatten</big>** : 将多维切片展平一层。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Flatten)]
|
||||
[[play](https://go.dev/play/p/hYa3cBEevtm)]
|
||||
@@ -1174,9 +1242,12 @@ import "github.com/duke-git/lancet/v2/stream"
|
||||
- **<big>Reduce</big>** : 使用关联累加函数对 stream 的元素执行 reduce 操作,并 reduce 操作结果(如果有)。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Reduce)]
|
||||
[[play](https://go.dev/play/p/6uzZjq_DJLU)]
|
||||
- **<big>FindFirst</big>** : 返回此 stream 的第一个元素和 true,如果 stream 为空,则返回零值和 false。
|
||||
- **<big>FindFirst</big>** : 返回此 stream 的第一个元素,如果 stream 为空,则返回零值和 false。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#FindFirst)]
|
||||
[[play](https://go.dev/play/p/9xEf0-6C1e3)]
|
||||
- **<big>FindLast</big>** : 返回此 stream 的最后一个元素,如果 stream 为空,则返回零值和 false。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#FindLast)]
|
||||
[[play](https://go.dev/play/p/WZD2rDAW-2h)]
|
||||
- **<big>Max</big>** : 根据提供的 less 函数返回 stream 的最大元素。less 函数: a > b
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Max)]
|
||||
[[play](https://go.dev/play/p/fm-1KOPtGzn)]
|
||||
@@ -1260,6 +1331,12 @@ import "github.com/duke-git/lancet/v2/strutil"
|
||||
- **<big>Capitalize</big>** : 将字符串的第一个字符转换为大写。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Capitalize)]
|
||||
[[play](https://go.dev/play/p/2OAjgbmAqHZ)]
|
||||
- **<big>ContainsAll</big>** : 判断字符串是否包括全部给定的子字符串切片。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#ContainsAll)]
|
||||
[[play](https://go.dev/play/p/KECtK2Os4zq)]
|
||||
- **<big>ContainsAny</big>** : 判断字符串是否包括给定的子字符串切片中任意一个子字符串。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#ContainsAny)]
|
||||
[[play](https://go.dev/play/p/dZGSSMB3LXE)]
|
||||
- **<big>IsString</big>** : 判断传入参数的数据类型是否为字符串。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#IsString)]
|
||||
[[play](https://go.dev/play/p/IOgq7oF9ERm)]
|
||||
@@ -1316,16 +1393,36 @@ import "github.com/duke-git/lancet/v2/strutil"
|
||||
[[play](https://go.dev/play/p/og47F5x_jTZ)]
|
||||
- **<big>StringToBytes</big>** : 在不分配内存的情况下将字符串转换为字节片。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#StringToBytes)]
|
||||
[[play](https://go.dev/play/p/7OyFBrf9AxA)]
|
||||
- **<big>BytesToString</big>** : 在不分配内存的情况下将字节切片转换为字符串。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#BytesToString)]
|
||||
[[play](https://go.dev/play/p/6c68HRvJecH)]
|
||||
- **<big>IsBlank</big>** : 检查字符串是否为空格或空。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#IsBlank)]
|
||||
[[play](https://go.dev/play/p/6zXRH_c0Qd3)]
|
||||
- **<big>HasPrefixAny</big>** : 检查字符串是否以指定字符串数组中的任何一个开头。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#HasPrefixAny)]
|
||||
[[play](https://go.dev/play/p/8UUTl2C5slo)]
|
||||
- **<big>HasSuffixAny</big>** : 检查字符串是否以指定字符串数组中的任何一个结尾。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#HasSuffixAny)]
|
||||
- **<big>IndexOffset</big>** : 将字符串偏移idxFrom后,返回字符串中第一个 substr 实例的索引。
|
||||
[[play](https://go.dev/play/p/sKWpCQdOVkx)]
|
||||
- **<big>IndexOffset</big>** : 将字符串偏移 idxFrom 后,返回字符串中第一个 substr 实例的索引。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#IndexOffset)]
|
||||
[[play](https://go.dev/play/p/qZo4lV2fomB)]
|
||||
- **<big>ReplaceWithMap</big>** : 返回 string 的副本,以无序的方式被 map 替换,区分大小写。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#ReplaceWithMap)]
|
||||
[[play](https://go.dev/play/p/h3t7CNj2Vvu)]
|
||||
- **<big>Trim</big>** : 从字符串的开头和结尾去除空格(或其他字符)。 可选参数 characterMask 指定额外的剥离字符。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Trim)]
|
||||
[[play](https://go.dev/play/p/Y0ilP0NRV3j)]
|
||||
- **<big>SplitAndTrim</big>** : 将字符串 str 按字符串 delimiter 拆分为一个切片,并对该数组的每个元素调用 Trim。忽略 Trim 后为空的元素。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#SplitAndTrim)]
|
||||
[[play](https://go.dev/play/p/ZNL6o4SkYQ7)]
|
||||
- **<big>HideString</big>** : 隐藏源字符串中的一些字符。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#HideString)]
|
||||
[[play](https://go.dev/play/p/pzbaIVCTreZ)]
|
||||
- **<big>RemoveWhiteSpace</big>** : 删除字符串中的空格。
|
||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#RemoveWhiteSpace)]
|
||||
|
||||
### 21. system 包含 os, runtime, shell command 的相关函数。
|
||||
|
||||
|
||||
@@ -27,32 +27,38 @@ var (
|
||||
)
|
||||
|
||||
// Equal checks if two values are equal or not. (check both type and value)
|
||||
// Play: https://go.dev/play/p/wmVxR-to4lz
|
||||
func Equal(left, right any) bool {
|
||||
return compareValue(equal, left, right)
|
||||
}
|
||||
|
||||
// EqualValue checks if two values are equal or not. (check value only)
|
||||
// Play: https://go.dev/play/p/fxnna_LLD9u
|
||||
func EqualValue(left, right any) bool {
|
||||
ls, rs := convertor.ToString(left), convertor.ToString(right)
|
||||
return ls == rs
|
||||
}
|
||||
|
||||
// LessThan checks if value `left` less than value `right`.
|
||||
// Play: https://go.dev/play/p/cYh7FQQj0ne
|
||||
func LessThan(left, right any) bool {
|
||||
return compareValue(lessThan, left, right)
|
||||
}
|
||||
|
||||
// GreaterThan checks if value `left` greater than value `right`.
|
||||
// Play: https://go.dev/play/p/9-NYDFZmIMp
|
||||
func GreaterThan(left, right any) bool {
|
||||
return compareValue(greaterThan, left, right)
|
||||
}
|
||||
|
||||
// LessOrEqual checks if value `left` less than or equal to value `right`.
|
||||
// Play: https://go.dev/play/p/e4T_scwoQzp
|
||||
func LessOrEqual(left, right any) bool {
|
||||
return compareValue(lessOrEqual, left, right)
|
||||
}
|
||||
|
||||
// GreaterOrEqual checks if value `left` greater than or equal to value `right`.
|
||||
// Play: https://go.dev/play/p/vx8mP0U8DFk
|
||||
func GreaterOrEqual(left, right any) bool {
|
||||
return compareValue(greaterOrEqual, left, right)
|
||||
}
|
||||
|
||||
@@ -11,12 +11,15 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"golang.org/x/text/encoding/simplifiedchinese"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// ToBool convert string to boolean.
|
||||
@@ -321,7 +324,7 @@ func DeepClone[T any](src T) T {
|
||||
|
||||
// CopyProperties copies each field from the source into the destination. It recursively copies struct pointers and interfaces that contain struct pointers.
|
||||
// use json.Marshal/Unmarshal, so json tag should be set for fields of dst and src struct.
|
||||
// Play: todo
|
||||
// Play: https://go.dev/play/p/oZujoB5Sgg5
|
||||
func CopyProperties[T, U any](dst T, src U) error {
|
||||
dstType, srcType := reflect.TypeOf(dst), reflect.TypeOf(src)
|
||||
|
||||
@@ -347,3 +350,47 @@ func CopyProperties[T, U any](dst T, src U) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToInterface converts reflect value to its interface type.
|
||||
// Play: https://go.dev/play/p/syqw0-WG7Xd
|
||||
func ToInterface(v reflect.Value) (value interface{}, ok bool) {
|
||||
if v.IsValid() && v.CanInterface() {
|
||||
return v.Interface(), true
|
||||
}
|
||||
switch v.Kind() {
|
||||
case reflect.Bool:
|
||||
return v.Bool(), true
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return v.Int(), true
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return v.Uint(), true
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float(), true
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
return v.Complex(), true
|
||||
case reflect.String:
|
||||
return v.String(), true
|
||||
case reflect.Ptr:
|
||||
return ToInterface(v.Elem())
|
||||
case reflect.Interface:
|
||||
return ToInterface(v.Elem())
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
|
||||
// Utf8ToGbk convert utf8 encoding data to GBK encoding data.
|
||||
// Play: todo
|
||||
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.
|
||||
// Play: todo
|
||||
func GbkToUtf8(bs []byte) ([]byte, error) {
|
||||
r := transform.NewReader(bytes.NewReader(bs), simplifiedchinese.GBK.NewDecoder())
|
||||
b, err := io.ReadAll(r)
|
||||
return b, err
|
||||
}
|
||||
|
||||
@@ -2,7 +2,11 @@ package convertor
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func ExampleToBool() {
|
||||
@@ -349,3 +353,41 @@ func ExampleCopyProperties() {
|
||||
// 127.0.0.1
|
||||
// 3
|
||||
}
|
||||
|
||||
func ExampleToInterface() {
|
||||
val := reflect.ValueOf("abc")
|
||||
iVal, ok := ToInterface(val)
|
||||
|
||||
fmt.Printf("%T\n", iVal)
|
||||
fmt.Printf("%v\n", iVal)
|
||||
fmt.Println(ok)
|
||||
|
||||
// Output:
|
||||
// string
|
||||
// abc
|
||||
// true
|
||||
}
|
||||
|
||||
func ExampleUtf8ToGbk() {
|
||||
utf8Data := []byte("hello")
|
||||
gbkData, _ := Utf8ToGbk(utf8Data)
|
||||
|
||||
fmt.Println(utf8.Valid(utf8Data))
|
||||
fmt.Println(validator.IsGBK(gbkData))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
}
|
||||
|
||||
func ExampleGbkToUtf8() {
|
||||
gbkData, _ := Utf8ToGbk([]byte("hello"))
|
||||
utf8Data, _ := GbkToUtf8(gbkData)
|
||||
|
||||
fmt.Println(utf8.Valid(utf8Data))
|
||||
fmt.Println(string(utf8Data))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// hello
|
||||
}
|
||||
|
||||
@@ -5,9 +5,11 @@ import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
"testing"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
"github.com/duke-git/lancet/v2/validator"
|
||||
)
|
||||
|
||||
func TestToChar(t *testing.T) {
|
||||
@@ -367,3 +369,54 @@ func TestCopyProperties(t *testing.T) {
|
||||
assert.Equal("127.0.0.1", indicatorVO.Ip)
|
||||
assert.Equal(3, len(indicatorVO.Disk))
|
||||
}
|
||||
|
||||
func TestToInterface(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestToInterface")
|
||||
|
||||
cases := []reflect.Value{
|
||||
reflect.ValueOf("abc"),
|
||||
reflect.ValueOf(int(0)), reflect.ValueOf(int8(1)), reflect.ValueOf(int16(-1)), reflect.ValueOf(int32(123)), reflect.ValueOf(int64(123)),
|
||||
reflect.ValueOf(uint(123)), reflect.ValueOf(uint8(123)), reflect.ValueOf(uint16(123)), reflect.ValueOf(uint32(123)), reflect.ValueOf(uint64(123)),
|
||||
reflect.ValueOf(float64(12.3)), reflect.ValueOf(float32(12.3)),
|
||||
reflect.ValueOf(true), reflect.ValueOf(false),
|
||||
}
|
||||
|
||||
expected := []interface{}{
|
||||
"abc",
|
||||
0, int8(1), int16(-1), int32(123), int64(123),
|
||||
uint(123), uint8(123), uint16(123), uint32(123), uint64(123),
|
||||
float64(12.3), float32(12.3),
|
||||
true, false,
|
||||
}
|
||||
|
||||
for i := 0; i < len(cases); i++ {
|
||||
actual, _ := ToInterface(cases[i])
|
||||
assert.Equal(expected[i], actual)
|
||||
}
|
||||
|
||||
nilVal, ok := ToInterface(reflect.ValueOf(nil))
|
||||
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))
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure implements some data structure. eg. list, linklist, stack, queue, tree, graph.
|
||||
// Package datastructure implements some data structure. hashmap structure.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure implements some data structure. eg. list, linklist, stack, queue, tree, graph.
|
||||
// Package datastructure implements some data structure. MaxHeap is a binary max heap.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure contains some data structure. Link structure contains SinglyLink and DoublyLink.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure contains some data structure. Link structure contains SinglyLink and DoublyLink.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure implements some data structure. eg. list, linklist, stack, queue, tree, graph.
|
||||
// Package datastructure contains some data structure. list is a linear table, implemented with slice.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure implements some data structure. eg. list, linklist, stack, queue, tree, graph.
|
||||
// Package datastructure implements some data structure.
|
||||
package datastructure
|
||||
|
||||
// LinkNode is a linkedlist node, which have a Value and Pre points to previous node, Next points to a next node of the link.
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure contains some data structure.
|
||||
// Queue structure contains ArrayQueue, LinkedQueue, CircularQueue, and PriorityQueue.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure contains some data structure.
|
||||
// Queue structure contains ArrayQueue, LinkedQueue, CircularQueue, and PriorityQueue.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure contains some data structure.
|
||||
// Queue structure contains ArrayQueue, LinkedQueue, CircularQueue, and PriorityQueue.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure contains some data structure.
|
||||
// Queue structure contains ArrayQueue, LinkedQueue, CircularQueue, and PriorityQueue.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure contains some data structure. Set is a data container, like slice, but element of set is not duplicate.
|
||||
package datastructure
|
||||
|
||||
// Set is a data container, like slice, but element of set is not duplicate
|
||||
// Set is a data container, like slice, but element of set is not duplicate.
|
||||
type Set[T comparable] map[T]struct{}
|
||||
|
||||
// NewSet return a instance of set
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure contains some data structure. Stack structure contains ArrayStack and LinkedStack.
|
||||
package datastructure
|
||||
|
||||
import "errors"
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure contains some data structure. Stack structure contains ArrayStack and LinkedStack.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package datastructure contains some data structure. BSTree is binary search tree.
|
||||
package datastructure
|
||||
|
||||
import (
|
||||
|
||||
@@ -35,7 +35,7 @@ func init() {
|
||||
timeFormat = map[string]string{
|
||||
"yyyy-mm-dd hh:mm:ss": "2006-01-02 15:04:05",
|
||||
"yyyy-mm-dd hh:mm": "2006-01-02 15:04",
|
||||
"yyyy-mm-dd hh": "2006-01-02 15:04",
|
||||
"yyyy-mm-dd hh": "2006-01-02 15",
|
||||
"yyyy-mm-dd": "2006-01-02",
|
||||
"yyyy-mm": "2006-01",
|
||||
"mm-dd": "01-02",
|
||||
@@ -72,6 +72,12 @@ func AddDay(t time.Time, day int64) time.Time {
|
||||
return t.Add(24 * time.Hour * time.Duration(day))
|
||||
}
|
||||
|
||||
// AddYear add or sub year to the time.
|
||||
// Play: https://go.dev/play/p/MqW2ujnBx10
|
||||
func AddYear(t time.Time, year int64) time.Time {
|
||||
return t.Add(365 * 24 * time.Hour * time.Duration(year))
|
||||
}
|
||||
|
||||
// GetNowDate return format yyyy-mm-dd of current date.
|
||||
// Play: https://go.dev/play/p/PvfkPpcpBBf
|
||||
func GetNowDate() string {
|
||||
@@ -218,3 +224,32 @@ func BeginOfYear(t time.Time) time.Time {
|
||||
func EndOfYear(t time.Time) time.Time {
|
||||
return BeginOfYear(t).AddDate(1, 0, 0).Add(-time.Nanosecond)
|
||||
}
|
||||
|
||||
// IsLeapYear check if param year is leap year or not.
|
||||
// Play: https://go.dev/play/p/xS1eS2ejGew
|
||||
func IsLeapYear(year int) bool {
|
||||
return year%4 == 0 && (year%100 != 0 || year%400 == 0)
|
||||
}
|
||||
|
||||
// BetweenSeconds returns the number of seconds between two times.
|
||||
// Play: https://go.dev/play/p/n3YDRyfyXJu
|
||||
func BetweenSeconds(t1 time.Time, t2 time.Time) int64 {
|
||||
index := t2.Unix() - t1.Unix()
|
||||
return index
|
||||
}
|
||||
|
||||
// DayOfYear returns which day of the year the parameter date `t` is.
|
||||
// Play: https://go.dev/play/p/0hjqhTwFNlH
|
||||
func DayOfYear(t time.Time) int {
|
||||
y, m, d := t.Date()
|
||||
firstDay := time.Date(y, 1, 1, 0, 0, 0, 0, t.Location())
|
||||
nowDate := time.Date(y, m, d, 0, 0, 0, 0, t.Location())
|
||||
|
||||
return int(nowDate.Sub(firstDay).Hours() / 24)
|
||||
}
|
||||
|
||||
// IsWeekend checks if passed time is weekend or not.
|
||||
// Play: https://go.dev/play/p/cupRM5aZOIY
|
||||
func IsWeekend(t time.Time) bool {
|
||||
return time.Saturday == t.Weekday() || time.Sunday == t.Weekday()
|
||||
}
|
||||
|
||||
@@ -57,6 +57,23 @@ func ExampleAddMinute() {
|
||||
// -2m0s
|
||||
}
|
||||
|
||||
func ExampleAddYear() {
|
||||
now := time.Now()
|
||||
|
||||
after1Year := AddYear(now, 1)
|
||||
diff1 := after1Year.Sub(now)
|
||||
|
||||
before1Year := AddYear(now, -1)
|
||||
diff2 := before1Year.Sub(now)
|
||||
|
||||
fmt.Println(diff1)
|
||||
fmt.Println(diff2)
|
||||
|
||||
// Output:
|
||||
// 8760h0m0s
|
||||
// -8760h0m0s
|
||||
}
|
||||
|
||||
func ExampleGetNowDate() {
|
||||
result := GetNowDate()
|
||||
|
||||
@@ -114,15 +131,18 @@ func ExampleFormatTimeToStr() {
|
||||
result1 := FormatTimeToStr(datetime, "yyyy-mm-dd hh:mm:ss")
|
||||
result2 := FormatTimeToStr(datetime, "yyyy-mm-dd")
|
||||
result3 := FormatTimeToStr(datetime, "dd-mm-yy hh:mm:ss")
|
||||
result4 := FormatTimeToStr(datetime, "yyyy-mm-dd hh")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// 2021-01-02 16:04:08
|
||||
// 2021-01-02
|
||||
// 02-01-21 16:04:08
|
||||
// 2021-01-02 16
|
||||
}
|
||||
|
||||
func ExampleFormatStrToTime() {
|
||||
@@ -321,3 +341,70 @@ func ExampleNewUnixNow() {
|
||||
// // Output:
|
||||
// // 2006-01-02T23:04:05+08:00
|
||||
// }
|
||||
|
||||
func ExampleIsLeapYear() {
|
||||
result1 := IsLeapYear(2000)
|
||||
result2 := IsLeapYear(2001)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
|
||||
func ExampleBetweenSeconds() {
|
||||
today := time.Now()
|
||||
tomorrow := AddDay(today, 1)
|
||||
yesterday := AddDay(today, -1)
|
||||
|
||||
result1 := BetweenSeconds(today, tomorrow)
|
||||
result2 := BetweenSeconds(today, yesterday)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 86400
|
||||
// -86400
|
||||
}
|
||||
|
||||
func ExampleDayOfYear() {
|
||||
date1 := time.Date(2023, 02, 01, 1, 1, 1, 0, time.Local)
|
||||
result1 := DayOfYear(date1)
|
||||
|
||||
date2 := time.Date(2023, 01, 02, 1, 1, 1, 0, time.Local)
|
||||
result2 := DayOfYear(date2)
|
||||
|
||||
date3 := time.Date(2023, 01, 01, 1, 1, 1, 0, time.Local)
|
||||
result3 := DayOfYear(date3)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 31
|
||||
// 1
|
||||
// 0
|
||||
}
|
||||
|
||||
func ExampleIsWeekend() {
|
||||
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 := IsWeekend(date1)
|
||||
result2 := IsWeekend(date2)
|
||||
result3 := IsWeekend(date3)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
}
|
||||
|
||||
@@ -7,6 +7,33 @@ import (
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestAddYear(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestAddDay")
|
||||
|
||||
now := time.Now()
|
||||
after2Years := AddYear(now, 1)
|
||||
diff1 := after2Years.Sub(now)
|
||||
assert.Equal(float64(8760), diff1.Hours())
|
||||
|
||||
before2Years := AddYear(now, -1)
|
||||
diff2 := before2Years.Sub(now)
|
||||
assert.Equal(float64(-8760), diff2.Hours())
|
||||
}
|
||||
|
||||
func TestBetweenSeconds(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestBetweenSeconds")
|
||||
|
||||
today := time.Now()
|
||||
tomorrow := AddDay(today, 1)
|
||||
yesterday := AddDay(today, -1)
|
||||
|
||||
result1 := BetweenSeconds(today, tomorrow)
|
||||
result2 := BetweenSeconds(today, yesterday)
|
||||
|
||||
assert.Equal(int64(86400), result1)
|
||||
assert.Equal(int64(-86400), result2)
|
||||
}
|
||||
|
||||
func TestAddDay(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestAddDay")
|
||||
|
||||
@@ -71,12 +98,16 @@ func TestFormatTimeToStr(t *testing.T) {
|
||||
cases := []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"}
|
||||
"hh:mm:ss", "yyyy/mm",
|
||||
"yyyy-mm-dd hh",
|
||||
}
|
||||
|
||||
expected := []string{
|
||||
"2021-01-02 16:04:08", "2021-01-02",
|
||||
"02-01-21 16:04:08", "2021/01/02 16:04:08",
|
||||
"16:04:08", "2021/01"}
|
||||
"16:04:08", "2021/01",
|
||||
"2021-01-02 16",
|
||||
}
|
||||
|
||||
for i := 0; i < len(cases); i++ {
|
||||
actual := FormatTimeToStr(datetime, cases[i])
|
||||
@@ -230,3 +261,44 @@ func TestEndOfYear(t *testing.T) {
|
||||
|
||||
assert.Equal(expected, actual)
|
||||
}
|
||||
|
||||
func TestIsLeapYear(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestEndOfYear")
|
||||
|
||||
result1 := IsLeapYear(2000)
|
||||
result2 := IsLeapYear(2001)
|
||||
|
||||
assert.Equal(true, result1)
|
||||
assert.Equal(false, result2)
|
||||
}
|
||||
|
||||
func TestDayOfYear(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestDayOfYear")
|
||||
date1 := time.Date(2023, 02, 01, 1, 1, 1, 0, time.Local)
|
||||
result1 := DayOfYear(date1)
|
||||
assert.Equal(31, result1)
|
||||
|
||||
date2 := time.Date(2023, 01, 02, 1, 1, 1, 0, time.Local)
|
||||
result2 := DayOfYear(date2)
|
||||
assert.Equal(1, result2)
|
||||
|
||||
date3 := time.Date(2023, 01, 01, 1, 1, 1, 0, time.Local)
|
||||
result3 := DayOfYear(date3)
|
||||
assert.Equal(0, result3)
|
||||
}
|
||||
|
||||
func TestIsWeekend(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIsWeekend")
|
||||
date := time.Date(2023, 06, 03, 0, 0, 0, 0, time.Local)
|
||||
result := IsWeekend(date)
|
||||
assert.Equal(true, result)
|
||||
|
||||
date1 := time.Date(2023, 06, 04, 0, 0, 0, 0, time.Local)
|
||||
result1 := IsWeekend(date1)
|
||||
assert.Equal(true, result1)
|
||||
|
||||
date2 := time.Date(2023, 06, 02, 0, 0, 0, 0, time.Local)
|
||||
result2 := IsWeekend(date2)
|
||||
assert.Equal(false, result2)
|
||||
|
||||
}
|
||||
|
||||
@@ -40,6 +40,9 @@ import (
|
||||
- [DecodeByte](#DecodeByte)
|
||||
- [DeepClone](#DeepClone)
|
||||
- [CopyProperties](#CopyProperties)
|
||||
- [ToInterface](#ToInterface)
|
||||
- [Utf8ToGbk](#Utf8ToGbk)
|
||||
- [GbkToUtf8](#GbkToUtf8)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -629,7 +632,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="DeepClone">DeepClone</span>
|
||||
|
||||
<p>Creates a deep copy of passed item, can't clone unexported field of struct.</p>
|
||||
@@ -694,7 +696,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="CopyProperties">CopyProperties</span>
|
||||
|
||||
<p>Copies each field from the source struct into the destination struct. Use json.Marshal/Unmarshal, so json tag should be set for fields of dst and src struct.</p>
|
||||
@@ -757,7 +758,11 @@ func main() {
|
||||
|
||||
indicatorVO := IndicatorVO{}
|
||||
|
||||
CopyProperties(&indicatorVO, indicator)
|
||||
err := convertor.CopyProperties(&indicatorVO, indicator)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(indicatorVO.Id)
|
||||
fmt.Println(indicatorVO.Ip)
|
||||
@@ -768,4 +773,106 @@ func main() {
|
||||
// 127.0.0.1
|
||||
// 3
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ToInterface">ToInterface</span>
|
||||
|
||||
<p>Converts reflect value to its interface type.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ToInterface(v reflect.Value) (value interface{}, ok bool)
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
val := reflect.ValueOf("abc")
|
||||
iVal, ok := convertor.ToInterface(val)
|
||||
|
||||
fmt.Printf("%T\n", iVal)
|
||||
fmt.Printf("%v\n", iVal)
|
||||
fmt.Println(ok)
|
||||
|
||||
// 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/v2/convertor"
|
||||
"github.com/duke-git/lancet/v2/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/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
gbkData, _ := convertor.Utf8ToGbk([]byte("hello"))
|
||||
utf8Data, _ := convertor.GbkToUtf8(gbkData)
|
||||
|
||||
fmt.Println(utf8.Valid(utf8Data))
|
||||
fmt.Println(string(utf8Data))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// hello
|
||||
}
|
||||
```
|
||||
@@ -40,7 +40,9 @@ import (
|
||||
- [DecodeByte](#DecodeByte)
|
||||
- [DeepClone](#DeepClone)
|
||||
- [CopyProperties](#CopyProperties)
|
||||
|
||||
- [ToInterface](#ToInterface)
|
||||
- [Utf8ToGbk](#Utf8ToGbk)
|
||||
- [GbkToUtf8](#GbkToUtf8)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -756,7 +758,11 @@ func main() {
|
||||
|
||||
indicatorVO := IndicatorVO{}
|
||||
|
||||
CopyProperties(&indicatorVO, indicator)
|
||||
err := convertor.CopyProperties(&indicatorVO, indicator)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(indicatorVO.Id)
|
||||
fmt.Println(indicatorVO.Ip)
|
||||
@@ -767,4 +773,106 @@ func main() {
|
||||
// 127.0.0.1
|
||||
// 3
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
### <span id="ToInterface">ToInterface</span>
|
||||
|
||||
<p>将反射值转换成对应的interface类型。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ToInterface(v reflect.Value) (value interface{}, ok bool)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
val := reflect.ValueOf("abc")
|
||||
iVal, ok := convertor.ToInterface(val)
|
||||
|
||||
fmt.Printf("%T\n", iVal)
|
||||
fmt.Printf("%v\n", iVal)
|
||||
fmt.Println(ok)
|
||||
|
||||
// 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/v2/convertor"
|
||||
"github.com/duke-git/lancet/v2/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/v2/convertor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
gbkData, _ := convertor.Utf8ToGbk([]byte("hello"))
|
||||
utf8Data, _ := convertor.GbkToUtf8(gbkData)
|
||||
|
||||
fmt.Println(utf8.Valid(utf8Data))
|
||||
fmt.Println(string(utf8Data))
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
248
docs/datetime.md
248
docs/datetime.md
@@ -26,6 +26,7 @@ import (
|
||||
- [AddDay](#AddDay)
|
||||
- [AddHour](#AddHour)
|
||||
- [AddMinute](#AddMinute)
|
||||
- [AddYear](#AddYear)
|
||||
- [BeginOfMinute](#BeginOfMinute)
|
||||
- [BeginOfHour](#BeginOfHour)
|
||||
- [BeginOfDay](#BeginOfDay)
|
||||
@@ -53,6 +54,10 @@ import (
|
||||
- [ToFormat](#ToFormat)
|
||||
- [ToFormatForTpl](#ToFormatForTpl)
|
||||
- [ToIso8601](#ToIso8601)
|
||||
- [IsLeapYear](#IsLeapYear)
|
||||
- [BetweenSeconds](#BetweenSeconds)
|
||||
- [DayOfYear](#DayOfYear)
|
||||
- [IsWeekend](#IsWeekend)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -198,6 +203,45 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="AddYear">AddYear</span>
|
||||
|
||||
<p>Add or sub year to the time.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func AddYear(t time.Time, year int64) time.Time
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
|
||||
after1Year := datetime.AddYear(now, 1)
|
||||
diff1 := after1Year.Sub(now)
|
||||
|
||||
before1Year := datetime.AddYear(now, -1)
|
||||
diff2 := before1Year.Sub(now)
|
||||
|
||||
fmt.Println(diff1)
|
||||
fmt.Println(diff2)
|
||||
|
||||
// Output:
|
||||
// 8760h0m0s
|
||||
// -8760h0m0s
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="BeginOfMinute">BeginOfMinute</span>
|
||||
|
||||
<p>Return beginning minute time of day.</p>
|
||||
@@ -607,8 +651,8 @@ func main() {
|
||||
now := time.Now()
|
||||
currentDate := datetime.GetNowDate()
|
||||
|
||||
fmt.Println(currentDate)
|
||||
|
||||
fmt.Println(currentDate)
|
||||
|
||||
// Output:
|
||||
// 2022-01-28
|
||||
}
|
||||
@@ -671,8 +715,8 @@ func main() {
|
||||
now := time.Now()
|
||||
current := datetime.GetNowDateTime()
|
||||
|
||||
fmt.Println(current)
|
||||
|
||||
fmt.Println(current)
|
||||
|
||||
// Output:
|
||||
// 2022-01-28 15:59:33
|
||||
}
|
||||
@@ -702,9 +746,9 @@ import (
|
||||
func main() {
|
||||
now := time.Now()
|
||||
zeroTime := datetime.GetZeroHourTimestamp()
|
||||
|
||||
fmt.Println(zeroTime)
|
||||
|
||||
|
||||
fmt.Println(zeroTime)
|
||||
|
||||
// Output:
|
||||
// 1643299200
|
||||
}
|
||||
@@ -735,8 +779,8 @@ func main() {
|
||||
now := time.Now()
|
||||
nightTime := datetime.GetNightTimestamp()
|
||||
|
||||
fmt.Println(nightTime)
|
||||
|
||||
fmt.Println(nightTime)
|
||||
|
||||
// Output:
|
||||
// 1643385599
|
||||
}
|
||||
@@ -842,8 +886,8 @@ import (
|
||||
|
||||
func main() {
|
||||
tm := datetime.NewUnixNow()
|
||||
fmt.Println(tm)
|
||||
|
||||
fmt.Println(tm)
|
||||
|
||||
// Output:
|
||||
// &{1647597438}
|
||||
}
|
||||
@@ -874,8 +918,8 @@ import (
|
||||
|
||||
func main() {
|
||||
tm := datetime.NewUnix(1647597438)
|
||||
fmt.Println(tm)
|
||||
|
||||
fmt.Println(tm)
|
||||
|
||||
// Output:
|
||||
// &{1647597438}
|
||||
}
|
||||
@@ -906,8 +950,8 @@ import (
|
||||
|
||||
func main() {
|
||||
tm, err := datetime.NewFormat("2022-03-18 17:04:05")
|
||||
fmt.Println(tm)
|
||||
|
||||
fmt.Println(tm)
|
||||
|
||||
// Output:
|
||||
// &{1647594245}
|
||||
}
|
||||
@@ -938,8 +982,8 @@ import (
|
||||
|
||||
func main() {
|
||||
tm, err := datetime.NewISO8601("2006-01-02T15:04:05.999Z")
|
||||
fmt.Println(tm)
|
||||
|
||||
fmt.Println(tm)
|
||||
|
||||
// Output:
|
||||
// &{1136214245}
|
||||
}
|
||||
@@ -967,8 +1011,8 @@ import (
|
||||
|
||||
func main() {
|
||||
tm := datetime.NewUnixNow()
|
||||
fmt.Println(tm.ToUnix())
|
||||
|
||||
fmt.Println(tm.ToUnix())
|
||||
|
||||
// Output:
|
||||
// 1647597438
|
||||
}
|
||||
@@ -996,8 +1040,8 @@ import (
|
||||
|
||||
func main() {
|
||||
tm, _ := datetime.NewFormat("2022-03-18 17:04:05")
|
||||
fmt.Println(tm.ToFormat())
|
||||
|
||||
fmt.Println(tm.ToFormat())
|
||||
|
||||
// Output:
|
||||
// 2022-03-18 17:04:05
|
||||
}
|
||||
@@ -1026,8 +1070,8 @@ import (
|
||||
func main() {
|
||||
tm, _ := datetime.NewFormat("2022-03-18 17:04:05")
|
||||
ts := tm.ToFormatForTpl("2006/01/02 15:04:05")
|
||||
fmt.Println(ts)
|
||||
|
||||
fmt.Println(ts)
|
||||
|
||||
// Output:
|
||||
// 2022/03/18 17:04:05
|
||||
}
|
||||
@@ -1056,9 +1100,163 @@ import (
|
||||
func main() {
|
||||
tm, _ := datetime.NewISO8601("2006-01-02T15:04:05.999Z")
|
||||
ts := tm.ToIso8601()
|
||||
fmt.Println(ts)
|
||||
|
||||
fmt.Println(ts)
|
||||
|
||||
// Output:
|
||||
// 2006-01-02T23:04:05+08:00
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="IsLeapYear">IsLeapYear</span>
|
||||
|
||||
<p>check if param `year` is leap year or not.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func IsLeapYear(year int) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := datetime.IsLeapYear(2000)
|
||||
result2 := datetime.IsLeapYear(2001)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="BetweenSeconds">BetweenSeconds</span>
|
||||
|
||||
<p>Return the number of seconds between two times.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func BetweenSeconds(t1 time.Time, t2 time.Time) int64
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
today := time.Now()
|
||||
tomorrow := datetime.AddDay(today, 1)
|
||||
yesterday := datetime.AddDay(today, -1)
|
||||
|
||||
result1 := datetime.BetweenSeconds(today, tomorrow)
|
||||
result2 := datetime.BetweenSeconds(today, yesterday)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 86400
|
||||
// -86400
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="DayOfYear">DayOfYear</span>
|
||||
|
||||
<p>Returns which day of the year the parameter date `t` is.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func DayOfYear(t time.Time) int
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
date1 := time.Date(2023, 02, 01, 1, 1, 1, 0, time.Local)
|
||||
result1 := datetime.DayOfYear(date1)
|
||||
|
||||
date2 := time.Date(2023, 01, 02, 1, 1, 1, 0, time.Local)
|
||||
result2 := datetime.DayOfYear(date2)
|
||||
|
||||
date3 := time.Date(2023, 01, 01, 1, 1, 1, 0, time.Local)
|
||||
result3 := datetime.DayOfYear(date3)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 31
|
||||
// 1
|
||||
// 0
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <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/v2/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
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
# Datetime
|
||||
datetime日期时间处理包,格式化日期,比较日期。
|
||||
|
||||
datetime 日期时间处理包,格式化日期,比较日期。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/datetime/datetime.go](https://github.com/duke-git/lancet/blob/main/datetime/datetime.go)
|
||||
- [https://github.com/duke-git/lancet/blob/main/datetime/datetime.go](https://github.com/duke-git/lancet/blob/main/datetime/datetime.go)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
@@ -19,74 +21,82 @@ import (
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录
|
||||
- [AddDay](#AddDay)
|
||||
- [AddHour](#AddHour)
|
||||
- [AddMinute](#AddMinute)
|
||||
- [BeginOfMinute](#BeginOfMinute)
|
||||
- [BeginOfHour](#BeginOfHour)
|
||||
- [BeginOfDay](#BeginOfDay)
|
||||
- [BeginOfWeek](#BeginOfWeek)
|
||||
- [BeginOfMonth](#BeginOfMonth)
|
||||
- [BeginOfYear](#BeginOfYear)
|
||||
- [EndOfMinute](#EndOfMinute)
|
||||
- [EndOfHour](#EndOfHour)
|
||||
- [EndOfDay](#EndOfDay)
|
||||
- [EndOfWeek](#EndOfWeek)
|
||||
- [EndOfMonth](#EndOfMonth)
|
||||
- [EndOfYear](#EndOfYear)
|
||||
- [GetNowDate](#GetNowDate)
|
||||
- [GetNowTime](#GetNowTime)
|
||||
- [GetNowDateTime](#GetNowDateTime)
|
||||
- [GetZeroHourTimestamp](#GetZeroHourTimestamp)
|
||||
- [GetNightTimestamp](#GetNightTimestamp)
|
||||
- [FormatTimeToStr](#FormatTimeToStr)
|
||||
- [FormatStrToTime](#FormatStrToTime)
|
||||
- [NewUnixNow](#NewUnixNow)
|
||||
- [NewUnix](#NewUnix)
|
||||
- [NewFormat](#NewFormat)
|
||||
- [NewISO8601](#NewISO8601)
|
||||
- [ToUnix](#ToUnix)
|
||||
- [ToFormat](#ToFormat)
|
||||
- [ToFormatForTpl](#ToFormatForTpl)
|
||||
- [ToIso8601](#ToIso8601)
|
||||
|
||||
- [AddDay](#AddDay)
|
||||
- [AddHour](#AddHour)
|
||||
- [AddMinute](#AddMinute)
|
||||
- [AddYear](#AddYear)
|
||||
- [BeginOfMinute](#BeginOfMinute)
|
||||
- [BeginOfHour](#BeginOfHour)
|
||||
- [BeginOfDay](#BeginOfDay)
|
||||
- [BeginOfWeek](#BeginOfWeek)
|
||||
- [BeginOfMonth](#BeginOfMonth)
|
||||
- [BeginOfYear](#BeginOfYear)
|
||||
- [EndOfMinute](#EndOfMinute)
|
||||
- [EndOfHour](#EndOfHour)
|
||||
- [EndOfDay](#EndOfDay)
|
||||
- [EndOfWeek](#EndOfWeek)
|
||||
- [EndOfMonth](#EndOfMonth)
|
||||
- [EndOfYear](#EndOfYear)
|
||||
- [GetNowDate](#GetNowDate)
|
||||
- [GetNowTime](#GetNowTime)
|
||||
- [GetNowDateTime](#GetNowDateTime)
|
||||
- [GetZeroHourTimestamp](#GetZeroHourTimestamp)
|
||||
- [GetNightTimestamp](#GetNightTimestamp)
|
||||
- [FormatTimeToStr](#FormatTimeToStr)
|
||||
- [FormatStrToTime](#FormatStrToTime)
|
||||
- [NewUnixNow](#NewUnixNow)
|
||||
- [NewUnix](#NewUnix)
|
||||
- [NewFormat](#NewFormat)
|
||||
- [NewISO8601](#NewISO8601)
|
||||
- [ToUnix](#ToUnix)
|
||||
- [ToFormat](#ToFormat)
|
||||
- [ToFormatForTpl](#ToFormatForTpl)
|
||||
- [ToIso8601](#ToIso8601)
|
||||
- [IsLeapYear](#IsLeapYear)
|
||||
- [BetweenSeconds](#BetweenSeconds)
|
||||
- [DayOfYear](#DayOfYear)
|
||||
- [IsWeekend](#IsWeekend)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 文档
|
||||
|
||||
## 注:
|
||||
1. 方法FormatTimeToStr和FormatStrToTime中的format参数值需要传以下类型之一:
|
||||
- yyyy-mm-dd hh:mm:ss
|
||||
- yyyy-mm-dd hh:mm
|
||||
- yyyy-mm-dd hh
|
||||
- yyyy-mm-dd
|
||||
- yyyy-mm
|
||||
- mm-dd
|
||||
- dd-mm-yy hh:mm:ss
|
||||
- yyyy/mm/dd hh:mm:ss
|
||||
- yyyy/mm/dd hh:mm
|
||||
- yyyy-mm-dd hh
|
||||
- yyyy/mm/dd
|
||||
- yyyy/mm
|
||||
- mm/dd
|
||||
- dd/mm/yy hh:mm:ss
|
||||
- yyyy
|
||||
- mm
|
||||
- hh:mm:ss
|
||||
- mm:ss
|
||||
|
||||
1. 方法 FormatTimeToStr 和 FormatStrToTime 中的 format 参数值需要传以下类型之一:
|
||||
|
||||
- yyyy-mm-dd hh:mm:ss
|
||||
- yyyy-mm-dd hh:mm
|
||||
- yyyy-mm-dd hh
|
||||
- yyyy-mm-dd
|
||||
- yyyy-mm
|
||||
- mm-dd
|
||||
- dd-mm-yy hh:mm:ss
|
||||
- yyyy/mm/dd hh:mm:ss
|
||||
- yyyy/mm/dd hh:mm
|
||||
- yyyy-mm-dd hh
|
||||
- yyyy/mm/dd
|
||||
- yyyy/mm
|
||||
- mm/dd
|
||||
- dd/mm/yy hh:mm:ss
|
||||
- yyyy
|
||||
- mm
|
||||
- hh:mm:ss
|
||||
- mm:ss
|
||||
|
||||
### <span id="AddDay">AddDay</span>
|
||||
|
||||
<p>将日期加/减天数。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func AddDay(t time.Time, day int64) time.Time
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -119,13 +129,13 @@ func main() {
|
||||
|
||||
<p>将日期加/减小时数。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func AddHour(t time.Time, hour int64) time.Time
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -158,13 +168,13 @@ func main() {
|
||||
|
||||
<p>将日期加/减分钟数。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func AddMinute(t time.Time, minute int64) time.Time
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -193,17 +203,56 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="AddYear">AddYear</span>
|
||||
|
||||
<p>将日期加/减年数。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func AddYear(t time.Time, year int64) time.Time
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
now := time.Now()
|
||||
|
||||
after1Year := datetime.AddYear(now, 1)
|
||||
diff1 := after1Year.Sub(now)
|
||||
|
||||
before1Year := datetime.AddYear(now, -1)
|
||||
diff2 := before1Year.Sub(now)
|
||||
|
||||
fmt.Println(diff1)
|
||||
fmt.Println(diff2)
|
||||
|
||||
// Output:
|
||||
// 8760h0m0s
|
||||
// -8760h0m0s
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="BeginOfMinute">BeginOfMinute</span>
|
||||
|
||||
<p>返回指定时间的分钟开始时间。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func BeginOfMinute(t time.Time) time.Time
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -229,13 +278,13 @@ func main() {
|
||||
|
||||
<p>返回指定时间的小时开始时间。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func BeginOfHour(t time.Time) time.Time
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -261,13 +310,13 @@ func main() {
|
||||
|
||||
<p>返回指定时间的当天开始时间。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func BeginOfDay(t time.Time) time.Time
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -293,13 +342,13 @@ func main() {
|
||||
|
||||
<p>返回指定时间的每周开始时间,默认开始时间星期日。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func BeginOfWeek(t time.Time, beginFrom ...time.Weekday) time.Time
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -325,13 +374,13 @@ func main() {
|
||||
|
||||
<p>返回指定时间的当月开始时间。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func BeginOfMonth(t time.Time) time.Time
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -357,13 +406,13 @@ func main() {
|
||||
|
||||
<p>返回指定时间的当年开始时间</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func BeginOfYear(t time.Time) time.Time
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -389,13 +438,13 @@ func main() {
|
||||
|
||||
<p>返回指定时间的分钟结束时间。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func EndOfMinute(t time.Time) time.Time
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -421,13 +470,13 @@ func main() {
|
||||
|
||||
<p>返回指定时间的小时结束时间。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func EndOfHour(t time.Time) time.Time
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -453,13 +502,13 @@ func main() {
|
||||
|
||||
<p>返回指定时间的当天结束时间。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func EndOfDay(t time.Time) time.Time
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -485,13 +534,13 @@ func main() {
|
||||
|
||||
<p>返回指定时间的星期结束时间,默认结束时间星期六。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func EndOfWeek(t time.Time, endWith ...time.Weekday) time.Time
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -517,13 +566,13 @@ func main() {
|
||||
|
||||
<p>返回指定时间的当月结束时间。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func EndOfMonth(t time.Time) time.Time
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -549,13 +598,13 @@ func main() {
|
||||
|
||||
<p>返回指定时间的当年结束时间。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func EndOfYear(t time.Time) time.Time
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -581,13 +630,13 @@ func main() {
|
||||
|
||||
<p>获取当天日期,返回格式:yyyy-mm-dd。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GetNowDate() string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -602,8 +651,8 @@ func main() {
|
||||
now := time.Now()
|
||||
currentDate := datetime.GetNowDate()
|
||||
|
||||
fmt.Println(currentDate)
|
||||
|
||||
fmt.Println(currentDate)
|
||||
|
||||
// Output:
|
||||
// 2022-01-28
|
||||
}
|
||||
@@ -613,13 +662,13 @@ func main() {
|
||||
|
||||
<p>获取当时时间,返回格式:hh:mm:ss</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GetNowTime() string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -645,13 +694,13 @@ func main() {
|
||||
|
||||
<p>获取当时日期和时间,返回格式:yyyy-mm-dd hh:mm:ss。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GetNowDateTime() string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -666,8 +715,8 @@ func main() {
|
||||
now := time.Now()
|
||||
current := datetime.GetNowDateTime()
|
||||
|
||||
fmt.Println(current)
|
||||
|
||||
fmt.Println(current)
|
||||
|
||||
// Output:
|
||||
// 2022-01-28 15:59:33
|
||||
}
|
||||
@@ -677,13 +726,13 @@ func main() {
|
||||
|
||||
<p>获取零点时间戳(timestamp of 00:00)</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GetZeroHourTimestamp() int64
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -697,9 +746,9 @@ import (
|
||||
func main() {
|
||||
now := time.Now()
|
||||
zeroTime := datetime.GetZeroHourTimestamp()
|
||||
|
||||
fmt.Println(zeroTime)
|
||||
|
||||
|
||||
fmt.Println(zeroTime)
|
||||
|
||||
// Output:
|
||||
// 1643299200
|
||||
}
|
||||
@@ -709,13 +758,13 @@ func main() {
|
||||
|
||||
<p>获取午夜时间戳(timestamp of 23:59)。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GetNightTimestamp() int64
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -730,8 +779,8 @@ func main() {
|
||||
now := time.Now()
|
||||
nightTime := datetime.GetNightTimestamp()
|
||||
|
||||
fmt.Println(nightTime)
|
||||
|
||||
fmt.Println(nightTime)
|
||||
|
||||
// Output:
|
||||
// 1643385599
|
||||
}
|
||||
@@ -741,13 +790,13 @@ func main() {
|
||||
|
||||
<p>将日期格式化成字符串,`format` 参数格式参考注1。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func FormatTimeToStr(t time.Time, format string) string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -780,13 +829,13 @@ func main() {
|
||||
|
||||
<p>将字符串格式化成时间,`format` 参数格式参考注1。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func FormatStrToTime(str, format string) (time.Time, error)
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -816,7 +865,7 @@ func main() {
|
||||
|
||||
<p>创建一个当前时间的unix时间戳。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
@@ -825,7 +874,7 @@ type theTime struct {
|
||||
func NewUnixNow() *theTime
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -837,8 +886,8 @@ import (
|
||||
|
||||
func main() {
|
||||
tm := datetime.NewUnixNow()
|
||||
fmt.Println(tm)
|
||||
|
||||
fmt.Println(tm)
|
||||
|
||||
// Output:
|
||||
// &{1647597438}
|
||||
}
|
||||
@@ -848,7 +897,7 @@ func main() {
|
||||
|
||||
<p>创建一个unix时间戳。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
@@ -857,7 +906,7 @@ type theTime struct {
|
||||
func NewUnix(unix int64) *theTime
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -869,8 +918,8 @@ import (
|
||||
|
||||
func main() {
|
||||
tm := datetime.NewUnix(1647597438)
|
||||
fmt.Println(tm)
|
||||
|
||||
fmt.Println(tm)
|
||||
|
||||
// Output:
|
||||
// &{1647597438}
|
||||
}
|
||||
@@ -880,7 +929,7 @@ func main() {
|
||||
|
||||
<p>创建一个yyyy-mm-dd hh:mm:ss格式时间字符串的unix时间戳。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
@@ -889,7 +938,7 @@ type theTime struct {
|
||||
func NewFormat(t string) (*theTime, error)
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -901,8 +950,8 @@ import (
|
||||
|
||||
func main() {
|
||||
tm, err := datetime.NewFormat("2022-03-18 17:04:05")
|
||||
fmt.Println(tm)
|
||||
|
||||
fmt.Println(tm)
|
||||
|
||||
// Output:
|
||||
// &{1647594245}
|
||||
}
|
||||
@@ -912,7 +961,7 @@ func main() {
|
||||
|
||||
<p>创建一个iso8601格式时间字符串的unix时间戳。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
type theTime struct {
|
||||
@@ -921,7 +970,7 @@ type theTime struct {
|
||||
func NewISO8601(iso8601 string) (*theTime, error)
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -933,8 +982,8 @@ import (
|
||||
|
||||
func main() {
|
||||
tm, err := datetime.NewISO8601("2006-01-02T15:04:05.999Z")
|
||||
fmt.Println(tm)
|
||||
|
||||
fmt.Println(tm)
|
||||
|
||||
// Output:
|
||||
// &{1136214245}
|
||||
}
|
||||
@@ -944,13 +993,13 @@ func main() {
|
||||
|
||||
<p>返回unix时间戳。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (t *theTime) ToUnix() int64
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -962,8 +1011,8 @@ import (
|
||||
|
||||
func main() {
|
||||
tm := datetime.NewUnixNow()
|
||||
fmt.Println(tm.ToUnix())
|
||||
|
||||
fmt.Println(tm.ToUnix())
|
||||
|
||||
// Output:
|
||||
// 1647597438
|
||||
}
|
||||
@@ -973,13 +1022,13 @@ func main() {
|
||||
|
||||
<p>返回格式'yyyy-mm-dd hh:mm:ss'的日期字符串。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (t *theTime) ToFormat() string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -991,8 +1040,8 @@ import (
|
||||
|
||||
func main() {
|
||||
tm, _ := datetime.NewFormat("2022-03-18 17:04:05")
|
||||
fmt.Println(tm.ToFormat())
|
||||
|
||||
fmt.Println(tm.ToFormat())
|
||||
|
||||
// Output:
|
||||
// 2022-03-18 17:04:05
|
||||
}
|
||||
@@ -1002,13 +1051,13 @@ func main() {
|
||||
|
||||
<p>返回tpl格式指定的日期字符串。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (t *theTime) ToFormatForTpl(tpl string) string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -1021,8 +1070,8 @@ import (
|
||||
func main() {
|
||||
tm, _ := datetime.NewFormat("2022-03-18 17:04:05")
|
||||
ts := tm.ToFormatForTpl("2006/01/02 15:04:05")
|
||||
fmt.Println(ts)
|
||||
|
||||
fmt.Println(ts)
|
||||
|
||||
// Output:
|
||||
// 2022/03/18 17:04:05
|
||||
}
|
||||
@@ -1032,13 +1081,13 @@ func main() {
|
||||
|
||||
<p>返回iso8601日期字符串。</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (t *theTime) ToIso8601() string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -1051,9 +1100,160 @@ import (
|
||||
func main() {
|
||||
tm, _ := datetime.NewISO8601("2006-01-02T15:04:05.999Z")
|
||||
ts := tm.ToIso8601()
|
||||
fmt.Println(ts)
|
||||
|
||||
fmt.Println(ts)
|
||||
|
||||
// Output:
|
||||
// 2006-01-02T23:04:05+08:00
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
### <span id="IsLeapYear">IsLeapYear</span>
|
||||
|
||||
<p>验证是否是闰年。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func IsLeapYear(year int) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := datetime.IsLeapYear(2000)
|
||||
result2 := datetime.IsLeapYear(2001)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="BetweenSeconds">BetweenSeconds</span>
|
||||
|
||||
<p>返回两个时间的间隔秒数。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func BetweenSeconds(t1 time.Time, t2 time.Time) int64
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
today := time.Now()
|
||||
tomorrow := datetime.AddDay(today, 1)
|
||||
yesterday := datetime.AddDay(today, -1)
|
||||
|
||||
result1 := datetime.BetweenSeconds(today, tomorrow)
|
||||
result2 := datetime.BetweenSeconds(today, yesterday)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 86400
|
||||
// -86400
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="DayOfYear">DayOfYear</span>
|
||||
|
||||
<p>返回参数日期是一年中的第几天。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func DayOfYear(t time.Time) int
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/datetime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
date1 := time.Date(2023, 02, 01, 1, 1, 1, 0, time.Local)
|
||||
result1 := datetime.DayOfYear(date1)
|
||||
|
||||
date2 := time.Date(2023, 01, 02, 1, 1, 1, 0, time.Local)
|
||||
result2 := datetime.DayOfYear(date2)
|
||||
|
||||
date3 := time.Date(2023, 01, 01, 1, 1, 1, 0, time.Local)
|
||||
result3 := datetime.DayOfYear(date3)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 31
|
||||
// 1
|
||||
// 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/v2/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
|
||||
}
|
||||
```
|
||||
|
||||
169
docs/fileutil.md
169
docs/fileutil.md
@@ -37,12 +37,16 @@ import (
|
||||
- [ReadFileToString](#ReadFileToString)
|
||||
- [ReadFileByLine](#ReadFileByLine)
|
||||
- [Zip](#Zip)
|
||||
- [ZipAppendEntry](#ZipAppendEntry)
|
||||
- [UnZip](#UnZip)
|
||||
- [IsZipFile](#IsZipFile)
|
||||
- [FileSize](#FileSize)
|
||||
- [MTime](#MTime)
|
||||
- [Sha](#Sha)
|
||||
- [ReadCsvFile](#ReadCsvFile)
|
||||
- [WriteCsvFile](#WriteCsvFile)
|
||||
- [WriteStringToFile](#WriteStringToFile)
|
||||
- [WriteBytesToFile](#WriteBytesToFile)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -473,6 +477,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/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.ZipAppendEntry("./test.txt", "./test.zip")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="UnZip">UnZip</span>
|
||||
|
||||
<p>Unzip the file and save it to dest path.</p>
|
||||
@@ -522,7 +554,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
isZip := IsZipFile("./zipfile.zip")
|
||||
isZip := fileutil.IsZipFile("./zipfile.zip")
|
||||
fmt.Println(isZip)
|
||||
}
|
||||
```
|
||||
@@ -660,3 +692,138 @@ func main() {
|
||||
// <nil>
|
||||
}
|
||||
```
|
||||
|
||||
### <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/v2/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>Writes bytes to target file.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func WriteBytesToFile(filepath string, content []byte) error
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
filepath := "./bytes.txt"
|
||||
|
||||
file, err := os.Create(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
err = fileutil.WriteBytesToFile(filepath, []byte("hello"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
content, err := fileutil.ReadFileToString(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
os.Remove(filepath)
|
||||
|
||||
fmt.Println(content)
|
||||
|
||||
// Output:
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="WriteStringToFile">WriteStringToFile</span>
|
||||
|
||||
<p>Writes string to target file.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func WriteStringToFile(filepath string, content string, append bool) error
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
filepath := "./test.txt"
|
||||
|
||||
file, err := os.Create(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
err = fileutil.WriteStringToFile(filepath, "hello", true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
content, err := fileutil.ReadFileToString(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
os.Remove(filepath)
|
||||
|
||||
fmt.Println(content)
|
||||
|
||||
// Output:
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
@@ -37,12 +37,16 @@ import (
|
||||
- [ReadFileToString](#ReadFileToString)
|
||||
- [ReadFileByLine](#ReadFileByLine)
|
||||
- [Zip](#Zip)
|
||||
- [ZipAppendEntry](#ZipAppendEntry)
|
||||
- [UnZip](#UnZip)
|
||||
- [IsZipFile](#IsZipFile)
|
||||
- [FileSize](#FileSize)
|
||||
- [MTime](#MTime)
|
||||
- [Sha](#Sha)
|
||||
- [ReadCsvFile](#ReadCsvFile)
|
||||
- [WriteCsvFile](#WriteCsvFile)
|
||||
- [WriteStringToFile](#WriteStringToFile)
|
||||
- [WriteBytesToFile](#WriteBytesToFile)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -473,6 +477,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/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := fileutil.ZipAppendEntry("./test.txt", "./test.zip")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="UnZip">UnZip</span>
|
||||
|
||||
<p>zip解压缩文件并保存在目录中</p>
|
||||
@@ -522,7 +554,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
isZip := IsZipFile("./zipfile.zip")
|
||||
isZip := fileutil.IsZipFile("./zipfile.zip")
|
||||
fmt.Println(isZip)
|
||||
}
|
||||
```
|
||||
@@ -660,3 +692,138 @@ func main() {
|
||||
// <nil>
|
||||
}
|
||||
```
|
||||
|
||||
### <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/v2/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>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func WriteBytesToFile(filepath string, content []byte) error
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
filepath := "./bytes.txt"
|
||||
|
||||
file, err := os.Create(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
err = fileutil.WriteBytesToFile(filepath, []byte("hello"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
content, err := fileutil.ReadFileToString(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
os.Remove(filepath)
|
||||
|
||||
fmt.Println(content)
|
||||
|
||||
// Output:
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="WriteStringToFile">WriteStringToFile</span>
|
||||
|
||||
<p>将字符串写入文件。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func WriteStringToFile(filepath string, content string, append bool) error
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/fileutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
filepath := "./test.txt"
|
||||
|
||||
file, err := os.Create(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
err = fileutil.WriteStringToFile(filepath, "hello", true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
content, err := fileutil.ReadFileToString(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
os.Remove(filepath)
|
||||
|
||||
fmt.Println(content)
|
||||
|
||||
// Output:
|
||||
// hello
|
||||
}
|
||||
```
|
||||
|
||||
272
docs/mathutil.md
272
docs/mathutil.md
@@ -40,6 +40,12 @@ import (
|
||||
- [RadianToAngle](#RadianToAngle)
|
||||
- [PointDistance](#PointDistance)
|
||||
- [IsPrime](#IsPrime)
|
||||
- [GCD](#GCD)
|
||||
- [LCM](#LCM)
|
||||
- [Cos](#Cos)
|
||||
- [Sin](#Sin)
|
||||
- [Log](#Log)
|
||||
- [Sum](#Sum)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -365,13 +371,16 @@ import (
|
||||
func main() {
|
||||
result1 := mathutil.Percent(1, 2, 2)
|
||||
result2 := mathutil.Percent(0.1, 0.3, 2)
|
||||
result3 := mathutil.Percent(-30305, 408420, 2)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 0.5
|
||||
// 0.33
|
||||
// 50
|
||||
// 33.33
|
||||
// -7.42
|
||||
}
|
||||
```
|
||||
|
||||
@@ -597,7 +606,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="RadianToAngle">RadianToAngle</span>
|
||||
|
||||
<p>Converts radian value to angle value.</p>
|
||||
@@ -664,7 +672,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="IsPrime">IsPrime</span>
|
||||
|
||||
<p>Checks if number is prime number.</p>
|
||||
@@ -687,19 +694,252 @@ 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
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="GCD">GCD</span>
|
||||
|
||||
<p>Return greatest common divisor (GCD) of integers.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func GCD[T constraints.Integer](integers ...T) T
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.GCD(1, 1)
|
||||
result2 := mathutil.GCD(1, -1)
|
||||
result3 := mathutil.GCD(-1, 1)
|
||||
result4 := mathutil.GCD(-1, -1)
|
||||
result5 := mathutil.GCD(3, 6, 9)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// 1
|
||||
// -1
|
||||
// -1
|
||||
// 3
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="LCM">LCM</span>
|
||||
|
||||
<p>Return Least Common Multiple (LCM) of integers.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func LCM[T constraints.Integer](integers ...T) T
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.LCM(1, 1)
|
||||
result2 := mathutil.LCM(1, 2)
|
||||
result3 := mathutil.LCM(3, 6, 9)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// 2
|
||||
// 18
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Cos">Cos</span>
|
||||
|
||||
<p>Returns the cosine of the radian argument.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Cos(radian float64, precision ...int) float64
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Cos(0)
|
||||
result2 := mathutil.Cos(90)
|
||||
result3 := mathutil.Cos(180)
|
||||
result4 := mathutil.Cos(math.Pi)
|
||||
result5 := mathutil.Cos(math.Pi / 2)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// -0.447
|
||||
// -0.598
|
||||
// -1
|
||||
// 0
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Sin">Sin</span>
|
||||
|
||||
<p>Returns the sine of the radian argument.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Sin(radian float64, precision ...int) float64
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Sin(0)
|
||||
result2 := mathutil.Sin(90)
|
||||
result3 := mathutil.Sin(180)
|
||||
result4 := mathutil.Sin(math.Pi)
|
||||
result5 := mathutil.Sin(math.Pi / 2)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
|
||||
// Output:
|
||||
// 0
|
||||
// 0.894
|
||||
// -0.801
|
||||
// 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/v2/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
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Sum">Sum</span>
|
||||
|
||||
<p>Returns sum of passed numbers.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Sum[T constraints.Integer | constraints.Float](numbers ...T) T
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Sum(1, 2)
|
||||
result2 := mathutil.Sum(0.1, float64(1))
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 3
|
||||
// 1.1
|
||||
}
|
||||
```
|
||||
@@ -40,6 +40,12 @@ import (
|
||||
- [RadianToAngle](#RadianToAngle)
|
||||
- [PointDistance](#PointDistance)
|
||||
- [IsPrime](#IsPrime)
|
||||
- [GCD](#GCD)
|
||||
- [LCM](#LCM)
|
||||
- [Cos](#Cos)
|
||||
- [Sin](#Sin)
|
||||
- [Log](#Log)
|
||||
- [Sum](#Sum)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -365,13 +371,16 @@ import (
|
||||
func main() {
|
||||
result1 := mathutil.Percent(1, 2, 2)
|
||||
result2 := mathutil.Percent(0.1, 0.3, 2)
|
||||
result3 := mathutil.Percent(-30305, 408420, 2)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 0.5
|
||||
// 0.33
|
||||
// 50
|
||||
// 33.33
|
||||
// -7.42
|
||||
}
|
||||
```
|
||||
|
||||
@@ -663,8 +672,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="IsPrime">IsPrime</span>
|
||||
|
||||
<p>判断质数。</p>
|
||||
@@ -687,18 +694,250 @@ 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
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="GCD">GCD</span>
|
||||
|
||||
<p>计算最大公约数。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func GCD[T constraints.Integer](integers ...T) T
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.GCD(1, 1)
|
||||
result2 := mathutil.GCD(1, -1)
|
||||
result3 := mathutil.GCD(-1, 1)
|
||||
result4 := mathutil.GCD(-1, -1)
|
||||
result5 := mathutil.GCD(3, 6, 9)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// 1
|
||||
// -1
|
||||
// -1
|
||||
// 3
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="LCM">LCM</span>
|
||||
|
||||
<p>计算最小公倍数。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func LCM[T constraints.Integer](integers ...T) T
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.LCM(1, 1)
|
||||
result2 := mathutil.LCM(1, 2)
|
||||
result3 := mathutil.LCM(3, 6, 9)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// 2
|
||||
// 18
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Cos">Cos</span>
|
||||
|
||||
<p>计算弧度的余弦值</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Cos(radian float64, precision ...int) float64
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Cos(0)
|
||||
result2 := mathutil.Cos(90)
|
||||
result3 := mathutil.Cos(180)
|
||||
result4 := mathutil.Cos(math.Pi)
|
||||
result5 := mathutil.Cos(math.Pi / 2)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// -0.447
|
||||
// -0.598
|
||||
// -1
|
||||
// 0
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Sin">Sin</span>
|
||||
|
||||
<p>计算弧度的正弦值</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Sin(radian float64, precision ...int) float64
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Sin(0)
|
||||
result2 := mathutil.Sin(90)
|
||||
result3 := mathutil.Sin(180)
|
||||
result4 := mathutil.Sin(math.Pi)
|
||||
result5 := mathutil.Sin(math.Pi / 2)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
|
||||
// Output:
|
||||
// 0
|
||||
// 0.894
|
||||
// -0.801
|
||||
// 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/v2/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
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Sum">Sum</span>
|
||||
|
||||
<p>求传入参数之和。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Sum[T constraints.Integer | constraints.Float](numbers ...T) T
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/mathutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := mathutil.Sum(1, 2)
|
||||
result2 := mathutil.Sum(0.1, float64(1))
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 3
|
||||
// 1.1
|
||||
}
|
||||
```
|
||||
|
||||
@@ -620,9 +620,9 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HttpGet">HttpGet (Deprecated: use SendRequest for replacement)</span>
|
||||
### <span id="HttpGet">HttpGet</span>
|
||||
|
||||
<p>Send http get request.</p>
|
||||
<p>Send http get request. (Deprecated: use SendRequest for replacement)</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
@@ -662,9 +662,9 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HttpPost">HttpPost (Deprecated: use SendRequest for replacement)</span>
|
||||
### <span id="HttpPost">HttpPost</span>
|
||||
|
||||
<p>Send http post request.</p>
|
||||
<p>Send http post request.(Deprecated: use SendRequest for replacement)</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
@@ -692,16 +692,14 @@ import (
|
||||
func main() {
|
||||
url := "https://jsonplaceholder.typicode.com/todos"
|
||||
header := map[string]string{
|
||||
"Content-Type": "application/json",
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
}
|
||||
type Todo struct {
|
||||
UserId int `json:"userId"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
todo := Todo{1, "TestAddToDo"}
|
||||
bodyParams, _ := json.Marshal(todo)
|
||||
|
||||
resp, err := netutil.HttpPost(url, header, nil, bodyParams)
|
||||
postData := url.Values{}
|
||||
postData.Add("userId", "1")
|
||||
postData.Add("title", "TestToDo")
|
||||
|
||||
resp, err := netutil.HttpPost(apiUrl, header, nil, postData)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@@ -711,9 +709,9 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HttpPut">HttpPut (Deprecated: use SendRequest for replacement)</span>
|
||||
### <span id="HttpPut">HttpPut</span>
|
||||
|
||||
<p>Send http put request.</p>
|
||||
<p>Send http put request. (Deprecated: use SendRequest for replacement)</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
@@ -761,9 +759,9 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HttpDelete">HttpDelete (Deprecated: use SendRequest for replacement)</span>
|
||||
### <span id="HttpDelete">HttpDelete</span>
|
||||
|
||||
<p>Send http delete request.</p>
|
||||
<p>Send http delete request. (Deprecated: use SendRequest for replacement)</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
@@ -800,9 +798,9 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HttpPatch">HttpPatch (Deprecated: use SendRequest for replacement)</span>
|
||||
### <span id="HttpPatch">HttpPatch</span>
|
||||
|
||||
<p>Send http patch request.</p>
|
||||
<p>Send http patch request. (Deprecated: use SendRequest for replacement)</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
@@ -922,7 +920,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := DownloadFile("./lancet_logo.jpg", "https://picx.zhimg.com/v2-fc82a4199749de9cfb71e32e54f489d3_720w.jpg?source=172ae18b")
|
||||
err := netutil.DownloadFile("./lancet_logo.jpg", "https://picx.zhimg.com/v2-fc82a4199749de9cfb71e32e54f489d3_720w.jpg?source=172ae18b")
|
||||
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
@@ -622,9 +622,9 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HttpGet">HttpGet (Deprecated: use SendRequest for replacement)</span>
|
||||
### <span id="HttpGet">HttpGet</span>
|
||||
|
||||
<p>发送http get请求</p>
|
||||
<p>发送http get请求。(已废弃:使用SendRequest)</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -664,9 +664,9 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HttpPost">HttpPost (Deprecated: use SendRequest for replacement)</span>
|
||||
### <span id="HttpPost">HttpPost</span>
|
||||
|
||||
<p>发送http post请求</p>
|
||||
<p>发送http post请求。(已废弃:使用SendRequest)</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -694,16 +694,14 @@ import (
|
||||
func main() {
|
||||
url := "https://jsonplaceholder.typicode.com/todos"
|
||||
header := map[string]string{
|
||||
"Content-Type": "application/json",
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
}
|
||||
type Todo struct {
|
||||
UserId int `json:"userId"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
todo := Todo{1, "TestAddToDo"}
|
||||
bodyParams, _ := json.Marshal(todo)
|
||||
|
||||
resp, err := netutil.HttpPost(url, header, nil, bodyParams)
|
||||
postData := url.Values{}
|
||||
postData.Add("userId", "1")
|
||||
postData.Add("title", "TestToDo")
|
||||
|
||||
resp, err := netutil.HttpPost(apiUrl, header, nil, postData)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@@ -713,9 +711,9 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HttpPut">HttpPut (Deprecated: use SendRequest for replacement)</span>
|
||||
### <span id="HttpPut">HttpPut</span>
|
||||
|
||||
<p>发送http put请求</p>
|
||||
<p>发送http put请求。(已废弃:使用SendRequest)</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -763,9 +761,9 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HttpDelete">HttpDelete (Deprecated: use SendRequest for replacement)</span>
|
||||
### <span id="HttpDelete">HttpDelete</span>
|
||||
|
||||
<p>发送http delete请求</p>
|
||||
<p>发送http delete请求。(已废弃:使用SendRequest)</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -802,9 +800,9 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HttpPatch">HttpPatch (Deprecated: use SendRequest for replacement)</span>
|
||||
### <span id="HttpPatch">HttpPatch</span>
|
||||
|
||||
<p>发送http patch请求</p>
|
||||
<p>发送http patch请求。(已废弃:使用SendRequest)</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
@@ -924,7 +922,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := DownloadFile("./lancet_logo.jpg", "https://picx.zhimg.com/v2-fc82a4199749de9cfb71e32e54f489d3_720w.jpg?source=172ae18b")
|
||||
err := netutil.DownloadFile("./lancet_logo.jpg", "https://picx.zhimg.com/v2-fc82a4199749de9cfb71e32e54f489d3_720w.jpg?source=172ae18b")
|
||||
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import (
|
||||
- [RandNumeral](#RandNumeral)
|
||||
- [RandNumeralOrLetter](#RandNumeralOrLetter)
|
||||
- [UUIdV4](#UUIdV4)
|
||||
- [RandUniqueIntSlice](#RandUniqueIntSlice)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -245,3 +246,30 @@ 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/v2/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/v2/random"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result := RandUniqueIntSlice(5, 0, 10)
|
||||
fmt.Println(result) //[0 4 7 1 5] (random)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -896,18 +896,18 @@ import (
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
|
||||
isEven := func(i, num int) bool {
|
||||
return num%2 == 0
|
||||
}
|
||||
isEven := func(i, num int) bool {
|
||||
return num%2 == 0
|
||||
}
|
||||
|
||||
result, ok := slice.FindBy(nums, isEven)
|
||||
result, ok := slice.FindBy(nums, isEven)
|
||||
|
||||
fmt.Println(result)
|
||||
fmt.Println(ok)
|
||||
fmt.Println(result)
|
||||
fmt.Println(ok)
|
||||
|
||||
// Output:
|
||||
// 2
|
||||
// true
|
||||
// Output:
|
||||
// 2
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
@@ -968,18 +968,18 @@ import (
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
|
||||
isEven := func(i, num int) bool {
|
||||
return num%2 == 0
|
||||
}
|
||||
isEven := func(i, num int) bool {
|
||||
return num%2 == 0
|
||||
}
|
||||
|
||||
result, ok := slice.FindLastBy(nums, isEven)
|
||||
result, ok := slice.FindLastBy(nums, isEven)
|
||||
|
||||
fmt.Println(result)
|
||||
fmt.Println(ok)
|
||||
fmt.Println(result)
|
||||
fmt.Println(ok)
|
||||
|
||||
// Output:
|
||||
// 4
|
||||
// true
|
||||
// Output:
|
||||
// 4
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -897,18 +897,18 @@ import (
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
|
||||
isEven := func(i, num int) bool {
|
||||
return num%2 == 0
|
||||
}
|
||||
isEven := func(i, num int) bool {
|
||||
return num%2 == 0
|
||||
}
|
||||
|
||||
result, ok := slice.FindBy(nums, isEven)
|
||||
result, ok := slice.FindBy(nums, isEven)
|
||||
|
||||
fmt.Println(result)
|
||||
fmt.Println(ok)
|
||||
fmt.Println(result)
|
||||
fmt.Println(ok)
|
||||
|
||||
// Output:
|
||||
// 2
|
||||
// true
|
||||
// Output:
|
||||
// 2
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
@@ -969,18 +969,18 @@ import (
|
||||
func main() {
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
|
||||
isEven := func(i, num int) bool {
|
||||
return num%2 == 0
|
||||
}
|
||||
isEven := func(i, num int) bool {
|
||||
return num%2 == 0
|
||||
}
|
||||
|
||||
result, ok := slice.FindLastBy(nums, isEven)
|
||||
result, ok := slice.FindLastBy(nums, isEven)
|
||||
|
||||
fmt.Println(result)
|
||||
fmt.Println(ok)
|
||||
fmt.Println(result)
|
||||
fmt.Println(ok)
|
||||
|
||||
// Output:
|
||||
// 4
|
||||
// true
|
||||
// Output:
|
||||
// 4
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ import (
|
||||
- [ForEach](#ForEach)
|
||||
- [Reduce](#Reduce)
|
||||
- [FindFirst](#FindFirst)
|
||||
- [FindLast](#FindLast)
|
||||
- [Max](#Max)
|
||||
- [Min](#Min)
|
||||
- [AllMatch](#AllMatch)
|
||||
@@ -667,6 +668,38 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="FindLast">FindLast</span>
|
||||
|
||||
<p>Returns the last element of this stream and true, or zero value and false if the stream is empty.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func (s stream[T]) FindLast() (T, bool)
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
original := stream.FromSlice([]int{3, 2, 1})
|
||||
|
||||
result, ok := original.FindLast()
|
||||
|
||||
fmt.Println(result)
|
||||
fmt.Println(ok)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Max">Max</span>
|
||||
|
||||
<p>Returns the maximum element of this stream according to the provided less function. less fuction: a > b</p>
|
||||
|
||||
@@ -40,6 +40,7 @@ import (
|
||||
- [ForEach](#ForEach)
|
||||
- [Reduce](#Reduce)
|
||||
- [FindFirst](#FindFirst)
|
||||
- [FindLast](#FindLast)
|
||||
- [Max](#Max)
|
||||
- [Min](#Min)
|
||||
- [AllMatch](#AllMatch)
|
||||
@@ -667,6 +668,38 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="FindLast">FindLast</span>
|
||||
|
||||
<p>返回此stream最后一个元素和true,如果stream为空,则返回零值和false。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func (s stream[T]) FindLast() (T, bool)
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/stream"
|
||||
)
|
||||
|
||||
func main() {
|
||||
original := stream.FromSlice([]int{3, 2, 1})
|
||||
|
||||
result, ok := original.FindLast()
|
||||
|
||||
fmt.Println(result)
|
||||
fmt.Println(ok)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Max">Max</span>
|
||||
|
||||
<p>根据提供的less函数返回stream的最大元素。less 函数: a > b</p>
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index:
|
||||
|
||||
- [Tag](#Tag)
|
||||
- [Name](#Name)
|
||||
- [Value](#Value)
|
||||
@@ -57,24 +58,24 @@ func (f *Field) Tag() *Tag
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Parent struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
p1 := &Parent{"111"}
|
||||
type Parent struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
p1 := &Parent{"111"}
|
||||
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
tag := n.Tag()
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
tag := n.Tag()
|
||||
|
||||
fmt.Println(tag.Name)
|
||||
|
||||
// Output:
|
||||
// name
|
||||
fmt.Println(tag.Name)
|
||||
|
||||
// Output:
|
||||
// name
|
||||
}
|
||||
```
|
||||
|
||||
@@ -94,23 +95,23 @@ func (f *Field) Value() any
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Parent struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
p1 := &Parent{"111"}
|
||||
type Parent struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
p1 := &Parent{"111"}
|
||||
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
|
||||
fmt.Println(n.Value())
|
||||
|
||||
// Output:
|
||||
// 111
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
|
||||
fmt.Println(n.Value())
|
||||
|
||||
// Output:
|
||||
// 111
|
||||
}
|
||||
```
|
||||
|
||||
@@ -130,32 +131,32 @@ func (f *Field) IsEmbedded() bool
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Parent struct {
|
||||
Name string
|
||||
}
|
||||
type Child struct {
|
||||
Parent
|
||||
Age int
|
||||
}
|
||||
c1 := &Child{}
|
||||
c1.Name = "111"
|
||||
c1.Age = 11
|
||||
type Parent struct {
|
||||
Name string
|
||||
}
|
||||
type Child struct {
|
||||
Parent
|
||||
Age int
|
||||
}
|
||||
c1 := &Child{}
|
||||
c1.Name = "111"
|
||||
c1.Age = 11
|
||||
|
||||
s := structs.New(c1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("Age")
|
||||
|
||||
fmt.Println(n.IsEmbedded())
|
||||
fmt.Println(a.IsEmbedded())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
s := structs.New(c1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("Age")
|
||||
|
||||
fmt.Println(n.IsEmbedded())
|
||||
fmt.Println(a.IsEmbedded())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
@@ -175,26 +176,26 @@ func (f *Field) IsExported() bool
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Parent struct {
|
||||
Name string
|
||||
age int
|
||||
}
|
||||
p1 := &Parent{Name: "11", age: 11}
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("age")
|
||||
|
||||
fmt.Println(n.IsExported())
|
||||
fmt.Println(a.IsExported())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
type Parent struct {
|
||||
Name string
|
||||
age int
|
||||
}
|
||||
p1 := &Parent{Name: "11", age: 11}
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("age")
|
||||
|
||||
fmt.Println(n.IsExported())
|
||||
fmt.Println(a.IsExported())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
@@ -214,26 +215,26 @@ func (f *Field) IsZero() bool
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Parent struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
p1 := &Parent{Age: 11}
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("Age")
|
||||
|
||||
fmt.Println(n.IsZero())
|
||||
fmt.Println(a.IsZero())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
type Parent struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
p1 := &Parent{Age: 11}
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("Age")
|
||||
|
||||
fmt.Println(n.IsZero())
|
||||
fmt.Println(a.IsZero())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
@@ -253,26 +254,26 @@ func (f *Field) Name() string
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Parent struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
p1 := &Parent{Age: 11}
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("Age")
|
||||
|
||||
fmt.Println(n.Name())
|
||||
fmt.Println(a.Name())
|
||||
|
||||
// Output:
|
||||
// Name
|
||||
// Age
|
||||
type Parent struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
p1 := &Parent{Age: 11}
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("Age")
|
||||
|
||||
fmt.Println(n.Name())
|
||||
fmt.Println(a.Name())
|
||||
|
||||
// Output:
|
||||
// Name
|
||||
// Age
|
||||
}
|
||||
```
|
||||
|
||||
@@ -292,26 +293,26 @@ func (f *Field) Kind() reflect.Kind
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Parent struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
p1 := &Parent{Age: 11}
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("Age")
|
||||
|
||||
fmt.Println(n.Kind())
|
||||
fmt.Println(a.Kind())
|
||||
|
||||
// Output:
|
||||
// string
|
||||
// int
|
||||
type Parent struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
p1 := &Parent{Age: 11}
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("Age")
|
||||
|
||||
fmt.Println(n.Kind())
|
||||
fmt.Println(a.Kind())
|
||||
|
||||
// Output:
|
||||
// string
|
||||
// int
|
||||
}
|
||||
```
|
||||
|
||||
@@ -331,23 +332,23 @@ func (f *Field) IsSlice() bool
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Parent struct {
|
||||
Name string
|
||||
arr []int
|
||||
}
|
||||
type Parent struct {
|
||||
Name string
|
||||
arr []int
|
||||
}
|
||||
|
||||
p1 := &Parent{arr: []int{1, 2, 3}}
|
||||
s := structs.New(p1)
|
||||
a, _ := s.Field("arr")
|
||||
|
||||
fmt.Println(a.IsSlice())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
p1 := &Parent{arr: []int{1, 2, 3}}
|
||||
s := structs.New(p1)
|
||||
a, _ := s.Field("arr")
|
||||
|
||||
fmt.Println(a.IsSlice())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
@@ -57,24 +57,24 @@ func (f *Field) Tag() *Tag
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Parent struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
p1 := &Parent{"111"}
|
||||
type Parent struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
p1 := &Parent{"111"}
|
||||
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
tag := n.Tag()
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
tag := n.Tag()
|
||||
|
||||
fmt.Println(tag.Name)
|
||||
|
||||
// Output:
|
||||
// name
|
||||
fmt.Println(tag.Name)
|
||||
|
||||
// Output:
|
||||
// name
|
||||
}
|
||||
```
|
||||
|
||||
@@ -94,23 +94,23 @@ func (f *Field) Value() any
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Parent struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
p1 := &Parent{"111"}
|
||||
type Parent struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
p1 := &Parent{"111"}
|
||||
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
|
||||
fmt.Println(n.Value())
|
||||
|
||||
// Output:
|
||||
// 111
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
|
||||
fmt.Println(n.Value())
|
||||
|
||||
// Output:
|
||||
// 111
|
||||
}
|
||||
```
|
||||
|
||||
@@ -130,32 +130,32 @@ func (f *Field) IsEmbedded() bool
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Parent struct {
|
||||
Name string
|
||||
}
|
||||
type Child struct {
|
||||
Parent
|
||||
Age int
|
||||
}
|
||||
c1 := &Child{}
|
||||
c1.Name = "111"
|
||||
c1.Age = 11
|
||||
type Parent struct {
|
||||
Name string
|
||||
}
|
||||
type Child struct {
|
||||
Parent
|
||||
Age int
|
||||
}
|
||||
c1 := &Child{}
|
||||
c1.Name = "111"
|
||||
c1.Age = 11
|
||||
|
||||
s := structs.New(c1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("Age")
|
||||
|
||||
fmt.Println(n.IsEmbedded())
|
||||
fmt.Println(a.IsEmbedded())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
s := structs.New(c1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("Age")
|
||||
|
||||
fmt.Println(n.IsEmbedded())
|
||||
fmt.Println(a.IsEmbedded())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
@@ -175,26 +175,26 @@ func (f *Field) IsExported() bool
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Parent struct {
|
||||
Name string
|
||||
age int
|
||||
}
|
||||
p1 := &Parent{Name: "11", age: 11}
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("age")
|
||||
|
||||
fmt.Println(n.IsExported())
|
||||
fmt.Println(a.IsExported())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
type Parent struct {
|
||||
Name string
|
||||
age int
|
||||
}
|
||||
p1 := &Parent{Name: "11", age: 11}
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("age")
|
||||
|
||||
fmt.Println(n.IsExported())
|
||||
fmt.Println(a.IsExported())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
@@ -214,26 +214,26 @@ func (f *Field) IsZero() bool
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Parent struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
p1 := &Parent{Age: 11}
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("Age")
|
||||
|
||||
fmt.Println(n.IsZero())
|
||||
fmt.Println(a.IsZero())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
type Parent struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
p1 := &Parent{Age: 11}
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("Age")
|
||||
|
||||
fmt.Println(n.IsZero())
|
||||
fmt.Println(a.IsZero())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
@@ -253,26 +253,26 @@ func (f *Field) Name() string
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Parent struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
p1 := &Parent{Age: 11}
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("Age")
|
||||
|
||||
fmt.Println(n.Name())
|
||||
fmt.Println(a.Name())
|
||||
|
||||
// Output:
|
||||
// Name
|
||||
// Age
|
||||
type Parent struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
p1 := &Parent{Age: 11}
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("Age")
|
||||
|
||||
fmt.Println(n.Name())
|
||||
fmt.Println(a.Name())
|
||||
|
||||
// Output:
|
||||
// Name
|
||||
// Age
|
||||
}
|
||||
```
|
||||
|
||||
@@ -292,26 +292,26 @@ func (f *Field) Kind() reflect.Kind
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Parent struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
p1 := &Parent{Age: 11}
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("Age")
|
||||
|
||||
fmt.Println(n.Kind())
|
||||
fmt.Println(a.Kind())
|
||||
|
||||
// Output:
|
||||
// string
|
||||
// int
|
||||
type Parent struct {
|
||||
Name string
|
||||
Age int
|
||||
}
|
||||
p1 := &Parent{Age: 11}
|
||||
s := structs.New(p1)
|
||||
n, _ := s.Field("Name")
|
||||
a, _ := s.Field("Age")
|
||||
|
||||
fmt.Println(n.Kind())
|
||||
fmt.Println(a.Kind())
|
||||
|
||||
// Output:
|
||||
// string
|
||||
// int
|
||||
}
|
||||
```
|
||||
|
||||
@@ -331,23 +331,23 @@ func (f *Field) IsSlice() bool
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Parent struct {
|
||||
Name string
|
||||
arr []int
|
||||
}
|
||||
type Parent struct {
|
||||
Name string
|
||||
arr []int
|
||||
}
|
||||
|
||||
p1 := &Parent{arr: []int{1, 2, 3}}
|
||||
s := structs.New(p1)
|
||||
a, _ := s.Field("arr")
|
||||
|
||||
fmt.Println(a.IsSlice())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
p1 := &Parent{arr: []int{1, 2, 3}}
|
||||
s := structs.New(p1)
|
||||
a, _ := s.Field("arr")
|
||||
|
||||
fmt.Println(a.IsSlice())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
}
|
||||
```
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index:
|
||||
|
||||
- [New](#New)
|
||||
- [ToMap](#ToMap)
|
||||
- [Fields](#Fields)
|
||||
@@ -47,16 +48,16 @@ func New(value any, tagName ...string) *Struct
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
p1 := &People{Name: "11"}
|
||||
s := structs.New(p1)
|
||||
// to do something
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
p1 := &People{Name: "11"}
|
||||
s := structs.New(p1)
|
||||
// to do something
|
||||
}
|
||||
```
|
||||
|
||||
@@ -82,29 +83,29 @@ func ToMap(v any) (map[string]any, error)
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
p1 := &People{Name: "11"}
|
||||
// use constructor function
|
||||
s1 := structs.New(p1)
|
||||
m1, _ := s1.ToMap()
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
p1 := &People{Name: "11"}
|
||||
// use constructor function
|
||||
s1 := structs.New(p1)
|
||||
m1, _ := s1.ToMap()
|
||||
|
||||
fmt.Println(m1)
|
||||
|
||||
// use static function
|
||||
m2, _ := structs.ToMap(p1)
|
||||
|
||||
fmt.Println(m2)
|
||||
|
||||
// Output:
|
||||
// map[name:11]
|
||||
// map[name:11]
|
||||
fmt.Println(m1)
|
||||
|
||||
// use static function
|
||||
m2, _ := structs.ToMap(p1)
|
||||
|
||||
fmt.Println(m2)
|
||||
|
||||
// Output:
|
||||
// map[name:11]
|
||||
// map[name:11]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -124,22 +125,22 @@ func (s *Struct) Fields() []*Field
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
p1 := &People{Name: "11"}
|
||||
s := structs.New(p1)
|
||||
fields := s.Fields()
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
p1 := &People{Name: "11"}
|
||||
s := structs.New(p1)
|
||||
fields := s.Fields()
|
||||
|
||||
fmt.Println(len(fields))
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
fmt.Println(len(fields))
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
}
|
||||
```
|
||||
|
||||
@@ -159,22 +160,22 @@ func (s *Struct) Field(name string) *Field
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
p1 := &People{Name: "11"}
|
||||
s := structs.New(p1)
|
||||
f := s.Field("Name")
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
p1 := &People{Name: "11"}
|
||||
s := structs.New(p1)
|
||||
f := s.Field("Name")
|
||||
|
||||
fmt.Println(f.Value())
|
||||
|
||||
// Output:
|
||||
// 11
|
||||
fmt.Println(f.Value())
|
||||
|
||||
// Output:
|
||||
// 11
|
||||
}
|
||||
```
|
||||
|
||||
@@ -194,20 +195,20 @@ func (s *Struct) IsStruct() bool
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
p1 := &People{Name: "11"}
|
||||
s := structs.New(p1)
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
p1 := &People{Name: "11"}
|
||||
s := structs.New(p1)
|
||||
|
||||
fmt.Println(s.IsStruct())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
fmt.Println(s.IsStruct())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录:
|
||||
|
||||
- [New](#New)
|
||||
- [ToMap](#ToMap)
|
||||
- [Fields](#Fields)
|
||||
@@ -47,16 +48,16 @@ func New(value any, tagName ...string) *Struct
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
p1 := &People{Name: "11"}
|
||||
s := structs.New(p1)
|
||||
// to do something
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
p1 := &People{Name: "11"}
|
||||
s := structs.New(p1)
|
||||
// to do something
|
||||
}
|
||||
```
|
||||
|
||||
@@ -70,7 +71,7 @@ func main() {
|
||||
func (s *Struct) ToMap() (map[string]any, error)
|
||||
```
|
||||
|
||||
<b>除此之外,提供一个便捷的静态方法ToMap</b>
|
||||
<b>除此之外,提供一个便捷的静态方法 ToMap</b>
|
||||
|
||||
```go
|
||||
func ToMap(v any) (map[string]any, error)
|
||||
@@ -82,28 +83,28 @@ func ToMap(v any) (map[string]any, error)
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
p1 := &People{Name: "11"}
|
||||
s1 := structs.New(p1)
|
||||
m1, _ := s1.ToMap()
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
p1 := &People{Name: "11"}
|
||||
s1 := structs.New(p1)
|
||||
m1, _ := s1.ToMap()
|
||||
|
||||
fmt.Println(m1)
|
||||
|
||||
// 如果不需要Struct更多的方法,可以直接使用ToMap
|
||||
m2, _ := structs.ToMap(p1)
|
||||
|
||||
fmt.Println(m2)
|
||||
|
||||
// Output:
|
||||
// map[name:11]
|
||||
// map[name:11]
|
||||
fmt.Println(m1)
|
||||
|
||||
// 如果不需要Struct更多的方法,可以直接使用ToMap
|
||||
m2, _ := structs.ToMap(p1)
|
||||
|
||||
fmt.Println(m2)
|
||||
|
||||
// Output:
|
||||
// map[name:11]
|
||||
// map[name:11]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -123,22 +124,22 @@ func (s *Struct) Fields() []*Field
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
p1 := &People{Name: "11"}
|
||||
s := structs.New(p1)
|
||||
fields := s.Fields()
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
p1 := &People{Name: "11"}
|
||||
s := structs.New(p1)
|
||||
fields := s.Fields()
|
||||
|
||||
fmt.Println(len(fields))
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
fmt.Println(len(fields))
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
}
|
||||
```
|
||||
|
||||
@@ -158,22 +159,22 @@ func (s *Struct) Field(name string) *Field
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
p1 := &People{Name: "11"}
|
||||
s := structs.New(p1)
|
||||
f := s.Field("Name")
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
p1 := &People{Name: "11"}
|
||||
s := structs.New(p1)
|
||||
f := s.Field("Name")
|
||||
|
||||
fmt.Println(f.Value())
|
||||
|
||||
// Output:
|
||||
// 11
|
||||
fmt.Println(f.Value())
|
||||
|
||||
// Output:
|
||||
// 11
|
||||
}
|
||||
```
|
||||
|
||||
@@ -193,20 +194,20 @@ func (s *Struct) IsStruct() bool
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/structs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
p1 := &People{Name: "11"}
|
||||
s := structs.New(p1)
|
||||
type People struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
p1 := &People{Name: "11"}
|
||||
s := structs.New(p1)
|
||||
|
||||
fmt.Println(s.IsStruct())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
fmt.Println(s.IsStruct())
|
||||
|
||||
// Output:
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
354
docs/strutil.md
354
docs/strutil.md
@@ -52,6 +52,13 @@ import (
|
||||
- [HasPrefixAny](#HasPrefixAny)
|
||||
- [HasSuffixAny](#HasSuffixAny)
|
||||
- [IndexOffset](#IndexOffset)
|
||||
- [ReplaceWithMap](#ReplaceWithMap)
|
||||
- [Trim](#Trim)
|
||||
- [SplitAndTrim](#SplitAndTrim)
|
||||
- [HideString](#HideString)
|
||||
- [ContainsAll](#ContainsAll)
|
||||
- [ContainsAny](#ContainsAny)
|
||||
- [RemoveWhiteSpace](#RemoveWhiteSpace)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -968,6 +975,7 @@ func main() {
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// hello world
|
||||
// 你好😄
|
||||
@@ -994,13 +1002,14 @@ 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
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1024,11 +1033,12 @@ 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
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1052,16 +1062,17 @@ 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
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1072,7 +1083,7 @@ func main() {
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func HasPrefixAny(str string, prefixes []string) bool
|
||||
func ReplaceWithMap(str string, replaces map[string]string) string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
@@ -1085,13 +1096,14 @@ 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
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1115,13 +1127,14 @@ 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
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1146,22 +1159,267 @@ 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
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ReplaceWithMap">ReplaceWithMap</span>
|
||||
|
||||
<p>Returns a copy of `str`, which is replaced by a map in unordered way, case-sensitively.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ReplaceWithMap(str string, replaces map[string]string) string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "ac ab ab ac"
|
||||
replaces := map[string]string{
|
||||
"a": "1",
|
||||
"b": "2",
|
||||
}
|
||||
|
||||
result := strutil.ReplaceWithMap(str, replaces)
|
||||
|
||||
fmt.Println(result)
|
||||
// Output:
|
||||
// 1c 12 12 1c
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Trim">Trim</span>
|
||||
|
||||
<p>Strips whitespace (or other characters) from the beginning and end of a string. The optional parameter `characterMask` specifies the additional stripped characters.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Trim(str string, characterMask ...string) string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := strutil.Trim("\nabcd")
|
||||
|
||||
str := "$ ab cd $ "
|
||||
|
||||
result2 := strutil.Trim(str)
|
||||
result3 := strutil.Trim(str, "$")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// abcd
|
||||
// $ ab cd $
|
||||
// ab cd
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="SplitAndTrim">SplitAndTrim</span>
|
||||
|
||||
<p>Splits string `str` by a string `delimiter` to a slice, and calls Trim to every element of slice. It ignores the elements which are empty after Trim.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func SplitAndTrim(str, delimiter string, characterMask ...string) []string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := " a,b, c,d,$1 "
|
||||
|
||||
result1 := strutil.SplitAndTrim(str, ",")
|
||||
result2 := strutil.SplitAndTrim(str, ",", "$")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// [a b c d $1]
|
||||
// [a b c d 1]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HideString">HideString</span>
|
||||
|
||||
<p>Hide some chars in source string with param `replaceChar`. replace range is origin[start : end]. [start, end).</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func HideString(origin string, start, end int, replaceChar string) string
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
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, "*")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// 13242658976
|
||||
// 132*2658976
|
||||
// 132****8976
|
||||
// 1324265****
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ContainsAll">ContainsAll</span>
|
||||
|
||||
<p>Return true if target string contains all the substrings.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ContainsAll(str string, substrs []string) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "hello world"
|
||||
|
||||
result1 := strutil.ContainsAll(str, []string{"hello", "world"})
|
||||
result2 := strutil.ContainsAll(str, []string{"hello", "abc"})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ContainsAny">ContainsAny</span>
|
||||
|
||||
<p>Return true if target string contains any one of the substrings.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ContainsAny(str string, substrs []string) bool
|
||||
```
|
||||
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "hello world"
|
||||
|
||||
result1 := strutil.ContainsAny(str, []string{"hello", "world"})
|
||||
result2 := strutil.ContainsAny(str, []string{"hello", "abc"})
|
||||
result3 := strutil.ContainsAny(str, []string{"123", "abc"})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// 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/v2/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
|
||||
}
|
||||
```
|
||||
|
||||
@@ -52,6 +52,13 @@ import (
|
||||
- [HasPrefixAny](#HasPrefixAny)
|
||||
- [HasSuffixAny](#HasSuffixAny)
|
||||
- [IndexOffset](#IndexOffset)
|
||||
- [ReplaceWithMap](#ReplaceWithMap)
|
||||
- [Trim](#Trim)
|
||||
- [SplitAndTrim](#SplitAndTrim)
|
||||
- [HideString](#HideString)
|
||||
- [ContainsAll](#ContainsAll)
|
||||
- [ContainsAny](#ContainsAny)
|
||||
- [RemoveWhiteSpace](#RemoveWhiteSpace)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
@@ -968,6 +975,7 @@ func main() {
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// hello world
|
||||
// 你好😄
|
||||
@@ -994,13 +1002,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
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1024,11 +1032,12 @@ 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
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1052,16 +1061,17 @@ 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
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1085,13 +1095,14 @@ 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
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1115,13 +1126,14 @@ 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
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1146,22 +1158,267 @@ 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
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ReplaceWithMap">ReplaceWithMap</span>
|
||||
|
||||
<p>返回`str`的副本,以无序的方式被map替换,区分大小写。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ReplaceWithMap(str string, replaces map[string]string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "ac ab ab ac"
|
||||
replaces := map[string]string{
|
||||
"a": "1",
|
||||
"b": "2",
|
||||
}
|
||||
|
||||
result := strutil.ReplaceWithMap(str, replaces)
|
||||
|
||||
fmt.Println(result)
|
||||
// Output:
|
||||
// 1c 12 12 1c
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="Trim">Trim</span>
|
||||
|
||||
<p>从字符串的开头和结尾去除空格(或其他字符)。 可选参数 characterMask 指定额外的剥离字符。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Trim(str string, characterMask ...string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
result1 := strutil.Trim("\nabcd")
|
||||
|
||||
str := "$ ab cd $ "
|
||||
|
||||
result2 := strutil.Trim(str)
|
||||
result3 := strutil.Trim(str, "$")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// abcd
|
||||
// $ ab cd $
|
||||
// ab cd
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="SplitAndTrim">SplitAndTrim</span>
|
||||
|
||||
<p>将字符串str按字符串delimiter拆分为一个切片,并对该数组的每个元素调用Trim。忽略Trim后为空的元素。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func SplitAndTrim(str, delimiter string, characterMask ...string) []string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := " a,b, c,d,$1 "
|
||||
|
||||
result1 := strutil.SplitAndTrim(str, ",")
|
||||
result2 := strutil.SplitAndTrim(str, ",", "$")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// [a b c d $1]
|
||||
// [a b c d 1]
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="HideString">HideString</span>
|
||||
|
||||
<p>使用参数`replaceChar`隐藏源字符串中的一些字符。替换范围是 origin[start : end]。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func HideString(origin string, start, end int, replaceChar string) string
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
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, "*")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// 13242658976
|
||||
// 132*2658976
|
||||
// 132****8976
|
||||
// 1324265****
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ContainsAll">ContainsAll</span>
|
||||
|
||||
<p>判断字符串是否包括全部给定的子字符串切片。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ContainsAll(str string, substrs []string) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "hello world"
|
||||
|
||||
result1 := strutil.ContainsAll(str, []string{"hello", "world"})
|
||||
result2 := strutil.ContainsAll(str, []string{"hello", "abc"})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
```
|
||||
|
||||
### <span id="ContainsAny">ContainsAny</span>
|
||||
|
||||
<p>判断字符串是否包括给定的子字符串切片中任意一个子字符串。</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ContainsAny(str string, substrs []string) bool
|
||||
```
|
||||
|
||||
<b>示例:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/strutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := "hello world"
|
||||
|
||||
result1 := strutil.ContainsAny(str, []string{"hello", "world"})
|
||||
result2 := strutil.ContainsAny(str, []string{"hello", "abc"})
|
||||
result3 := strutil.ContainsAny(str, []string{"123", "abc"})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// 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/v2/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
|
||||
}
|
||||
```
|
||||
|
||||
152
fileutil/file.go
152
fileutil/file.go
@@ -180,7 +180,7 @@ func ListFileNames(path string) ([]string, error) {
|
||||
}
|
||||
|
||||
// IsZipFile checks if file is zip or not.
|
||||
// Play: todo
|
||||
// Play: https://go.dev/play/p/9M0g2j_uF_e
|
||||
func IsZipFile(filepath string) bool {
|
||||
f, err := os.Open(filepath)
|
||||
if err != nil {
|
||||
@@ -208,7 +208,11 @@ func Zip(fpath string, destPath string) error {
|
||||
archive := zip.NewWriter(zipFile)
|
||||
defer archive.Close()
|
||||
|
||||
err = filepath.Walk(fpath, func(path string, info os.FileInfo, err error) error {
|
||||
return addFileToArchive(fpath, archive)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
@@ -224,32 +228,22 @@ func Zip(fpath string, destPath string) error {
|
||||
header.Name += "/"
|
||||
} else {
|
||||
header.Method = zip.Deflate
|
||||
}
|
||||
|
||||
writer, err := archive.CreateHeader(header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !info.IsDir() {
|
||||
writer, err := archive.CreateHeader(header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
_, err = io.Copy(writer, file)
|
||||
if err != nil {
|
||||
if _, err := io.Copy(writer, file); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
// UnZip unzip the file and save it to destPath.
|
||||
@@ -302,6 +296,64 @@ 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 safeFilepathJoin(path1, path2 string) (string, error) {
|
||||
relPath, err := filepath.Rel(".", path2)
|
||||
if err != nil || strings.HasPrefix(relPath, "..") {
|
||||
@@ -383,7 +435,7 @@ func CurrentPath() string {
|
||||
}
|
||||
|
||||
// FileSize returns file size in bytes.
|
||||
// Play: todo
|
||||
// Play: https://go.dev/play/p/H9Z05uD-Jjc
|
||||
func FileSize(path string) (int64, error) {
|
||||
f, err := os.Stat(path)
|
||||
if err != nil {
|
||||
@@ -393,7 +445,7 @@ func FileSize(path string) (int64, error) {
|
||||
}
|
||||
|
||||
// MTime returns file modified time.
|
||||
// Play: todo
|
||||
// Play: https://go.dev/play/p/s_Tl7lZoAaY
|
||||
func MTime(filepath string) (int64, error) {
|
||||
f, err := os.Stat(filepath)
|
||||
if err != nil {
|
||||
@@ -402,8 +454,8 @@ func MTime(filepath string) (int64, error) {
|
||||
return f.ModTime().Unix(), nil
|
||||
}
|
||||
|
||||
// MTime returns file sha value, param `shaType` should be 1, 256 or 512.
|
||||
// Play: todo
|
||||
// Sha returns file sha value, param `shaType` should be 1, 256 or 512.
|
||||
// Play: https://go.dev/play/p/VfEEcO2MJYf
|
||||
func Sha(filepath string, shaType ...int) (string, error) {
|
||||
file, err := os.Open(filepath)
|
||||
if err != nil {
|
||||
@@ -437,7 +489,7 @@ func Sha(filepath string, shaType ...int) (string, error) {
|
||||
}
|
||||
|
||||
// ReadCsvFile read file content into slice.
|
||||
// Play: todo
|
||||
// Play: https://go.dev/play/p/OExTkhGEd3_u
|
||||
func ReadCsvFile(filepath string) ([][]string, error) {
|
||||
f, err := os.Open(filepath)
|
||||
if err != nil {
|
||||
@@ -453,3 +505,57 @@ func ReadCsvFile(filepath string) ([][]string, error) {
|
||||
|
||||
return records, nil
|
||||
}
|
||||
|
||||
// WriteCsvFile write content to target csv file.
|
||||
// Play: todo
|
||||
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.
|
||||
// Play: https://go.dev/play/p/GhLS6d8lH_g
|
||||
func WriteStringToFile(filepath string, content 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()
|
||||
|
||||
_, err = f.WriteString(content)
|
||||
return err
|
||||
}
|
||||
|
||||
// WriteBytesToFile write bytes to target file.
|
||||
// Play: https://go.dev/play/p/s7QlDxMj3P8
|
||||
func WriteBytesToFile(filepath string, content []byte) error {
|
||||
f, err := os.OpenFile(filepath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
|
||||
_, err = f.Write(content)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -175,11 +175,11 @@ func ExampleReadFileByLine() {
|
||||
}
|
||||
|
||||
func ExampleListFileNames() {
|
||||
fileList, _ := ListFileNames("./")
|
||||
fileList, _ := ListFileNames("../internal")
|
||||
fmt.Println(fileList)
|
||||
|
||||
// Output:
|
||||
// [file.go file_example_test.go file_test.go]
|
||||
// [assert.go assert_test.go error_join.go]
|
||||
}
|
||||
|
||||
func ExampleZip() {
|
||||
@@ -224,6 +224,28 @@ func ExampleUnZip() {
|
||||
// application/octet-stream
|
||||
}
|
||||
|
||||
func ExampleZipAppendEntry() {
|
||||
zipFile := "./test.zip"
|
||||
CopyFile("./testdata/file.go.zip", zipFile)
|
||||
|
||||
ZipAppendEntry("./testdata", zipFile)
|
||||
|
||||
unZipPath := "./unzip"
|
||||
UnZip(zipFile, unZipPath)
|
||||
|
||||
fmt.Println(IsExist("./unzip/file.go"))
|
||||
fmt.Println(IsExist("./unzip/testdata/file.go.zip"))
|
||||
fmt.Println(IsExist("./unzip/testdata/test.txt"))
|
||||
|
||||
os.Remove(zipFile)
|
||||
os.RemoveAll(unZipPath)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
}
|
||||
|
||||
func ExampleIsZipFile() {
|
||||
result1 := IsZipFile("./file.go")
|
||||
result2 := IsZipFile("./testdata/file.go.zip")
|
||||
@@ -276,7 +298,7 @@ func ExampleSha() {
|
||||
}
|
||||
|
||||
func ExampleReadCsvFile() {
|
||||
content, err := ReadCsvFile("./testdata/test.csv")
|
||||
content, err := ReadCsvFile("./testdata/demo.csv")
|
||||
|
||||
fmt.Println(content)
|
||||
fmt.Println(err)
|
||||
@@ -285,3 +307,75 @@ func ExampleReadCsvFile() {
|
||||
// [[Bob 12 male] [Duke 14 male] [Lucy 16 female]]
|
||||
// <nil>
|
||||
}
|
||||
|
||||
func ExampleWriteCsvFile() {
|
||||
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]]
|
||||
}
|
||||
|
||||
func ExampleWriteStringToFile() {
|
||||
filepath := "./test.txt"
|
||||
|
||||
file, err := os.Create(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
err = WriteStringToFile(filepath, "hello", true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
content, err := ReadFileToString(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
os.Remove(filepath)
|
||||
|
||||
fmt.Println(content)
|
||||
|
||||
// Output:
|
||||
// hello
|
||||
}
|
||||
|
||||
func ExampleWriteBytesToFile() {
|
||||
filepath := "./bytes.txt"
|
||||
|
||||
file, err := os.Create(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
err = WriteBytesToFile(filepath, []byte("hello"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
content, err := ReadFileToString(filepath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
os.Remove(filepath)
|
||||
|
||||
fmt.Println(content)
|
||||
|
||||
// Output:
|
||||
// hello
|
||||
}
|
||||
|
||||
@@ -191,6 +191,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")
|
||||
|
||||
@@ -235,10 +273,10 @@ func TestMiMeType(t *testing.T) {
|
||||
func TestListFileNames(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestListFileNames")
|
||||
|
||||
filesInPath, err := ListFileNames("./")
|
||||
filesInPath, err := ListFileNames("../internal")
|
||||
assert.IsNil(err)
|
||||
|
||||
expected := []string{"file.go", "file_example_test.go", "file_test.go"}
|
||||
expected := []string{"assert.go", "assert_test.go", "error_join.go"}
|
||||
assert.Equal(expected, filesInPath)
|
||||
}
|
||||
|
||||
@@ -288,7 +326,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")
|
||||
|
||||
assert.IsNil(err)
|
||||
|
||||
@@ -296,3 +334,91 @@ func TestReadCsvFile(t *testing.T) {
|
||||
assert.Equal(3, len(content[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])
|
||||
|
||||
// RemoveFile(csvFilePath)
|
||||
}
|
||||
|
||||
func TestWriteStringToFile(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestWriteStringToFile")
|
||||
|
||||
filepath := "./test.txt"
|
||||
|
||||
file, err := os.Create(filepath)
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
err = WriteStringToFile(filepath, "hello", false)
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
content1, err := ReadFileToString(filepath)
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
err = WriteStringToFile(filepath, " world", true)
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
content2, err := os.ReadFile(filepath)
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
assert.Equal("hello", content1)
|
||||
assert.Equal("hello world", string(content2))
|
||||
|
||||
os.Remove(filepath)
|
||||
}
|
||||
|
||||
func TestWriteBytesToFile(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestWriteBytesToFile")
|
||||
|
||||
filepath := "./bytes.txt"
|
||||
|
||||
file, err := os.Create(filepath)
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
err = WriteBytesToFile(filepath, []byte("hello"))
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
content, err := os.ReadFile(filepath)
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
assert.Equal("hello", string(content))
|
||||
|
||||
os.Remove(filepath)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
Bob, 12, male
|
||||
Duke, 14, male
|
||||
Lucy, 16, female
|
||||
Lucy, 16, female
|
||||
|
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
|
||||
|
2
fileutil/testdata/test2.csv
vendored
Normal file
2
fileutil/testdata/test2.csv
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
Lili,22,female
|
||||
Jim,21,male
|
||||
|
@@ -55,12 +55,12 @@ func Factorial(x uint) uint {
|
||||
}
|
||||
|
||||
// Percent calculate the percentage of value to total.
|
||||
// Play: https://go.dev/play/p/QQM9B13coSP
|
||||
// Play: https://go.dev/play/p/s0NdFCtwuyd
|
||||
func Percent(val, total float64, n int) float64 {
|
||||
if total == 0 {
|
||||
return float64(0)
|
||||
}
|
||||
tmp := val / total
|
||||
tmp := val / total * 100
|
||||
result := RoundToFloat(tmp, n)
|
||||
|
||||
return result
|
||||
@@ -172,6 +172,18 @@ func MinBy[T any](slice []T, comparator func(T, T) bool) T {
|
||||
return min
|
||||
}
|
||||
|
||||
// Sum return sum of passed numbers.
|
||||
// Play: todo
|
||||
func Sum[T constraints.Integer | constraints.Float](numbers ...T) T {
|
||||
var sum T
|
||||
|
||||
for _, v := range numbers {
|
||||
sum += v
|
||||
}
|
||||
|
||||
return sum
|
||||
}
|
||||
|
||||
// Average return average value of numbers.
|
||||
// Play: https://go.dev/play/p/Vv7LBwER-pz
|
||||
func Average[T constraints.Integer | constraints.Float](numbers ...T) T {
|
||||
@@ -256,3 +268,76 @@ func IsPrime(n int) bool {
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// GCD return greatest common divisor (GCD) of integers.
|
||||
// Play: https://go.dev/play/p/CiEceLSoAKB
|
||||
func GCD[T constraints.Integer](integers ...T) T {
|
||||
result := integers[0]
|
||||
|
||||
for k := range integers {
|
||||
result = gcd(integers[k], result)
|
||||
|
||||
if result == 1 {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// find greatest common divisor (GCD)
|
||||
func gcd[T constraints.Integer](a, b T) T {
|
||||
if b == 0 {
|
||||
return a
|
||||
}
|
||||
|
||||
return gcd(b, a%b)
|
||||
}
|
||||
|
||||
// LCM return Least Common Multiple (LCM) of integers.
|
||||
// Play: https://go.dev/play/p/EjcZxfY7G_g
|
||||
func LCM[T constraints.Integer](integers ...T) T {
|
||||
result := integers[0]
|
||||
|
||||
for k := range integers {
|
||||
result = lcm(integers[k], result)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// find Least Common Multiple (LCM) via GCD.
|
||||
func lcm[T constraints.Integer](a, b T) T {
|
||||
if a == 0 || b == 0 {
|
||||
panic("lcm function: provide non zero integers only.")
|
||||
}
|
||||
return a * b / gcd(a, b)
|
||||
}
|
||||
|
||||
// Cos returns the cosine of the radian argument.
|
||||
// Play: https://go.dev/play/p/Sm89LoIfvFq
|
||||
func Cos(radian float64, precision ...int) float64 {
|
||||
t := 1.0 / (2.0 * math.Pi)
|
||||
radian *= t
|
||||
radian -= 0.25 + math.Floor(radian+0.25)
|
||||
radian *= 16.0 * (math.Abs(radian) - 0.5)
|
||||
radian += 0.225 * radian * (math.Abs(radian) - 1.0)
|
||||
|
||||
if len(precision) == 1 {
|
||||
return TruncRound(radian, precision[0])
|
||||
}
|
||||
|
||||
return TruncRound(radian, 3)
|
||||
}
|
||||
|
||||
// Cos returns the sine of the radian argument.
|
||||
// Play: https://go.dev/play/p/TWMQlMywDsP
|
||||
func Sin(radian float64, precision ...int) float64 {
|
||||
return Cos((math.Pi / 2) - radian)
|
||||
}
|
||||
|
||||
// Log returns the logarithm of base n.
|
||||
// Play: todo
|
||||
func Log(n, base float64) float64 {
|
||||
return math.Log(n) / math.Log(base)
|
||||
}
|
||||
|
||||
@@ -53,13 +53,16 @@ func ExampleFactorial() {
|
||||
func ExamplePercent() {
|
||||
result1 := Percent(1, 2, 2)
|
||||
result2 := Percent(0.1, 0.3, 2)
|
||||
result3 := Percent(-30305, 408420, 2)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 0.5
|
||||
// 0.33
|
||||
// 50
|
||||
// 33.33
|
||||
// -7.42
|
||||
}
|
||||
|
||||
func ExampleRoundToFloat() {
|
||||
@@ -119,6 +122,18 @@ func ExampleAverage() {
|
||||
// 1.3
|
||||
}
|
||||
|
||||
func ExampleSum() {
|
||||
result1 := Sum(1, 2)
|
||||
result2 := Sum(0.1, float64(1))
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 3
|
||||
// 1.1
|
||||
}
|
||||
|
||||
func ExampleMax() {
|
||||
result1 := Max(1, 2, 3)
|
||||
result2 := Max(1.2, 1.4, 1.1, 1.4)
|
||||
@@ -281,3 +296,96 @@ func ExampleIsPrime() {
|
||||
// false
|
||||
// true
|
||||
}
|
||||
|
||||
func ExampleGCD() {
|
||||
result1 := GCD(1, 1)
|
||||
result2 := GCD(1, -1)
|
||||
result3 := GCD(-1, 1)
|
||||
result4 := GCD(-1, -1)
|
||||
result5 := GCD(3, 6, 9)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// 1
|
||||
// -1
|
||||
// -1
|
||||
// 3
|
||||
}
|
||||
|
||||
func ExampleLCM() {
|
||||
result1 := LCM(1, 1)
|
||||
result2 := LCM(1, 2)
|
||||
result3 := LCM(3, 6, 9)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// 2
|
||||
// 18
|
||||
}
|
||||
|
||||
func ExampleCos() {
|
||||
result1 := Cos(0)
|
||||
result2 := Cos(90)
|
||||
result3 := Cos(180)
|
||||
result4 := Cos(math.Pi)
|
||||
result5 := Cos(math.Pi / 2)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// -0.447
|
||||
// -0.598
|
||||
// -1
|
||||
// 0
|
||||
}
|
||||
|
||||
func ExampleSin() {
|
||||
result1 := Sin(0)
|
||||
result2 := Sin(90)
|
||||
result3 := Sin(180)
|
||||
result4 := Sin(math.Pi)
|
||||
result5 := Sin(math.Pi / 2)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
|
||||
// Output:
|
||||
// 0
|
||||
// 0.894
|
||||
// -0.801
|
||||
// 0
|
||||
// 1
|
||||
}
|
||||
|
||||
func ExampleLog() {
|
||||
result1 := Log(8, 2)
|
||||
result2 := TruncRound(Log(5, 2), 2)
|
||||
result3 := TruncRound(Log(27, 3), 0)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// 3
|
||||
// 2.32
|
||||
// 3
|
||||
}
|
||||
|
||||
@@ -36,60 +36,69 @@ func TestFactorial(t *testing.T) {
|
||||
func TestPercent(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestPercent")
|
||||
|
||||
assert.Equal(0.5, Percent(1, 2, 2))
|
||||
assert.Equal(0.33, Percent(0.1, 0.3, 2))
|
||||
assert.EqualValues(50, Percent(1, 2, 2))
|
||||
assert.EqualValues(33.33, Percent(0.1, 0.3, 2))
|
||||
assert.EqualValues(-7.42, Percent(-30305, 408420, 2))
|
||||
}
|
||||
|
||||
func TestRoundToFloat(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestRoundToFloat")
|
||||
|
||||
assert.Equal(RoundToFloat(0, 0), float64(0))
|
||||
assert.Equal(RoundToFloat(0, 1), float64(0))
|
||||
assert.Equal(RoundToFloat(0.124, 2), float64(0.12))
|
||||
assert.Equal(RoundToFloat(0.125, 2), float64(0.13))
|
||||
assert.Equal(RoundToFloat(0.125, 3), float64(0.125))
|
||||
assert.Equal(RoundToFloat(33.33333, 2), float64(33.33))
|
||||
assert.Equal(float64(0), RoundToFloat(0, 0))
|
||||
assert.Equal(float64(0), RoundToFloat(0, 1))
|
||||
assert.Equal(0.12, RoundToFloat(0.124, 2))
|
||||
assert.Equal(0.13, RoundToFloat(0.125, 2))
|
||||
assert.Equal(0.125, RoundToFloat(0.125, 3))
|
||||
assert.Equal(33.33, RoundToFloat(33.33333, 2))
|
||||
}
|
||||
|
||||
func TestRoundToString(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestRoundToString")
|
||||
|
||||
assert.Equal(RoundToString(0, 0), "0")
|
||||
assert.Equal(RoundToString(0, 1), "0.0")
|
||||
assert.Equal(RoundToString(0.124, 2), "0.12")
|
||||
assert.Equal(RoundToString(0.125, 2), "0.13")
|
||||
assert.Equal(RoundToString(0.125, 3), "0.125")
|
||||
assert.Equal("0", RoundToString(0, 0))
|
||||
assert.Equal("0.0", RoundToString(0, 1))
|
||||
assert.Equal("0.12", RoundToString(0.124, 2))
|
||||
assert.Equal("0.13", RoundToString(0.125, 2))
|
||||
assert.Equal("0.125", RoundToString(0.125, 3))
|
||||
}
|
||||
|
||||
func TestTruncRound(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestTruncRound")
|
||||
|
||||
assert.Equal(TruncRound(0, 0), float64(0))
|
||||
assert.Equal(TruncRound(0, 1), float64(0))
|
||||
assert.Equal(TruncRound(0.124, 2), float64(0.12))
|
||||
assert.Equal(TruncRound(0.125, 2), float64(0.12))
|
||||
assert.Equal(TruncRound(0.125, 3), float64(0.125))
|
||||
assert.Equal(TruncRound(33.33333, 2), float64(33.33))
|
||||
assert.Equal(float64(0), TruncRound(0, 0))
|
||||
assert.Equal(float64(0), TruncRound(0, 1))
|
||||
assert.Equal(0.12, TruncRound(0.124, 2))
|
||||
assert.Equal(0.12, TruncRound(0.125, 2))
|
||||
assert.Equal(0.125, TruncRound(0.125, 3))
|
||||
assert.Equal(33.33, TruncRound(33.33333, 2))
|
||||
}
|
||||
|
||||
func TestAverage(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestAverage")
|
||||
|
||||
assert.Equal(Average(0, 0), 0)
|
||||
assert.Equal(Average(1, 1), 1)
|
||||
assert.Equal(0, Average(0, 0))
|
||||
assert.Equal(1, Average(1, 1))
|
||||
|
||||
avg := Average(1.2, 1.4)
|
||||
assert.Equal(1.3, RoundToFloat(avg, 1))
|
||||
}
|
||||
|
||||
func TestSum(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSum")
|
||||
|
||||
assert.Equal(1, Sum(0, 1))
|
||||
assert.Equal(1.1, Sum(0.1, float64(1)))
|
||||
}
|
||||
|
||||
func TestMax(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestMax")
|
||||
|
||||
assert.Equal(Max(0, 0), 0)
|
||||
assert.Equal(Max(1, 2, 3), 3)
|
||||
assert.Equal(Max(1.2, 1.4, 1.1, 1.4), 1.4)
|
||||
assert.Equal(0, Max(0, 0))
|
||||
assert.Equal(3, Max(1, 2, 3))
|
||||
assert.Equal(1.4, Max(1.2, 1.4, 1.1, 1.4))
|
||||
|
||||
type Integer int
|
||||
assert.Equal(Max(Integer(1), Integer(0)), Integer(1))
|
||||
assert.Equal(Integer(1), Max(Integer(1), Integer(0)))
|
||||
}
|
||||
|
||||
func TestMaxBy(t *testing.T) {
|
||||
@@ -114,9 +123,9 @@ func TestMaxBy(t *testing.T) {
|
||||
func TestMin(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestMin")
|
||||
|
||||
assert.Equal(Min(0, 0), 0)
|
||||
assert.Equal(Min(1, 2, 3), 1)
|
||||
assert.Equal(Min(1.2, 1.4, 1.1, 1.4), 1.1)
|
||||
assert.Equal(0, Min(0, 0))
|
||||
assert.Equal(1, Min(1, 2, 3))
|
||||
assert.Equal(1.1, Min(1.2, 1.4, 1.1, 1.4))
|
||||
}
|
||||
|
||||
func TestMinBy(t *testing.T) {
|
||||
@@ -210,3 +219,69 @@ func TestIsPrime(t *testing.T) {
|
||||
assert.Equal(true, IsPrime(3))
|
||||
assert.Equal(false, IsPrime(4))
|
||||
}
|
||||
|
||||
func TestGCD(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestGCD")
|
||||
|
||||
assert.Equal(1, GCD(1, 1))
|
||||
assert.Equal(1, GCD(1, -1))
|
||||
assert.Equal(-1, GCD(-1, 1))
|
||||
assert.Equal(-1, GCD(-1, -1))
|
||||
|
||||
assert.Equal(1, GCD(1, 0))
|
||||
assert.Equal(1, GCD(0, 1))
|
||||
assert.Equal(-1, GCD(-1, 0))
|
||||
assert.Equal(-1, GCD(0, -1))
|
||||
|
||||
assert.Equal(1, GCD(1, -2))
|
||||
assert.Equal(1, GCD(-2, 1))
|
||||
assert.Equal(-1, GCD(-1, 2))
|
||||
assert.Equal(-1, GCD(2, -1))
|
||||
|
||||
assert.Equal(-1, GCD(-1, -2))
|
||||
assert.Equal(-1, GCD(-2, -1))
|
||||
|
||||
assert.Equal(-9, GCD(-27, -36))
|
||||
assert.Equal(3, GCD(3, 6, 9))
|
||||
}
|
||||
|
||||
func TestLCM(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestLCM")
|
||||
|
||||
assert.Equal(1, LCM(1))
|
||||
assert.Equal(-1, LCM(-1))
|
||||
assert.Equal(-1, LCM(1, -1))
|
||||
assert.Equal(1, LCM(-1, 1))
|
||||
assert.Equal(1, LCM(1, 1))
|
||||
assert.Equal(-1, LCM(-1, -1))
|
||||
assert.Equal(2, LCM(1, 2))
|
||||
assert.Equal(18, LCM(3, 6, 9))
|
||||
}
|
||||
|
||||
func TestCos(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestCos")
|
||||
|
||||
assert.EqualValues(1, Cos(0))
|
||||
assert.EqualValues(-0.447, Cos(90))
|
||||
assert.EqualValues(-0.598, Cos(180))
|
||||
assert.EqualValues(-1, Cos(math.Pi))
|
||||
assert.EqualValues(0, Cos(math.Pi/2))
|
||||
}
|
||||
|
||||
func TestSin(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSin")
|
||||
|
||||
assert.EqualValues(0, Sin(0))
|
||||
assert.EqualValues(0.894, Sin(90))
|
||||
assert.EqualValues(-0.801, Sin(180))
|
||||
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))
|
||||
}
|
||||
|
||||
@@ -19,8 +19,10 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -94,6 +96,7 @@ type HttpRequest struct {
|
||||
Headers http.Header
|
||||
QueryParams url.Values
|
||||
FormData url.Values
|
||||
File *File
|
||||
Body []byte
|
||||
}
|
||||
|
||||
@@ -186,7 +189,11 @@ func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, err
|
||||
}
|
||||
|
||||
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
|
||||
@@ -251,10 +258,80 @@ 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 = io.NopCloser(bytes.NewReader(formData))
|
||||
req.ContentLength = int64(len(formData))
|
||||
// setFormData set http request FormData param
|
||||
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,11 +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/v2/internal"
|
||||
@@ -49,8 +53,8 @@ func TestHttpPost(t *testing.T) {
|
||||
func TestHttpPostFormData(t *testing.T) {
|
||||
apiUrl := "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{}
|
||||
@@ -61,7 +65,7 @@ func TestHttpPostFormData(t *testing.T) {
|
||||
// postData["userId"] = "1"
|
||||
// postData["title"] = "title"
|
||||
|
||||
resp, err := HttpPost(apiUrl, header, postData, nil)
|
||||
resp, err := HttpPost(apiUrl, header, nil, postData)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@@ -245,3 +249,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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -249,9 +250,14 @@ func DownloadFile(filepath string, url string) error {
|
||||
}
|
||||
|
||||
// IsPingConnected checks if can ping specified host or not.
|
||||
// Play: todo
|
||||
// Play: https://go.dev/play/p/q8OzTijsA87
|
||||
func IsPingConnected(host string) bool {
|
||||
cmd := exec.Command("ping", host, "-c", "1", "-W", "6")
|
||||
cmd := exec.Command("ping", host, "-c", "4", "-W", "6")
|
||||
|
||||
if runtime.GOOS == "windows" {
|
||||
cmd = exec.Command("ping", host, "-n", "4", "-w", "6")
|
||||
}
|
||||
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return false
|
||||
@@ -260,7 +266,7 @@ func IsPingConnected(host string) bool {
|
||||
}
|
||||
|
||||
// IsTelnetConnected checks if can telnet specified host or not.
|
||||
// Play: todo
|
||||
// Play: https://go.dev/play/p/yiLCGtQv_ZG
|
||||
func IsTelnetConnected(host string, port string) bool {
|
||||
adder := host + ":" + port
|
||||
conn, err := net.DialTimeout("tcp", adder, 5*time.Second)
|
||||
|
||||
@@ -3,7 +3,9 @@ package netutil
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
@@ -72,52 +74,34 @@ func setHeaderAndQueryParam(req *http.Request, reqUrl string, header, queryParam
|
||||
}
|
||||
|
||||
func setHeaderAndQueryAndBody(req *http.Request, reqUrl string, header, queryParam, body any) error {
|
||||
err := setHeader(req, header)
|
||||
if err != nil {
|
||||
if err := setHeader(req, header); err != nil {
|
||||
return err
|
||||
} else if err = setQueryParam(req, reqUrl, queryParam); err != nil {
|
||||
return err
|
||||
} else if err = setBodyByte(req, body); err != nil {
|
||||
return err
|
||||
}
|
||||
err = setQueryParam(req, reqUrl, queryParam)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.Contains(req.Header.Get("Content-Type"), "multipart/form-data") || req.Header.Get("Content-Type") == "application/x-www-form-urlencoded" {
|
||||
if formData, ok := queryParam.(url.Values); ok {
|
||||
err = setBodyByte(req, []byte(formData.Encode()))
|
||||
}
|
||||
if formData, ok := queryParam.(map[string]string); ok {
|
||||
postData := url.Values{}
|
||||
for k, v := range formData {
|
||||
postData.Set(k, v)
|
||||
}
|
||||
err = setBodyByte(req, []byte(postData.Encode()))
|
||||
}
|
||||
|
||||
} else {
|
||||
err = setBodyByte(req, body)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setHeader(req *http.Request, header any) error {
|
||||
if header != nil {
|
||||
switch v := header.(type) {
|
||||
case map[string]string:
|
||||
for k := range v {
|
||||
req.Header.Add(k, v[k])
|
||||
}
|
||||
case http.Header:
|
||||
for k, vv := range v {
|
||||
for _, vvv := range vv {
|
||||
req.Header.Add(k, vvv)
|
||||
}
|
||||
}
|
||||
default:
|
||||
return errors.New("header params type should be http.Header or map[string]string")
|
||||
if header == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch v := header.(type) {
|
||||
case map[string]string:
|
||||
for k := range v {
|
||||
req.Header.Add(k, v[k])
|
||||
}
|
||||
case http.Header:
|
||||
for k, vv := range v {
|
||||
for _, vvv := range vv {
|
||||
req.Header.Add(k, vvv)
|
||||
}
|
||||
}
|
||||
default:
|
||||
return errors.New("header params type should be http.Header or map[string]string")
|
||||
}
|
||||
|
||||
if host := req.Header.Get("Host"); host != "" {
|
||||
@@ -137,19 +121,21 @@ func setUrl(req *http.Request, reqUrl string) error {
|
||||
}
|
||||
|
||||
func setQueryParam(req *http.Request, reqUrl string, queryParam any) error {
|
||||
if queryParam == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var values url.Values
|
||||
if queryParam != nil {
|
||||
switch v := queryParam.(type) {
|
||||
case map[string]string:
|
||||
values = url.Values{}
|
||||
for k := range v {
|
||||
values.Set(k, v[k])
|
||||
}
|
||||
case url.Values:
|
||||
values = v
|
||||
default:
|
||||
return errors.New("query string params type should be url.Values or map[string]string")
|
||||
switch v := queryParam.(type) {
|
||||
case map[string]string:
|
||||
values = url.Values{}
|
||||
for k := range v {
|
||||
values.Set(k, v[k])
|
||||
}
|
||||
case url.Values:
|
||||
values = v
|
||||
default:
|
||||
return errors.New("query string params type should be url.Values or map[string]string")
|
||||
}
|
||||
|
||||
// set url
|
||||
@@ -170,14 +156,36 @@ func setQueryParam(req *http.Request, reqUrl string, queryParam any) error {
|
||||
}
|
||||
|
||||
func setBodyByte(req *http.Request, body any) error {
|
||||
if body != nil {
|
||||
switch b := body.(type) {
|
||||
case []byte:
|
||||
req.Body = io.NopCloser(bytes.NewReader(b))
|
||||
req.ContentLength = int64(len(b))
|
||||
default:
|
||||
return errors.New("body type should be []byte")
|
||||
if body == nil {
|
||||
return nil
|
||||
}
|
||||
var bodyReader *bytes.Reader
|
||||
switch b := body.(type) {
|
||||
case io.Reader:
|
||||
buf := bytes.NewBuffer(nil)
|
||||
if _, err := io.Copy(buf, b); err != nil {
|
||||
return err
|
||||
}
|
||||
req.Body = ioutil.NopCloser(buf)
|
||||
req.ContentLength = int64(buf.Len())
|
||||
case []byte:
|
||||
bodyReader = bytes.NewReader(b)
|
||||
req.Body = ioutil.NopCloser(bodyReader)
|
||||
req.ContentLength = int64(bodyReader.Len())
|
||||
case map[string]interface{}:
|
||||
values := url.Values{}
|
||||
for k := range b {
|
||||
values.Set(k, fmt.Sprintf("%v", b[k]))
|
||||
}
|
||||
bodyReader = bytes.NewReader([]byte(values.Encode()))
|
||||
req.Body = ioutil.NopCloser(bodyReader)
|
||||
req.ContentLength = int64(bodyReader.Len())
|
||||
case url.Values:
|
||||
bodyReader = bytes.NewReader([]byte(b.Encode()))
|
||||
req.Body = ioutil.NopCloser(bodyReader)
|
||||
req.ContentLength = int64(bodyReader.Len())
|
||||
default:
|
||||
return fmt.Errorf("invalid body type: %T", b)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ func TestIsPingConnected(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIsPingConnected")
|
||||
|
||||
// in github action env, this will fail
|
||||
// result1 := IsPingConnected("bing.com")
|
||||
// result1 := IsPingConnected("www.baidu.com")
|
||||
// assert.Equal(true, result1)
|
||||
|
||||
result2 := IsPingConnected("www.!@#&&&.com")
|
||||
|
||||
@@ -1,8 +1,25 @@
|
||||
// Copyright 2023 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license.
|
||||
|
||||
// Package pointer contains some util functions to operate go pointer.
|
||||
package pointer
|
||||
|
||||
import "reflect"
|
||||
|
||||
// Of returns a pointer to the value `v`.
|
||||
// Play: todo
|
||||
func Of[T any](v T) *T {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Unwrap returns the value from the pointer.
|
||||
// Play: todo
|
||||
func Unwrap[T any](p *T) T {
|
||||
return *p
|
||||
}
|
||||
|
||||
// ExtractPointer returns the underlying value by the given interface type
|
||||
// Play: todo
|
||||
func ExtractPointer(value any) any {
|
||||
t := reflect.TypeOf(value)
|
||||
v := reflect.ValueOf(value)
|
||||
|
||||
44
pointer/pointer_examples_test.go
Normal file
44
pointer/pointer_examples_test.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package pointer
|
||||
|
||||
import "fmt"
|
||||
|
||||
func ExampleOf() {
|
||||
result1 := Of(123)
|
||||
result2 := Of("abc")
|
||||
|
||||
fmt.Println(*result1)
|
||||
fmt.Println(*result2)
|
||||
|
||||
// Output:
|
||||
// 123
|
||||
// abc
|
||||
}
|
||||
|
||||
func ExampleUnwrap() {
|
||||
a := 123
|
||||
b := "abc"
|
||||
|
||||
result1 := Unwrap(&a)
|
||||
result2 := Unwrap(&b)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// 123
|
||||
// abc
|
||||
}
|
||||
|
||||
func ExampleExtractPointer() {
|
||||
a := 1
|
||||
b := &a
|
||||
c := &b
|
||||
d := &c
|
||||
|
||||
result := ExtractPointer(d)
|
||||
|
||||
fmt.Println(result)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
}
|
||||
@@ -1,12 +1,32 @@
|
||||
package pointer
|
||||
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestExtractPointer(t *testing.T) {
|
||||
func TestOf(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestOf")
|
||||
|
||||
result1 := Of(123)
|
||||
result2 := Of("abc")
|
||||
|
||||
assert.Equal(123, *result1)
|
||||
assert.Equal("abc", *result2)
|
||||
}
|
||||
|
||||
func TestUnwrap(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestUnwrap")
|
||||
|
||||
a := 123
|
||||
b := "abc"
|
||||
|
||||
assert.Equal(a, Unwrap(&a))
|
||||
assert.Equal(b, Unwrap(&b))
|
||||
}
|
||||
|
||||
func TestExtractPointer(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestExtractPointer")
|
||||
|
||||
a := 1
|
||||
|
||||
@@ -114,3 +114,28 @@ 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.
|
||||
// Play: todo
|
||||
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
|
||||
}
|
||||
|
||||
@@ -123,3 +123,14 @@ func ExampleUUIdV4() {
|
||||
// Output:
|
||||
// true
|
||||
}
|
||||
|
||||
func ExampleRandUniqueIntSlice() {
|
||||
result := RandUniqueIntSlice(5, 0, 10)
|
||||
|
||||
if len(result) == 5 {
|
||||
fmt.Println("ok")
|
||||
}
|
||||
|
||||
// Output:
|
||||
// ok
|
||||
}
|
||||
|
||||
@@ -103,3 +103,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
|
||||
}
|
||||
|
||||
@@ -338,7 +338,7 @@ func FindLast[T any](slice []T, predicate func(index int, item T) bool) (*T, boo
|
||||
// FindBy iterates over elements of slice, returning the first one that passes a truth test on predicate function.
|
||||
// If return T is nil or zero value then no items matched the predicate func.
|
||||
// In contrast to Find or FindLast, its return value no longer requires dereferencing
|
||||
// Play: todo
|
||||
// Play: https://go.dev/play/p/n1lysBYl-GB
|
||||
func FindBy[T any](slice []T, predicate func(index int, item T) bool) (v T, ok bool) {
|
||||
index := -1
|
||||
|
||||
@@ -359,7 +359,7 @@ func FindBy[T any](slice []T, predicate func(index int, item T) bool) (v T, ok b
|
||||
// FindLastBy iterates over elements of slice, returning the last one that passes a truth test on predicate function.
|
||||
// If return T is nil or zero value then no items matched the predicate func.
|
||||
// In contrast to Find or FindLast, its return value no longer requires dereferencing
|
||||
// Play: todo
|
||||
// Play: https://go.dev/play/p/8iqomzyCl_s
|
||||
func FindLastBy[T any](slice []T, predicate func(index int, item T) bool) (v T, ok bool) {
|
||||
index := -1
|
||||
|
||||
|
||||
@@ -128,42 +128,46 @@ func TestEqualWith(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestEvery(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestEvery")
|
||||
|
||||
nums := []int{1, 2, 3, 5}
|
||||
isEven := func(i, num int) bool {
|
||||
return num%2 == 0
|
||||
}
|
||||
|
||||
assert := internal.NewAssert(t, "TestEvery")
|
||||
assert.Equal(false, Every(nums, isEven))
|
||||
}
|
||||
|
||||
func TestNone(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestNone")
|
||||
|
||||
nums := []int{1, 2, 3, 5}
|
||||
check := func(i, num int) bool {
|
||||
return num%2 == 1
|
||||
}
|
||||
|
||||
assert := internal.NewAssert(t, "TestNone")
|
||||
assert.Equal(false, None(nums, check))
|
||||
}
|
||||
|
||||
func TestSome(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSome")
|
||||
|
||||
nums := []int{1, 2, 3, 5}
|
||||
hasEven := func(i, num int) bool {
|
||||
return num%2 == 0
|
||||
}
|
||||
|
||||
assert := internal.NewAssert(t, "TestSome")
|
||||
assert.Equal(true, Some(nums, hasEven))
|
||||
}
|
||||
|
||||
func TestFilter(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestFilter")
|
||||
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
isEven := func(i, num int) bool {
|
||||
return num%2 == 0
|
||||
}
|
||||
|
||||
assert := internal.NewAssert(t, "TestFilter")
|
||||
assert.Equal([]int{2, 4}, Filter(nums, isEven))
|
||||
|
||||
type student struct {
|
||||
@@ -189,17 +193,16 @@ func TestFilter(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGroupBy(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestGroupBy")
|
||||
|
||||
nums := []int{1, 2, 3, 4, 5, 6}
|
||||
evenFunc := func(i, num int) bool {
|
||||
return (num % 2) == 0
|
||||
}
|
||||
expectedEven := []int{2, 4, 6}
|
||||
expectedOdd := []int{1, 3, 5}
|
||||
even, odd := GroupBy(nums, evenFunc)
|
||||
|
||||
assert := internal.NewAssert(t, "TestGroupBy")
|
||||
assert.Equal(expectedEven, even)
|
||||
assert.Equal(expectedOdd, odd)
|
||||
assert.Equal([]int{2, 4, 6}, even)
|
||||
assert.Equal([]int{1, 3, 5}, odd)
|
||||
}
|
||||
|
||||
func TestGroupWith(t *testing.T) {
|
||||
@@ -240,65 +243,64 @@ func TestFind(t *testing.T) {
|
||||
even := func(i, num int) bool {
|
||||
return num%2 == 0
|
||||
}
|
||||
res, ok := Find(nums, even)
|
||||
if !ok {
|
||||
t.Fatal("found nothing")
|
||||
}
|
||||
result, ok := Find(nums, even)
|
||||
|
||||
assert := internal.NewAssert(t, "TestFind")
|
||||
assert.Equal(2, *res)
|
||||
assert.Equal(true, ok)
|
||||
assert.Equal(2, *result)
|
||||
}
|
||||
|
||||
func TestFindBy(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestFindBy")
|
||||
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
even := func(i, num int) bool {
|
||||
return num%2 == 0
|
||||
}
|
||||
res, ok := FindBy(nums, even)
|
||||
if !ok {
|
||||
t.Fatal("found nothing")
|
||||
}
|
||||
assert.Equal(2, res)
|
||||
|
||||
res, ok = FindBy(nums, func(_ int, v int) bool {
|
||||
result, ok := FindBy(nums, func(i, num int) bool {
|
||||
return num%2 == 0
|
||||
})
|
||||
assert.Equal(true, ok)
|
||||
assert.Equal(2, result)
|
||||
|
||||
result, ok = FindBy(nums, func(_ int, v int) bool {
|
||||
return v == 6
|
||||
})
|
||||
assert.Equal(res == 0 && ok == false, true)
|
||||
assert.Equal(false, ok)
|
||||
assert.Equal(0, result)
|
||||
}
|
||||
|
||||
func TestFindLastBy(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestFindBy")
|
||||
assert := internal.NewAssert(t, "TestFindLastBy")
|
||||
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
even := func(i, num int) bool {
|
||||
return num%2 == 0
|
||||
}
|
||||
res, ok := FindLastBy(nums, even)
|
||||
result, ok := FindLastBy(nums, even)
|
||||
if !ok {
|
||||
t.Fatal("found nothing")
|
||||
}
|
||||
assert.Equal(4, res)
|
||||
assert.Equal(4, result)
|
||||
|
||||
res, ok = FindLastBy(nums, func(_ int, v int) bool {
|
||||
result, ok = FindLastBy(nums, func(_ int, v int) bool {
|
||||
return v == 6
|
||||
})
|
||||
assert.Equal(res == 0 && ok == false, true)
|
||||
|
||||
assert.Equal(result == 0 && ok == false, true)
|
||||
}
|
||||
|
||||
func TestFindLast(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestFindLast")
|
||||
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
even := func(i, num int) bool {
|
||||
return num%2 == 0
|
||||
}
|
||||
res, ok := FindLast(nums, even)
|
||||
result, ok := FindLast(nums, even)
|
||||
if !ok {
|
||||
t.Fatal("found nothing")
|
||||
}
|
||||
|
||||
assert := internal.NewAssert(t, "TestFindLast")
|
||||
assert.Equal(4, *res)
|
||||
assert.Equal(4, *result)
|
||||
}
|
||||
|
||||
func TestFindFoundNothing(t *testing.T) {
|
||||
@@ -307,45 +309,47 @@ func TestFindFoundNothing(t *testing.T) {
|
||||
return num > 1
|
||||
}
|
||||
_, ok := Find(nums, findFunc)
|
||||
// if ok {
|
||||
// t.Fatal("found something")
|
||||
// }
|
||||
|
||||
assert := internal.NewAssert(t, "TestFindFoundNothing")
|
||||
assert.Equal(false, ok)
|
||||
}
|
||||
|
||||
func TestFlatten(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestFlatten")
|
||||
|
||||
input := [][][]string{{{"a", "b"}}, {{"c", "d"}}}
|
||||
expected := [][]string{{"a", "b"}, {"c", "d"}}
|
||||
|
||||
assert := internal.NewAssert(t, "TestFlatten")
|
||||
assert.Equal(expected, Flatten(input))
|
||||
}
|
||||
|
||||
func TestFlattenDeep(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestFlattenDeep")
|
||||
|
||||
input := [][][]string{{{"a", "b"}}, {{"c", "d"}}}
|
||||
expected := []string{"a", "b", "c", "d"}
|
||||
|
||||
assert := internal.NewAssert(t, "TestFlattenDeep")
|
||||
assert.Equal(expected, FlattenDeep(input))
|
||||
}
|
||||
|
||||
func TestForEach(t *testing.T) {
|
||||
numbers := []int{1, 2, 3, 4, 5}
|
||||
expected := []int{3, 4, 5, 6, 7}
|
||||
assert := internal.NewAssert(t, "TestForEach")
|
||||
|
||||
var numbersAddTwo []int
|
||||
numbers := []int{1, 2, 3, 4, 5}
|
||||
|
||||
var result []int
|
||||
addTwo := func(index int, value int) {
|
||||
numbersAddTwo = append(numbersAddTwo, value+2)
|
||||
result = append(result, value+2)
|
||||
}
|
||||
|
||||
ForEach(numbers, addTwo)
|
||||
|
||||
assert := internal.NewAssert(t, "TestForEach")
|
||||
assert.Equal(expected, numbersAddTwo)
|
||||
assert.Equal([]int{3, 4, 5, 6, 7}, result)
|
||||
}
|
||||
|
||||
func TestForEachWithBreak(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestForEach")
|
||||
|
||||
numbers := []int{1, 2, 3, 4, 5}
|
||||
|
||||
var sum int
|
||||
@@ -358,17 +362,17 @@ func TestForEachWithBreak(t *testing.T) {
|
||||
return true
|
||||
})
|
||||
|
||||
assert := internal.NewAssert(t, "TestForEach")
|
||||
assert.Equal(6, sum)
|
||||
}
|
||||
|
||||
func TestMap(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestMap")
|
||||
|
||||
nums := []int{1, 2, 3, 4}
|
||||
multiplyTwo := func(i, num int) int {
|
||||
return num * 2
|
||||
}
|
||||
|
||||
assert := internal.NewAssert(t, "TestMap")
|
||||
assert.Equal([]int{2, 4, 6, 8}, Map(nums, multiplyTwo))
|
||||
|
||||
type student struct {
|
||||
@@ -424,6 +428,8 @@ func TestFlatMap(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestReduce(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestReduce")
|
||||
|
||||
cases := [][]int{
|
||||
{},
|
||||
{1},
|
||||
@@ -435,8 +441,6 @@ func TestReduce(t *testing.T) {
|
||||
return v1 + v2
|
||||
}
|
||||
|
||||
assert := internal.NewAssert(t, "TestReduce")
|
||||
|
||||
for i := 0; i < len(cases); i++ {
|
||||
actual := Reduce(cases[i], f, 0)
|
||||
assert.Equal(expected[i], actual)
|
||||
@@ -460,7 +464,7 @@ func TestReduceBy(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestReduceRight(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "ReduceRight")
|
||||
assert := internal.NewAssert(t, "TestReduceRight")
|
||||
|
||||
result := ReduceRight([]int{1, 2, 3, 4}, "", func(_ int, item int, agg string) string {
|
||||
return agg + fmt.Sprintf("%v", item)
|
||||
@@ -470,26 +474,29 @@ func TestReduceRight(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestIntSlice(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIntSlice")
|
||||
|
||||
var nums []any
|
||||
nums = append(nums, 1, 2, 3)
|
||||
|
||||
assert := internal.NewAssert(t, "TestIntSlice")
|
||||
assert.Equal([]int{1, 2, 3}, IntSlice(nums))
|
||||
}
|
||||
|
||||
func TestStringSlice(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestStringSlice")
|
||||
|
||||
var strs []any
|
||||
strs = append(strs, "a", "b", "c")
|
||||
|
||||
assert := internal.NewAssert(t, "TestStringSlice")
|
||||
assert.Equal([]string{"a", "b", "c"}, StringSlice(strs))
|
||||
}
|
||||
|
||||
func TestInterfaceSlice(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestInterfaceSlice")
|
||||
|
||||
strs := []string{"a", "b", "c"}
|
||||
expect := []any{"a", "b", "c"}
|
||||
|
||||
assert := internal.NewAssert(t, "TestInterfaceSlice")
|
||||
assert.Equal(expect, InterfaceSlice(strs))
|
||||
}
|
||||
|
||||
@@ -657,6 +664,8 @@ func TestMerge(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestIntersection(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIntersection")
|
||||
|
||||
s1 := []int{1, 2, 2, 3}
|
||||
s2 := []int{1, 2, 3, 4}
|
||||
s3 := []int{0, 2, 3, 5, 6}
|
||||
@@ -668,17 +677,15 @@ func TestIntersection(t *testing.T) {
|
||||
{1, 2, 3},
|
||||
{},
|
||||
}
|
||||
res := []any{
|
||||
result := []any{
|
||||
Intersection(s1, s2, s3),
|
||||
Intersection(s1, s2),
|
||||
Intersection(s1),
|
||||
Intersection(s1, s4),
|
||||
}
|
||||
|
||||
assert := internal.NewAssert(t, "TestIntersection")
|
||||
|
||||
for i := 0; i < len(res); i++ {
|
||||
assert.Equal(expected[i], res[i])
|
||||
for i := 0; i < len(result); i++ {
|
||||
assert.Equal(expected[i], result[i])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -711,6 +718,7 @@ func TestDifference(t *testing.T) {
|
||||
|
||||
s1 := []int{1, 2, 3, 4, 5}
|
||||
s2 := []int{4, 5, 6}
|
||||
|
||||
assert.Equal([]int{1, 2, 3}, Difference(s1, s2))
|
||||
}
|
||||
|
||||
@@ -722,6 +730,7 @@ func TestDifferenceWith(t *testing.T) {
|
||||
isDouble := func(v1, v2 int) bool {
|
||||
return v2 == 2*v1
|
||||
}
|
||||
|
||||
assert.Equal([]int{1, 5}, DifferenceWith(s1, s2, isDouble))
|
||||
}
|
||||
|
||||
@@ -733,6 +742,7 @@ func TestDifferenceBy(t *testing.T) {
|
||||
addOne := func(i int, v int) int {
|
||||
return v + 1
|
||||
}
|
||||
|
||||
assert.Equal([]int{1, 2}, DifferenceBy(s1, s2, addOne))
|
||||
}
|
||||
|
||||
@@ -848,7 +858,7 @@ func TestSortByFielDesc(t *testing.T) {
|
||||
err := SortByField(students, "age", "desc")
|
||||
assert.IsNil(err)
|
||||
|
||||
assert.Equal(students, studentsOfSortByAge)
|
||||
assert.Equal(studentsOfSortByAge, students)
|
||||
}
|
||||
|
||||
func TestSortByFieldAsc(t *testing.T) {
|
||||
@@ -874,7 +884,7 @@ func TestSortByFieldAsc(t *testing.T) {
|
||||
err := SortByField(students, "age")
|
||||
assert.IsNil(err)
|
||||
|
||||
assert.Equal(students, studentsOfSortByAge)
|
||||
assert.Equal(studentsOfSortByAge, students)
|
||||
}
|
||||
|
||||
func TestWithout(t *testing.T) {
|
||||
@@ -886,10 +896,10 @@ func TestWithout(t *testing.T) {
|
||||
func TestShuffle(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestShuffle")
|
||||
|
||||
s := []int{1, 2, 3, 4, 5}
|
||||
res := Shuffle(s)
|
||||
numbers := []int{1, 2, 3, 4, 5}
|
||||
result := Shuffle(numbers)
|
||||
|
||||
assert.Equal(5, len(res))
|
||||
assert.Equal(5, len(result))
|
||||
}
|
||||
|
||||
func TestIndexOf(t *testing.T) {
|
||||
@@ -1000,13 +1010,12 @@ func TestKeyBy(t *testing.T) {
|
||||
return len(str)
|
||||
})
|
||||
|
||||
assert.Equal(result, map[int]string{1: "a", 2: "ab", 3: "abc"})
|
||||
assert.Equal(map[int]string{1: "a", 2: "ab", 3: "abc"}, result)
|
||||
}
|
||||
|
||||
func TestRepeat(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestRepeat")
|
||||
|
||||
result := Repeat("a", 6)
|
||||
|
||||
assert.Equal(result, []string{"a", "a", "a", "a", "a", "a"})
|
||||
assert.Equal([]string{}, Repeat("a", 0))
|
||||
assert.Equal([]string{"a", "a", "a", "a", "a", "a"}, Repeat("a", 6))
|
||||
}
|
||||
|
||||
@@ -295,6 +295,18 @@ func (s stream[T]) FindFirst() (T, bool) {
|
||||
return s.source[0], true
|
||||
}
|
||||
|
||||
// FindLast returns the last element of this stream and true, or zero value and false if the stream is empty.
|
||||
// Play: https://go.dev/play/p/WZD2rDAW-2h
|
||||
func (s stream[T]) FindLast() (T, bool) {
|
||||
var result T
|
||||
|
||||
if s.source == nil || len(s.source) == 0 {
|
||||
return result, false
|
||||
}
|
||||
|
||||
return s.source[len(s.source)-1], true
|
||||
}
|
||||
|
||||
// Reverse returns a stream whose elements are reverse order of given stream.
|
||||
// Play: https://go.dev/play/p/A8_zkJnLHm4
|
||||
func (s stream[T]) Reverse() stream[T] {
|
||||
|
||||
@@ -290,6 +290,19 @@ func ExampleStream_FindFirst() {
|
||||
// true
|
||||
}
|
||||
|
||||
func ExampleStream_FindLast() {
|
||||
original := FromSlice([]int{3, 2, 1})
|
||||
|
||||
result, ok := original.FindLast()
|
||||
|
||||
fmt.Println(result)
|
||||
fmt.Println(ok)
|
||||
|
||||
// Output:
|
||||
// 1
|
||||
// true
|
||||
}
|
||||
|
||||
func ExampleStream_Reverse() {
|
||||
original := FromSlice([]int{1, 2, 3})
|
||||
|
||||
|
||||
@@ -273,6 +273,24 @@ func TestStream_FindFirst(t *testing.T) {
|
||||
assert.Equal(true, ok)
|
||||
}
|
||||
|
||||
func TestStream_FindLast(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestStream_FindLast")
|
||||
|
||||
stream := FromSlice([]int{3, 2, 1})
|
||||
|
||||
result, ok := stream.FindLast()
|
||||
|
||||
assert.Equal(1, result)
|
||||
assert.Equal(true, ok)
|
||||
|
||||
stream2 := FromSlice([]int{})
|
||||
|
||||
result, ok = stream2.FindLast()
|
||||
|
||||
assert.Equal(0, result)
|
||||
assert.Equal(false, ok)
|
||||
}
|
||||
|
||||
func TestStream_Reverse(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestStream_Reverse")
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ package strutil
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
@@ -377,7 +378,7 @@ func RemoveNonPrintable(str string) string {
|
||||
}
|
||||
|
||||
// StringToBytes converts a string to byte slice without a memory allocation.
|
||||
// Play: todo
|
||||
// Play: https://go.dev/play/p/7OyFBrf9AxA
|
||||
func StringToBytes(str string) (b []byte) {
|
||||
sh := *(*reflect.StringHeader)(unsafe.Pointer(&str))
|
||||
bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
|
||||
@@ -386,13 +387,13 @@ func StringToBytes(str string) (b []byte) {
|
||||
}
|
||||
|
||||
// BytesToString converts a byte slice to string without a memory allocation.
|
||||
// Play: todo
|
||||
// Play: https://go.dev/play/p/6c68HRvJecH
|
||||
func BytesToString(bytes []byte) string {
|
||||
return *(*string)(unsafe.Pointer(&bytes))
|
||||
}
|
||||
|
||||
// IsBlank checks if a string is whitespace, empty.
|
||||
// Play: todo
|
||||
// Play: https://go.dev/play/p/6zXRH_c0Qd3
|
||||
func IsBlank(str string) bool {
|
||||
if len(str) == 0 {
|
||||
return true
|
||||
@@ -407,8 +408,8 @@ func IsBlank(str string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// HasPrefixAny check if a string starts with any of an array of specified strings.
|
||||
// Play: todo
|
||||
// HasPrefixAny check if a string starts with any of a slice of specified strings.
|
||||
// Play: https://go.dev/play/p/8UUTl2C5slo
|
||||
func HasPrefixAny(str string, prefixes []string) bool {
|
||||
if len(str) == 0 || len(prefixes) == 0 {
|
||||
return false
|
||||
@@ -421,8 +422,8 @@ func HasPrefixAny(str string, prefixes []string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// HasSuffixAny check if a string ends with any of an array of specified strings.
|
||||
// Play: todo
|
||||
// HasSuffixAny check if a string ends with any of a slice of specified strings.
|
||||
// Play: https://go.dev/play/p/sKWpCQdOVkx
|
||||
func HasSuffixAny(str string, suffixes []string) bool {
|
||||
if len(str) == 0 || len(suffixes) == 0 {
|
||||
return false
|
||||
@@ -437,7 +438,7 @@ func HasSuffixAny(str string, suffixes []string) bool {
|
||||
|
||||
// IndexOffset returns the index of the first instance of substr in string after offsetting the string by `idxFrom`,
|
||||
// or -1 if substr is not present in string.
|
||||
// Play: todo
|
||||
// Play: https://go.dev/play/p/qZo4lV2fomB
|
||||
func IndexOffset(str string, substr string, idxFrom int) int {
|
||||
if idxFrom > len(str)-1 || idxFrom < 0 {
|
||||
return -1
|
||||
@@ -445,3 +446,129 @@ func IndexOffset(str string, substr string, idxFrom int) int {
|
||||
|
||||
return strings.Index(str[idxFrom:], substr) + idxFrom
|
||||
}
|
||||
|
||||
// ReplaceWithMap returns a copy of `str`,
|
||||
// which is replaced by a map in unordered way, case-sensitively.
|
||||
// Play: https://go.dev/play/p/h3t7CNj2Vvu
|
||||
func ReplaceWithMap(str string, replaces map[string]string) string {
|
||||
for k, v := range replaces {
|
||||
str = strings.ReplaceAll(str, k, v)
|
||||
}
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
// SplitAndTrim splits string `str` by a string `delimiter` to a slice,
|
||||
// and calls Trim to every element of this slice. It ignores the elements
|
||||
// which are empty after Trim.
|
||||
// Play: https://go.dev/play/p/ZNL6o4SkYQ7
|
||||
func SplitAndTrim(str, delimiter string, characterMask ...string) []string {
|
||||
result := make([]string, 0)
|
||||
|
||||
for _, v := range strings.Split(str, delimiter) {
|
||||
v = Trim(v, characterMask...)
|
||||
if v != "" {
|
||||
result = append(result, v)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
var (
|
||||
// DefaultTrimChars are the characters which are stripped by Trim* functions in default.
|
||||
DefaultTrimChars = string([]byte{
|
||||
'\t', // Tab.
|
||||
'\v', // Vertical tab.
|
||||
'\n', // New line (line feed).
|
||||
'\r', // Carriage return.
|
||||
'\f', // New page.
|
||||
' ', // Ordinary space.
|
||||
0x00, // NUL-byte.
|
||||
0x85, // Delete.
|
||||
0xA0, // Non-breaking space.
|
||||
})
|
||||
)
|
||||
|
||||
// Trim strips whitespace (or other characters) from the beginning and end of a string.
|
||||
// The optional parameter `characterMask` specifies the additional stripped characters.
|
||||
// Play: https://go.dev/play/p/Y0ilP0NRV3j
|
||||
func Trim(str string, characterMask ...string) string {
|
||||
trimChars := DefaultTrimChars
|
||||
|
||||
if len(characterMask) > 0 {
|
||||
trimChars += characterMask[0]
|
||||
}
|
||||
|
||||
return strings.Trim(str, trimChars)
|
||||
}
|
||||
|
||||
// HideString hide some chars in source string with param `replaceChar`.
|
||||
// replace range is origin[start : end]. [start, end)
|
||||
// Play: https://go.dev/play/p/pzbaIVCTreZ)
|
||||
func HideString(origin string, start, end int, replaceChar string) string {
|
||||
size := len(origin)
|
||||
|
||||
if start > size-1 || start < 0 || end < 0 || start > end {
|
||||
return origin
|
||||
}
|
||||
|
||||
if end > size {
|
||||
end = size
|
||||
}
|
||||
|
||||
if replaceChar == "" {
|
||||
return origin
|
||||
}
|
||||
|
||||
startStr := origin[0:start]
|
||||
endStr := origin[end:size]
|
||||
|
||||
replaceSize := end - start
|
||||
replaceStr := strings.Repeat(replaceChar, replaceSize)
|
||||
|
||||
return startStr + replaceStr + endStr
|
||||
}
|
||||
|
||||
// ContainsAll return true if target string contains all the substrs.
|
||||
// Play: https://go.dev/play/p/KECtK2Os4zq
|
||||
func ContainsAll(str string, substrs []string) bool {
|
||||
for _, v := range substrs {
|
||||
if !strings.Contains(str, v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// ContainsAny return true if target string contains any one of the substrs.
|
||||
// Play: https://go.dev/play/p/dZGSSMB3LXE
|
||||
func ContainsAny(str string, substrs []string) bool {
|
||||
for _, v := range substrs {
|
||||
if strings.Contains(str, v) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
// Play: todo
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -394,22 +394,19 @@ func ExampleSplitWords() {
|
||||
|
||||
result1 := SplitWords("a word")
|
||||
result2 := SplitWords("I'am a programmer")
|
||||
result3 := SplitWords("Bonjour, je suis programmeur")
|
||||
result4 := SplitWords("a -b-c' 'd'e")
|
||||
result5 := SplitWords("你好,我是一名码农")
|
||||
result6 := SplitWords("こんにちは,私はプログラマーです")
|
||||
result3 := SplitWords("a -b-c' 'd'e")
|
||||
result4 := SplitWords("你好,我是一名码农")
|
||||
result5 := SplitWords("こんにちは,私はプログラマーです")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
fmt.Println(result6)
|
||||
|
||||
// Output:
|
||||
// [a word]
|
||||
// [I'am a programmer]
|
||||
// [Bonjour je suis programmeur]
|
||||
// [a b-c' d'e]
|
||||
// []
|
||||
// []
|
||||
@@ -419,22 +416,19 @@ func ExampleWordCount() {
|
||||
|
||||
result1 := WordCount("a word")
|
||||
result2 := WordCount("I'am a programmer")
|
||||
result3 := WordCount("Bonjour, je suis programmeur")
|
||||
result4 := WordCount("a -b-c' 'd'e")
|
||||
result5 := WordCount("你好,我是一名码农")
|
||||
result6 := WordCount("こんにちは,私はプログラマーです")
|
||||
result3 := WordCount("a -b-c' 'd'e")
|
||||
result4 := WordCount("你好,我是一名码农")
|
||||
result5 := WordCount("こんにちは,私はプログラマーです")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
fmt.Println(result5)
|
||||
fmt.Println(result6)
|
||||
|
||||
// Output:
|
||||
// 2
|
||||
// 3
|
||||
// 4
|
||||
// 3
|
||||
// 0
|
||||
// 0
|
||||
@@ -528,3 +522,114 @@ func ExampleIndexOffset() {
|
||||
// -1
|
||||
// -1
|
||||
}
|
||||
|
||||
func ExampleReplaceWithMap() {
|
||||
str := "ac ab ab ac"
|
||||
replaces := map[string]string{
|
||||
"a": "1",
|
||||
"b": "2",
|
||||
}
|
||||
|
||||
result := ReplaceWithMap(str, replaces)
|
||||
|
||||
fmt.Println(result)
|
||||
// Output:
|
||||
// 1c 12 12 1c
|
||||
}
|
||||
|
||||
func ExampleTrim() {
|
||||
result1 := Trim("\nabcd")
|
||||
|
||||
str := "$ ab cd $ "
|
||||
|
||||
result2 := Trim(str)
|
||||
result3 := Trim(str, "$")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// abcd
|
||||
// $ ab cd $
|
||||
// ab cd
|
||||
}
|
||||
|
||||
func ExampleSplitAndTrim() {
|
||||
str := " a,b, c,d,$1 "
|
||||
|
||||
result1 := SplitAndTrim(str, ",")
|
||||
result2 := SplitAndTrim(str, ",", "$")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// [a b c d $1]
|
||||
// [a b c d 1]
|
||||
}
|
||||
|
||||
func ExampleHideString() {
|
||||
str := "13242658976"
|
||||
|
||||
result1 := HideString(str, 3, 3, "*")
|
||||
result2 := HideString(str, 3, 4, "*")
|
||||
result3 := HideString(str, 3, 7, "*")
|
||||
result4 := HideString(str, 7, 11, "*")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// 13242658976
|
||||
// 132*2658976
|
||||
// 132****8976
|
||||
// 1324265****
|
||||
}
|
||||
|
||||
func ExampleContainsAll() {
|
||||
str := "hello world"
|
||||
|
||||
result1 := ContainsAll(str, []string{"hello", "world"})
|
||||
result2 := ContainsAll(str, []string{"hello", "abc"})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
|
||||
func ExampleContainsAny() {
|
||||
str := "hello world"
|
||||
|
||||
result1 := ContainsAny(str, []string{"hello", "world"})
|
||||
result2 := ContainsAny(str, []string{"hello", "abc"})
|
||||
result3 := ContainsAny(str, []string{"123", "abc"})
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
}
|
||||
|
||||
func ExampleRemoveWhiteSpace() {
|
||||
str := " hello \r\n \t world"
|
||||
|
||||
result1 := RemoveWhiteSpace(str, true)
|
||||
result2 := RemoveWhiteSpace(str, false)
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
|
||||
// Output:
|
||||
// helloworld
|
||||
// hello world
|
||||
}
|
||||
|
||||
@@ -314,11 +314,10 @@ func TestSplitWords(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSplitWords")
|
||||
|
||||
cases := map[string][]string{
|
||||
"a word": {"a", "word"},
|
||||
"I'am a programmer": {"I'am", "a", "programmer"},
|
||||
"Bonjour, je suis programmeur": {"Bonjour", "je", "suis", "programmeur"},
|
||||
"a -b-c' 'd'e": {"a", "b-c'", "d'e"},
|
||||
"你好,我是一名码农": nil,
|
||||
"a word": {"a", "word"},
|
||||
"I'am a programmer": {"I'am", "a", "programmer"},
|
||||
"a -b-c' 'd'e": {"a", "b-c'", "d'e"},
|
||||
"你好,我是一名码农": nil,
|
||||
"こんにちは,私はプログラマーです": nil,
|
||||
}
|
||||
|
||||
@@ -331,11 +330,10 @@ func TestWordCount(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSplitWords")
|
||||
|
||||
cases := map[string]int{
|
||||
"a word": 2, // {"a", "word"},
|
||||
"I'am a programmer": 3, // {"I'am", "a", "programmer"},
|
||||
"Bonjour, je suis programmeur": 4, // {"Bonjour", "je", "suis", "programmeur"},
|
||||
"a -b-c' 'd'e": 3, // {"a", "b-c'", "d'e"},
|
||||
"你好,我是一名码农": 0, // nil,
|
||||
"a word": 2, // {"a", "word"},
|
||||
"I'am a programmer": 3, // {"I'am", "a", "programmer"},
|
||||
"a -b-c' 'd'e": 3, // {"a", "b-c'", "d'e"},
|
||||
"你好,我是一名码农": 0, // nil,
|
||||
"こんにちは,私はプログラマーです": 0, // nil,
|
||||
}
|
||||
|
||||
@@ -399,3 +397,82 @@ func TestIndexOffset(t *testing.T) {
|
||||
assert.Equal(IndexOffset(str, "d", len(str)), -1)
|
||||
assert.Equal(IndexOffset(str, "f", -1), -1)
|
||||
}
|
||||
|
||||
func TestReplaceWithMap(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestReplaceWithMap")
|
||||
|
||||
str := "ac ab ab ac"
|
||||
replaces := map[string]string{
|
||||
"a": "1",
|
||||
"b": "2",
|
||||
}
|
||||
|
||||
assert.Equal(str, "ac ab ab ac")
|
||||
assert.Equal(ReplaceWithMap(str, replaces), "1c 12 12 1c")
|
||||
}
|
||||
|
||||
func TestTrim(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestTrim")
|
||||
|
||||
str1 := "$ ab cd $ "
|
||||
|
||||
assert.Equal("$ ab cd $", Trim(str1))
|
||||
assert.Equal("ab cd", Trim(str1, "$"))
|
||||
assert.Equal("abcd", Trim("\nabcd"))
|
||||
}
|
||||
|
||||
func TestSplitAndTrim(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestTrim")
|
||||
|
||||
str := " a,b, c,d,$1 "
|
||||
|
||||
result1 := SplitAndTrim(str, ",")
|
||||
result2 := SplitAndTrim(str, ",", "$")
|
||||
|
||||
assert.Equal([]string{"a", "b", "c", "d", "$1"}, result1)
|
||||
assert.Equal([]string{"a", "b", "c", "d", "1"}, result2)
|
||||
}
|
||||
|
||||
func TestHideString(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestTrim")
|
||||
|
||||
str := "13242658976"
|
||||
|
||||
assert.Equal("13242658976", HideString(str, 0, -1, "*"))
|
||||
assert.Equal("13242658976", HideString(str, 0, 0, "*"))
|
||||
assert.Equal("****2658976", HideString(str, 0, 4, "*"))
|
||||
|
||||
assert.Equal("13242658976", HideString(str, 3, 3, "*"))
|
||||
assert.Equal("132*2658976", HideString(str, 3, 4, "*"))
|
||||
assert.Equal("132****8976", HideString(str, 3, 7, "*"))
|
||||
assert.Equal("1324265****", HideString(str, 7, 11, "*"))
|
||||
|
||||
assert.Equal("1324265****", HideString(str, 7, 100, "*"))
|
||||
assert.Equal("13242658976", HideString(str, 100, 100, "*"))
|
||||
}
|
||||
|
||||
func TestContainsAll(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestContainsAll")
|
||||
|
||||
assert.Equal(true, ContainsAll("hello world", []string{"hello", "world"}))
|
||||
assert.Equal(true, ContainsAll("hello world", []string{""}))
|
||||
assert.Equal(false, ContainsAll("hello world", []string{"hello", "abc"}))
|
||||
}
|
||||
|
||||
func TestContainsAny(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestContainsAny")
|
||||
|
||||
assert.Equal(true, ContainsAny("hello world", []string{"hello", "world"}))
|
||||
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))
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
var (
|
||||
alphaMatcher *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z]+$`)
|
||||
letterRegexMatcher *regexp.Regexp = regexp.MustCompile(`[a-zA-Z]`)
|
||||
numberRegexMatcher *regexp.Regexp = regexp.MustCompile(`\d`)
|
||||
intStrMatcher *regexp.Regexp = regexp.MustCompile(`^[\+-]?\d+$`)
|
||||
urlMatcher *regexp.Regexp = regexp.MustCompile(`^((ftp|http|https?):\/\/)?(\S+(:\S*)?@)?((([1-9]\d?|1\d\d|2[01]\d|22[0-3])(\.(1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(([a-zA-Z0-9]+([-\.][a-zA-Z0-9]+)*)|((www\.)?))?(([a-z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-z\x{00a1}-\x{ffff}]{2,}))?))(:(\d{1,5}))?((\/|\?|#)[^\s]*)?$`)
|
||||
dnsMatcher *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z]([a-zA-Z0-9\-]+[\.]?)*[a-zA-Z0-9]$`)
|
||||
@@ -111,6 +112,11 @@ func ContainLetter(str string) bool {
|
||||
return letterRegexMatcher.MatchString(str)
|
||||
}
|
||||
|
||||
// ContainLetter check if the string contain at least one number.
|
||||
func ContainNumber(input string) bool {
|
||||
return numberRegexMatcher.MatchString(input)
|
||||
}
|
||||
|
||||
// IsJSON checks if the string is valid JSON.
|
||||
// Play: https://go.dev/play/p/8Kip1Itjiil
|
||||
func IsJSON(str string) bool {
|
||||
|
||||
@@ -36,6 +36,24 @@ func ExampleContainLetter() {
|
||||
// true
|
||||
}
|
||||
|
||||
func ExampleContainNumber() {
|
||||
result1 := ContainNumber("你好")
|
||||
result2 := ContainNumber("&@#$%^&*")
|
||||
result3 := ContainNumber("ab1")
|
||||
result4 := ContainNumber("1234")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// false
|
||||
// false
|
||||
// true
|
||||
// true
|
||||
}
|
||||
|
||||
func ExampleContainLower() {
|
||||
result1 := ContainLower("abc")
|
||||
result2 := ContainLower("aBC")
|
||||
|
||||
@@ -86,6 +86,23 @@ func TestContainLetter(t *testing.T) {
|
||||
assert.Equal(false, ContainLetter("&@#$%^&*"))
|
||||
}
|
||||
|
||||
func TestContainNumber(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestContainNumber")
|
||||
|
||||
assert.Equal(true, ContainNumber("123"))
|
||||
assert.Equal(true, ContainNumber("1Bc"))
|
||||
assert.Equal(true, ContainNumber("a2c"))
|
||||
assert.Equal(true, ContainNumber("ab3"))
|
||||
assert.Equal(true, ContainNumber("a23"))
|
||||
assert.Equal(true, ContainNumber("a23c"))
|
||||
assert.Equal(true, ContainNumber("1%%%"))
|
||||
|
||||
assert.Equal(false, ContainNumber("ABC"))
|
||||
assert.Equal(false, ContainNumber(""))
|
||||
assert.Equal(false, ContainNumber("你好"))
|
||||
assert.Equal(false, ContainNumber("&@#$%^&*"))
|
||||
}
|
||||
|
||||
func TestIsJSON(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIsJSON")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user