mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-08 06:32:28 +08:00
Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a8ff17b52 | ||
|
|
6b46a0c05c | ||
|
|
4b8b624b4c | ||
|
|
f274375e62 | ||
|
|
6dc017a5fa | ||
|
|
e1fb97095d | ||
|
|
d8f5a15590 | ||
|
|
1202ac955d | ||
|
|
84b2cec9b5 | ||
|
|
2d01a13787 | ||
|
|
db9b045500 | ||
|
|
2701bcc4d2 | ||
|
|
b9745fd08b | ||
|
|
3b1597d6f7 | ||
|
|
40ab5e8f7b | ||
|
|
cacedf2a05 | ||
|
|
4fc391895b | ||
|
|
b419319e66 | ||
|
|
db34b5f69c | ||
|
|
ee44526d9e | ||
|
|
6576b1f0cb | ||
|
|
93108bafb9 | ||
|
|
07f5e0697f | ||
|
|
4ba91d7e4c | ||
|
|
ab81d9c283 |
98
README.md
98
README.md
@@ -4,7 +4,7 @@
|
|||||||
<br/>
|
<br/>
|
||||||
|
|
||||||

|

|
||||||
[](https://github.com/duke-git/lancet/releases)
|
[](https://github.com/duke-git/lancet/releases)
|
||||||
[](https://pkg.go.dev/github.com/duke-git/lancet)
|
[](https://pkg.go.dev/github.com/duke-git/lancet)
|
||||||
[](https://goreportcard.com/report/github.com/duke-git/lancet)
|
[](https://goreportcard.com/report/github.com/duke-git/lancet)
|
||||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||||
@@ -24,7 +24,7 @@ English | [简体中文](./README_zh-CN.md)
|
|||||||
## Feature
|
## Feature
|
||||||
|
|
||||||
- 👏 Comprehensive, efficient and reusable.
|
- 👏 Comprehensive, efficient and reusable.
|
||||||
- 💪 200+ go util functions, support string, slice, datetime, net, crypt...
|
- 💪 400+ go util functions, support string, slice, datetime, net, crypt...
|
||||||
- 💅 Only depend on the go standard library.
|
- 💅 Only depend on the go standard library.
|
||||||
- 🌍 Unit test for every exported function.
|
- 🌍 Unit test for every exported function.
|
||||||
|
|
||||||
@@ -63,7 +63,22 @@ func main() {
|
|||||||
|
|
||||||
## API Documentation
|
## API Documentation
|
||||||
|
|
||||||
### 1. Convertor package contains some functions for data convertion.
|
### 1. Compare package provides a lightweight comparison function on any type.
|
||||||
|
|
||||||
|
```go
|
||||||
|
import "github.com/duke-git/lancet/compare"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Function list:
|
||||||
|
|
||||||
|
- [Equal](https://github.com/duke-git/lancet/blob/v1/docs/compare.md#Equal)
|
||||||
|
- [EqualValue](https://github.com/duke-git/lancet/blob/v1/docs/compare.md#EqualValue)
|
||||||
|
- [LessThan](https://github.com/duke-git/lancet/blob/v1/docs/compare.md#LessThan)
|
||||||
|
- [GreaterThan](https://github.com/duke-git/lancet/blob/v1/docs/compare.md#GreaterThan)
|
||||||
|
- [LessOrEqual](https://github.com/duke-git/lancet/blob/v1/docs/compare.md#LessOrEqual)
|
||||||
|
- [GreaterOrEqual](https://github.com/duke-git/lancet/blob/v1/docs/compare.md#GreaterOrEqual)
|
||||||
|
|
||||||
|
### 2. Convertor package contains some functions for data convertion.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/convertor"
|
import "github.com/duke-git/lancet/convertor"
|
||||||
@@ -86,7 +101,7 @@ import "github.com/duke-git/lancet/convertor"
|
|||||||
- [DeepClone](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#DeepClone)
|
- [DeepClone](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#DeepClone)
|
||||||
- [CopyProperties](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#CopyProperties)
|
- [CopyProperties](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#CopyProperties)
|
||||||
|
|
||||||
### 2. Cryptor package is for data encryption and decryption.
|
### 3. Cryptor package is for data encryption and decryption.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/cryptor"
|
import "github.com/duke-git/lancet/cryptor"
|
||||||
@@ -127,7 +142,7 @@ import "github.com/duke-git/lancet/cryptor"
|
|||||||
- [RsaEncrypt](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#RsaEncrypt)
|
- [RsaEncrypt](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#RsaEncrypt)
|
||||||
- [RsaDecrypt](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#RsaDecrypt)
|
- [RsaDecrypt](https://github.com/duke-git/lancet/blob/v1/docs/cryptor.md#RsaDecrypt)
|
||||||
|
|
||||||
### 3. Datetime package supports date and time format and compare.
|
### 4. Datetime package supports date and time format and compare.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/datetime"
|
import "github.com/duke-git/lancet/datetime"
|
||||||
@@ -138,6 +153,7 @@ import "github.com/duke-git/lancet/datetime"
|
|||||||
- [AddDay](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#AddDay)
|
- [AddDay](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#AddDay)
|
||||||
- [AddHour](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#AddHour)
|
- [AddHour](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#AddHour)
|
||||||
- [AddMinute](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#AddMinute)
|
- [AddMinute](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#AddMinute)
|
||||||
|
- [AddYear](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#AddYear)
|
||||||
- [BeginOfMinute](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#BeginOfMinute)
|
- [BeginOfMinute](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#BeginOfMinute)
|
||||||
- [BeginOfHour](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#BeginOfHour)
|
- [BeginOfHour](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#BeginOfHour)
|
||||||
- [BeginOfDay](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#BeginOfDay)
|
- [BeginOfDay](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#BeginOfDay)
|
||||||
@@ -165,8 +181,12 @@ import "github.com/duke-git/lancet/datetime"
|
|||||||
- [ToFormat](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#ToFormat)
|
- [ToFormat](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#ToFormat)
|
||||||
- [ToFormatForTpl](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#ToFormatForTpl)
|
- [ToFormatForTpl](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#ToFormatForTpl)
|
||||||
- [ToIso8601](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#ToIso8601)
|
- [ToIso8601](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#ToIso8601)
|
||||||
|
- [IsLeapYear](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#IsLeapYear)
|
||||||
|
- [BetweenSeconds](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#BetweenSeconds)
|
||||||
|
- [DayOfYear](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#DayOfYear)
|
||||||
|
- [IsWeekend](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#IsWeekend)
|
||||||
|
|
||||||
### 4. Fileutil package implements some basic functions for file operations.
|
### 5. Fileutil package implements some basic functions for file operations.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/fileutil"
|
import "github.com/duke-git/lancet/fileutil"
|
||||||
@@ -189,8 +209,16 @@ import "github.com/duke-git/lancet/fileutil"
|
|||||||
- [ReadFileByLine](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#ReadFileByLine)
|
- [ReadFileByLine](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#ReadFileByLine)
|
||||||
- [Zip](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#Zip)
|
- [Zip](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#Zip)
|
||||||
- [UnZip](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#UnZip)
|
- [UnZip](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#UnZip)
|
||||||
|
- [CurrentPath](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#CurrentPath)
|
||||||
|
- [IsZipFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#IsZipFile)
|
||||||
|
- [FileSize](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#FileSize)
|
||||||
|
- [MTime](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#MTime)
|
||||||
|
- [Sha](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#Sha)
|
||||||
|
- [ReadCsvFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#ReadCsvFile)
|
||||||
|
- [WriteStringToFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#WriteStringToFile)
|
||||||
|
- [WriteBytesToFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil.md#WriteBytesToFile)
|
||||||
|
|
||||||
### 5. Formatter contains some functions for data formatting.
|
### 6. Formatter contains some functions for data formatting.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/formatter"
|
import "github.com/duke-git/lancet/formatter"
|
||||||
@@ -199,8 +227,14 @@ import "github.com/duke-git/lancet/formatter"
|
|||||||
#### Function list:
|
#### Function list:
|
||||||
|
|
||||||
- [Comma](https://github.com/duke-git/lancet/blob/v1/docs/formatter.md#Comma)
|
- [Comma](https://github.com/duke-git/lancet/blob/v1/docs/formatter.md#Comma)
|
||||||
|
- [Pretty](https://github.com/duke-git/lancet/blob/v1/docs/formatter.md#Pretty)
|
||||||
|
- [PrettyToWriter](https://github.com/duke-git/lancet/blob/v1/docs/formatter.md#PrettyToWriter)
|
||||||
|
- [DecimalBytes](https://github.com/duke-git/lancet/blob/v1/docs/formatter.md#DecimalBytes)
|
||||||
|
- [BinaryBytes](https://github.com/duke-git/lancet/blob/v1/docs/formatter.md#BinaryBytes)
|
||||||
|
- [ParseDecimalBytes](https://github.com/duke-git/lancet/blob/v1/docs/formatter.md#ParseDecimalBytes)
|
||||||
|
- [ParseBinaryBytes](https://github.com/duke-git/lancet/blob/v1/docs/formatter.md#ParseBinaryBytes)
|
||||||
|
|
||||||
### Function package can control the flow of function execution and support part of functional programming
|
### 7. Function package can control the flow of function execution and support part of functional programming
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/function"
|
import "github.com/duke-git/lancet/function"
|
||||||
@@ -218,7 +252,7 @@ import "github.com/duke-git/lancet/function"
|
|||||||
- [Schedule](https://github.com/duke-git/lancet/blob/v1/docs/function.md#Schedule)
|
- [Schedule](https://github.com/duke-git/lancet/blob/v1/docs/function.md#Schedule)
|
||||||
- [Watcher](https://github.com/duke-git/lancet/blob/v1/docs/function.md#Watcher)
|
- [Watcher](https://github.com/duke-git/lancet/blob/v1/docs/function.md#Watcher)
|
||||||
|
|
||||||
### 6. Mathutil package implements some functions for math calculation.
|
### 8. Mathutil package implements some functions for math calculation.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/mathutil"
|
import "github.com/duke-git/lancet/mathutil"
|
||||||
@@ -233,8 +267,16 @@ import "github.com/duke-git/lancet/mathutil"
|
|||||||
- [RoundToFloat](https://github.com/duke-git/lancet/blob/v1/docs/mathutil.md#RoundToFloat)
|
- [RoundToFloat](https://github.com/duke-git/lancet/blob/v1/docs/mathutil.md#RoundToFloat)
|
||||||
- [RoundToString](https://github.com/duke-git/lancet/blob/v1/docs/mathutil.md#RoundToString)
|
- [RoundToString](https://github.com/duke-git/lancet/blob/v1/docs/mathutil.md#RoundToString)
|
||||||
- [TruncRound](https://github.com/duke-git/lancet/blob/v1/docs/mathutil.md#TruncRound)
|
- [TruncRound](https://github.com/duke-git/lancet/blob/v1/docs/mathutil.md#TruncRound)
|
||||||
|
- [AngleToRadian](https://github.com/duke-git/lancet/blob/v1/docs/mathutil.md#AngleToRadian)
|
||||||
|
- [RadianToAngle](https://github.com/duke-git/lancet/blob/v1/docs/mathutil.md#RadianToAngle)
|
||||||
|
- [PointDistance](https://github.com/duke-git/lancet/blob/v1/docs/mathutil.md#PointDistance)
|
||||||
|
- [IsPrime](https://github.com/duke-git/lancet/blob/v1/docs/mathutil.md#IsPrime)
|
||||||
|
- [GCD](https://github.com/duke-git/lancet/blob/v1/docs/mathutil.md#GCD)
|
||||||
|
- [LCM](https://github.com/duke-git/lancet/blob/v1/docs/mathutil.md#LCM)
|
||||||
|
- [Cos](https://github.com/duke-git/lancet/blob/v1/docs/mathutil.md#Cos)
|
||||||
|
- [Sin](https://github.com/duke-git/lancet/blob/v1/docs/mathutil.md#Sin)
|
||||||
|
|
||||||
### 7. Netutil package contains functions to get net information and send http request.
|
### 9. Netutil package contains functions to get net information and send http request.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/netutil"
|
import "github.com/duke-git/lancet/netutil"
|
||||||
@@ -257,8 +299,12 @@ import "github.com/duke-git/lancet/netutil"
|
|||||||
- [HttpPut](https://github.com/duke-git/lancet/blob/v1/docs/netutil.md#HttpPut)
|
- [HttpPut](https://github.com/duke-git/lancet/blob/v1/docs/netutil.md#HttpPut)
|
||||||
- [HttpPatch](https://github.com/duke-git/lancet/blob/v1/docs/netutil.md#HttpPatch)
|
- [HttpPatch](https://github.com/duke-git/lancet/blob/v1/docs/netutil.md#HttpPatch)
|
||||||
- [ParseHttpResponse](https://github.com/duke-git/lancet/blob/v1/docs/netutil.md#ParseHttpResponse)
|
- [ParseHttpResponse](https://github.com/duke-git/lancet/blob/v1/docs/netutil.md#ParseHttpResponse)
|
||||||
|
- [UploadFile](https://github.com/duke-git/lancet/blob/v1/docs/netutil.md#UploadFile)
|
||||||
|
- [DownloadFile](https://github.com/duke-git/lancet/blob/v1/docs/netutil.md#DownloadFile)
|
||||||
|
- [IsPingConnected](https://github.com/duke-git/lancet/blob/v1/docs/netutil.md#IsPingConnected)
|
||||||
|
- [IsTelnetConnected](https://github.com/duke-git/lancet/blob/v1/docs/netutil.md#IsTelnetConnected)
|
||||||
|
|
||||||
### 8. Random package implements some basic functions to generate random int and string.
|
### 10. Random package implements some basic functions to generate random int and string.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/random"
|
import "github.com/duke-git/lancet/random"
|
||||||
@@ -275,7 +321,7 @@ import "github.com/duke-git/lancet/random"
|
|||||||
- [RandNumeralOrLetter](https://github.com/duke-git/lancet/blob/v1/docs/random.md#RandNumeralOrLetter)
|
- [RandNumeralOrLetter](https://github.com/duke-git/lancet/blob/v1/docs/random.md#RandNumeralOrLetter)
|
||||||
- [UUIdV4](https://github.com/duke-git/lancet/blob/v1/docs/random.md#UUIdV4)
|
- [UUIdV4](https://github.com/duke-git/lancet/blob/v1/docs/random.md#UUIdV4)
|
||||||
|
|
||||||
### 9. Retry package is for executing a function repeatedly until it was successful or canceled by the context.
|
### 11. Retry package is for executing a function repeatedly until it was successful or canceled by the context.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/retry"
|
import "github.com/duke-git/lancet/retry"
|
||||||
@@ -289,7 +335,7 @@ import "github.com/duke-git/lancet/retry"
|
|||||||
- [RetryDuration](https://github.com/duke-git/lancet/blob/v1/docs/retry.md#RetryDuration)
|
- [RetryDuration](https://github.com/duke-git/lancet/blob/v1/docs/retry.md#RetryDuration)
|
||||||
- [RetryTimes](https://github.com/duke-git/lancet/blob/v1/docs/retry.md#RetryTimes)
|
- [RetryTimes](https://github.com/duke-git/lancet/blob/v1/docs/retry.md#RetryTimes)
|
||||||
|
|
||||||
### 10. Slice contains some functions to manipulate slice.
|
### 12. Slice contains some functions to manipulate slice.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/slice"
|
import "github.com/duke-git/lancet/slice"
|
||||||
@@ -338,7 +384,7 @@ import "github.com/duke-git/lancet/slice"
|
|||||||
- [UpdateByIndex](https://github.com/duke-git/lancet/blob/v1/docs/slice.md#UpdateByIndex)
|
- [UpdateByIndex](https://github.com/duke-git/lancet/blob/v1/docs/slice.md#UpdateByIndex)
|
||||||
- [Without](https://github.com/duke-git/lancet/blob/v1/docs/slice.md#Without)
|
- [Without](https://github.com/duke-git/lancet/blob/v1/docs/slice.md#Without)
|
||||||
|
|
||||||
### 11. Strutil package contains some functions to manipulate string.
|
### 13. Strutil package contains some functions to manipulate string.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/strutil"
|
import "github.com/duke-git/lancet/strutil"
|
||||||
@@ -352,6 +398,8 @@ import "github.com/duke-git/lancet/strutil"
|
|||||||
- [BeforeLast](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#BeforeLast)
|
- [BeforeLast](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#BeforeLast)
|
||||||
- [CamelCase](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#CamelCase)
|
- [CamelCase](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#CamelCase)
|
||||||
- [Capitalize](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#Capitalize)
|
- [Capitalize](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#Capitalize)
|
||||||
|
- [ContainsAll](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#ContainsAll)
|
||||||
|
- [ContainsAny](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#ContainsAny)
|
||||||
- [IsString](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#IsString)
|
- [IsString](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#IsString)
|
||||||
- [KebabCase](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#KebabCase)
|
- [KebabCase](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#KebabCase)
|
||||||
- [UpperKebabCase](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#UpperKebabCase)
|
- [UpperKebabCase](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#UpperKebabCase)
|
||||||
@@ -368,8 +416,19 @@ import "github.com/duke-git/lancet/strutil"
|
|||||||
- [Unwrap](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#Unwrap)
|
- [Unwrap](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#Unwrap)
|
||||||
- [SplitWords](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#SplitWords)
|
- [SplitWords](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#SplitWords)
|
||||||
- [WordCount](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#WordCount)
|
- [WordCount](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#WordCount)
|
||||||
|
- [RemoveNonPrintable](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#RemoveNonPrintable)
|
||||||
|
- [StringToBytes](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#StringToBytes)
|
||||||
|
- [BytesToString](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#BytesToString)
|
||||||
|
- [IsBlank](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#IsBlank)
|
||||||
|
- [HasPrefixAny](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#HasPrefixAny)
|
||||||
|
- [HasSuffixAny](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#HasSuffixAny)
|
||||||
|
- [IndexOffset](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#IndexOffset)
|
||||||
|
- [ReplaceWithMap](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#ReplaceWithMap)
|
||||||
|
- [Trim](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#Trim)
|
||||||
|
- [SplitAndTrim](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#SplitAndTrim)
|
||||||
|
- [HideString](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#HideString)
|
||||||
|
|
||||||
### 12. System package contain some functions about os, runtime, shell command.
|
### 14. System package contain some functions about os, runtime, shell command.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/system"
|
import "github.com/duke-git/lancet/system"
|
||||||
@@ -387,7 +446,7 @@ import "github.com/duke-git/lancet/system"
|
|||||||
- [ExecCommand](https://github.com/duke-git/lancet/blob/v1/docs/system.md#ExecCommand)
|
- [ExecCommand](https://github.com/duke-git/lancet/blob/v1/docs/system.md#ExecCommand)
|
||||||
- [GetOsBits](https://github.com/duke-git/lancet/blob/v1/docs/system.md#GetOsBits)
|
- [GetOsBits](https://github.com/duke-git/lancet/blob/v1/docs/system.md#GetOsBits)
|
||||||
|
|
||||||
### 13. Validator package contains some functions for data validation.
|
### 15. Validator package contains some functions for data validation.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/validator"
|
import "github.com/duke-git/lancet/validator"
|
||||||
@@ -410,11 +469,14 @@ import "github.com/duke-git/lancet/validator"
|
|||||||
- [IsDns](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsDns)
|
- [IsDns](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsDns)
|
||||||
- [IsEmail](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsEmail)
|
- [IsEmail](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsEmail)
|
||||||
- [IsEmptyString](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsEmptyString)
|
- [IsEmptyString](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsEmptyString)
|
||||||
|
- [IsInt](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsInt)
|
||||||
|
- [IsFloat](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsFloat)
|
||||||
|
- [IsNumber](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsNumber)
|
||||||
|
- [IsIntStr](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsIntStr)
|
||||||
- [IsFloatStr](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsFloatStr)
|
- [IsFloatStr](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsFloatStr)
|
||||||
- [IsNumberStr](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsNumberStr)
|
- [IsNumberStr](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsNumberStr)
|
||||||
- [IsJSON](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsJSON)
|
- [IsJSON](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsJSON)
|
||||||
- [IsRegexMatch](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsRegexMatch)
|
- [IsRegexMatch](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsRegexMatch)
|
||||||
- [IsIntStr](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsIntStr)
|
|
||||||
- [IsIp](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsIp)
|
- [IsIp](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsIp)
|
||||||
- [IsIpV4](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsIpV4)
|
- [IsIpV4](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsIpV4)
|
||||||
- [IsIpV6](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsIpV6)
|
- [IsIpV6](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsIpV6)
|
||||||
@@ -423,6 +485,8 @@ import "github.com/duke-git/lancet/validator"
|
|||||||
- [IsWeakPassword](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsWeakPassword)
|
- [IsWeakPassword](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsWeakPassword)
|
||||||
- [IsZeroValue](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsZeroValue)
|
- [IsZeroValue](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsZeroValue)
|
||||||
- [IsGBK](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsGBK)
|
- [IsGBK](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsGBK)
|
||||||
|
- [IsASCII](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsASCII)
|
||||||
|
- [IsPrintable](https://github.com/duke-git/lancet/blob/v1/docs/validator.md#IsPrintable)
|
||||||
|
|
||||||
## How to Contribute
|
## How to Contribute
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<br/>
|
<br/>
|
||||||
|
|
||||||

|

|
||||||
[](https://github.com/duke-git/lancet/releases)
|
[](https://github.com/duke-git/lancet/releases)
|
||||||
[](https://pkg.go.dev/github.com/duke-git/lancet)
|
[](https://pkg.go.dev/github.com/duke-git/lancet)
|
||||||
[](https://goreportcard.com/report/github.com/duke-git/lancet)
|
[](https://goreportcard.com/report/github.com/duke-git/lancet)
|
||||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
## 特性
|
## 特性
|
||||||
|
|
||||||
- 👏 全面、高效、可复用
|
- 👏 全面、高效、可复用
|
||||||
- 💪 200+常用 go 工具函数,支持 string、slice、datetime、net、crypt...
|
- 💪 400+常用 go 工具函数,支持 string、slice、datetime、net、crypt...
|
||||||
- 💅 只依赖 go 标准库
|
- 💅 只依赖 go 标准库
|
||||||
- 🌍 所有导出函数单元测试覆盖率 100%
|
- 🌍 所有导出函数单元测试覆盖率 100%
|
||||||
|
|
||||||
@@ -62,7 +62,22 @@ func main() {
|
|||||||
|
|
||||||
## API 文档
|
## API 文档
|
||||||
|
|
||||||
### 1. convertor 转换器包支持一些常见的数据类型转换。
|
|
||||||
|
### 1. compare包提供几个轻量级的类型比较函数。
|
||||||
|
```go
|
||||||
|
import "github.com/duke-git/lancet/compare"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Function list:
|
||||||
|
|
||||||
|
- [Equal](https://github.com/duke-git/lancet/blob/v1/docs/compare_zh-CN.md#Equal)
|
||||||
|
- [EqualValue](https://github.com/duke-git/lancet/blob/v1/docs/compare_zh-CN.md#EqualValue)
|
||||||
|
- [LessThan](https://github.com/duke-git/lancet/blob/v1/docs/compare_zh-CN.md#LessThan)
|
||||||
|
- [GreaterThan](https://github.com/duke-git/lancet/blob/v1/docs/compare_zh-CN.md#GreaterThan)
|
||||||
|
- [LessOrEqual](https://github.com/duke-git/lancet/blob/v1/docs/compare_zh-CN.md#LessOrEqual)
|
||||||
|
- [GreaterOrEqual](https://github.com/duke-git/lancet/blob/v1/docs/compare_zh-CN.md#GreaterOrEqual)
|
||||||
|
|
||||||
|
### 2. convertor转换器包支持一些常见的数据类型转换。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/convertor"
|
import "github.com/duke-git/lancet/convertor"
|
||||||
@@ -85,7 +100,7 @@ import "github.com/duke-git/lancet/convertor"
|
|||||||
- [DeepClone](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#DeepClone)
|
- [DeepClone](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#DeepClone)
|
||||||
- [CopyProperties](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#CopyProperties)
|
- [CopyProperties](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#CopyProperties)
|
||||||
|
|
||||||
### 2. cryptor 加密包支持数据加密和解密,获取 md5,hash 值。支持 base64, md5, hmac, aes, des, rsa。
|
### 3. cryptor 加密包支持数据加密和解密,获取 md5,hash 值。支持 base64, md5, hmac, aes, des, rsa。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/cryptor"
|
import "github.com/duke-git/lancet/cryptor"
|
||||||
@@ -126,7 +141,7 @@ import "github.com/duke-git/lancet/cryptor"
|
|||||||
- [RsaEncrypt](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#RsaEncrypt)
|
- [RsaEncrypt](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#RsaEncrypt)
|
||||||
- [RsaDecrypt](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#RsaDecrypt)
|
- [RsaDecrypt](https://github.com/duke-git/lancet/blob/v1/docs/cryptor_zh-CN.md#RsaDecrypt)
|
||||||
|
|
||||||
### 3. datetime 日期时间处理包,格式化日期,比较日期。
|
### 4. datetime 日期时间处理包,格式化日期,比较日期。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/datetime"
|
import "github.com/duke-git/lancet/datetime"
|
||||||
@@ -137,6 +152,7 @@ import "github.com/duke-git/lancet/datetime"
|
|||||||
- [AddDay](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#AddDay)
|
- [AddDay](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#AddDay)
|
||||||
- [AddHour](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#AddHour)
|
- [AddHour](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#AddHour)
|
||||||
- [AddMinute](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#AddMinute)
|
- [AddMinute](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#AddMinute)
|
||||||
|
- [AddYear](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#AddYear)
|
||||||
- [BeginOfMinute](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#BeginOfMinute)
|
- [BeginOfMinute](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#BeginOfMinute)
|
||||||
- [BeginOfHour](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#BeginOfHour)
|
- [BeginOfHour](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#BeginOfHour)
|
||||||
- [BeginOfDay](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#BeginOfDay)
|
- [BeginOfDay](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#BeginOfDay)
|
||||||
@@ -164,8 +180,12 @@ import "github.com/duke-git/lancet/datetime"
|
|||||||
- [ToFormat](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#ToFormat)
|
- [ToFormat](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#ToFormat)
|
||||||
- [ToFormatForTpl](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#ToFormatForTpl)
|
- [ToFormatForTpl](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#ToFormatForTpl)
|
||||||
- [ToIso8601](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#ToIso8601)
|
- [ToIso8601](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#ToIso8601)
|
||||||
|
- [IsLeapYear](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#IsLeapYear)
|
||||||
|
- [BetweenSeconds](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#BetweenSeconds)
|
||||||
|
- [DayOfYear](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#DayOfYear)
|
||||||
|
- [IsWeekend](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#IsWeekend)
|
||||||
|
|
||||||
### 4. fileutil 包支持文件基本操作。
|
### 5. fileutil 包支持文件基本操作。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/fileutil"
|
import "github.com/duke-git/lancet/fileutil"
|
||||||
@@ -188,8 +208,16 @@ import "github.com/duke-git/lancet/fileutil"
|
|||||||
- [ReadFileByLine](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#ReadFileByLine)
|
- [ReadFileByLine](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#ReadFileByLine)
|
||||||
- [Zip](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#Zip)
|
- [Zip](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#Zip)
|
||||||
- [UnZip](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#UnZip)
|
- [UnZip](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#UnZip)
|
||||||
|
- [CurrentPath](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#CurrentPath)
|
||||||
|
- [IsZipFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#IsZipFile)
|
||||||
|
- [FileSize](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#FileSize)
|
||||||
|
- [MTime](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#MTime)
|
||||||
|
- [Sha](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#Sha)
|
||||||
|
- [ReadCsvFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#ReadCsvFile)
|
||||||
|
- [WriteStringToFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#WriteStringToFile)
|
||||||
|
- [WriteBytesToFile](https://github.com/duke-git/lancet/blob/v1/docs/fileutil_zh-CN.md#WriteBytesToFile)
|
||||||
|
|
||||||
### 5. formatter 格式化器包含一些数据格式化处理方法。
|
### 6. formatter 格式化器包含一些数据格式化处理方法。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/formatter"
|
import "github.com/duke-git/lancet/formatter"
|
||||||
@@ -198,8 +226,14 @@ import "github.com/duke-git/lancet/formatter"
|
|||||||
#### 函数列表:
|
#### 函数列表:
|
||||||
|
|
||||||
- [Comma](https://github.com/duke-git/lancet/blob/v1/docs/formatter_zh-CN.md#Comma)
|
- [Comma](https://github.com/duke-git/lancet/blob/v1/docs/formatter_zh-CN.md#Comma)
|
||||||
|
- [Pretty](https://github.com/duke-git/lancet/blob/v1/docs/formatter_zh-CN.md#Pretty)
|
||||||
|
- [PrettyToWriter](https://github.com/duke-git/lancet/blob/v1/docs/formatter_zh-CN.md#PrettyToWriter)
|
||||||
|
- [DecimalBytes](https://github.com/duke-git/lancet/blob/v1/docs/formatter_zh-CN.md#DecimalBytes)
|
||||||
|
- [BinaryBytes](https://github.com/duke-git/lancet/blob/v1/docs/formatter_zh-CN.md#BinaryBytes)
|
||||||
|
- [ParseDecimalBytes](https://github.com/duke-git/lancet/blob/v1/docs/formatter_zh-CN.md#ParseDecimalBytes)
|
||||||
|
- [ParseBinaryBytes](https://github.com/duke-git/lancet/blob/v1/docs/formatter_zh-CN.md#ParseBinaryBytes)
|
||||||
|
|
||||||
### function 函数包控制函数执行流程,包含部分函数式编程。
|
### 7. function 函数包控制函数执行流程,包含部分函数式编程。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/function"
|
import "github.com/duke-git/lancet/function"
|
||||||
@@ -217,7 +251,7 @@ import "github.com/duke-git/lancet/function"
|
|||||||
- [Schedule](https://github.com/duke-git/lancet/blob/v1/docs/function_zh-CN.md#Schedule)
|
- [Schedule](https://github.com/duke-git/lancet/blob/v1/docs/function_zh-CN.md#Schedule)
|
||||||
- [Watcher](https://github.com/duke-git/lancet/blob/v1/docs/function_zh-CN.md#Watcher)
|
- [Watcher](https://github.com/duke-git/lancet/blob/v1/docs/function_zh-CN.md#Watcher)
|
||||||
|
|
||||||
### 6. mathutil 包实现了一些数学计算的函数。
|
### 8. mathutil 包实现了一些数学计算的函数。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/mathutil"
|
import "github.com/duke-git/lancet/mathutil"
|
||||||
@@ -232,8 +266,16 @@ import "github.com/duke-git/lancet/mathutil"
|
|||||||
- [RoundToFloat](https://github.com/duke-git/lancet/blob/v1/docs/mathutil_zh-CN.md#RoundToFloat)
|
- [RoundToFloat](https://github.com/duke-git/lancet/blob/v1/docs/mathutil_zh-CN.md#RoundToFloat)
|
||||||
- [RoundToString](https://github.com/duke-git/lancet/blob/v1/docs/mathutil_zh-CN.md#RoundToString)
|
- [RoundToString](https://github.com/duke-git/lancet/blob/v1/docs/mathutil_zh-CN.md#RoundToString)
|
||||||
- [TruncRound](https://github.com/duke-git/lancet/blob/v1/docs/mathutil_zh-CN.md#TruncRound)
|
- [TruncRound](https://github.com/duke-git/lancet/blob/v1/docs/mathutil_zh-CN.md#TruncRound)
|
||||||
|
- [AngleToRadian](https://github.com/duke-git/lancet/blob/v1/docs/mathutil_zh-CN.md#AngleToRadian)
|
||||||
|
- [RadianToAngle](https://github.com/duke-git/lancet/blob/v1/docs/mathutil_zh-CN.md#RadianToAngle)
|
||||||
|
- [PointDistance](https://github.com/duke-git/lancet/blob/v1/docs/mathutil_zh-CN.md#PointDistance)
|
||||||
|
- [IsPrime](https://github.com/duke-git/lancet/blob/v1/docs/mathutil_zh-CN.md#IsPrime)
|
||||||
|
- [GCD](https://github.com/duke-git/lancet/blob/v1/docs/mathutil_zh-CN.md#GCD)
|
||||||
|
- [LCM](https://github.com/duke-git/lancet/blob/v1/docs/mathutil_zh-CN.md#LCM)
|
||||||
|
- [Cos](https://github.com/duke-git/lancet/blob/v1/docs/mathutil_zh-CN.md#Cos)
|
||||||
|
- [Sin](https://github.com/duke-git/lancet/blob/v1/docs/mathutil_zh-CN.md#Sin)
|
||||||
|
|
||||||
### 7. netutil 网络包支持获取 ip 地址,发送 http 请求。
|
### 9. netutil 网络包支持获取 ip 地址,发送 http 请求。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/netutil"
|
import "github.com/duke-git/lancet/netutil"
|
||||||
@@ -256,8 +298,12 @@ import "github.com/duke-git/lancet/netutil"
|
|||||||
- [HttpPut](https://github.com/duke-git/lancet/blob/v1/docs/netutil_zh-CN.md#HttpPut)
|
- [HttpPut](https://github.com/duke-git/lancet/blob/v1/docs/netutil_zh-CN.md#HttpPut)
|
||||||
- [HttpPatch](https://github.com/duke-git/lancet/blob/v1/docs/netutil_zh-CN.md#HttpPatch)
|
- [HttpPatch](https://github.com/duke-git/lancet/blob/v1/docs/netutil_zh-CN.md#HttpPatch)
|
||||||
- [ParseHttpResponse](https://github.com/duke-git/lancet/blob/v1/docs/netutil_zh-CN.md#ParseHttpResponse)
|
- [ParseHttpResponse](https://github.com/duke-git/lancet/blob/v1/docs/netutil_zh-CN.md#ParseHttpResponse)
|
||||||
|
- [UploadFile](https://github.com/duke-git/lancet/blob/v1/docs/netutil_zh-CN.md#UploadFile)
|
||||||
|
- [DownloadFile](https://github.com/duke-git/lancet/blob/v1/docs/netutil_zh-CN.md#DownloadFile)
|
||||||
|
- [IsPingConnected](https://github.com/duke-git/lancet/blob/v1/docs/netutil_zh-CN.md#IsPingConnected)
|
||||||
|
- [IsTelnetConnected](https://github.com/duke-git/lancet/blob/v1/docs/netutil_zh-CN.md#IsTelnetConnected)
|
||||||
|
|
||||||
### 8. random 随机数生成器包,可以生成随机[]bytes, int, string。
|
### 10. random 随机数生成器包,可以生成随机[]bytes, int, string。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/random"
|
import "github.com/duke-git/lancet/random"
|
||||||
@@ -274,7 +320,7 @@ import "github.com/duke-git/lancet/random"
|
|||||||
- [RandNumeralOrLetter](https://github.com/duke-git/lancet/blob/v1/docs/random_zh-CN.md#RandNumeralOrLetter)
|
- [RandNumeralOrLetter](https://github.com/duke-git/lancet/blob/v1/docs/random_zh-CN.md#RandNumeralOrLetter)
|
||||||
- [UUIdV4](https://github.com/duke-git/lancet/blob/v1/docs/random.md#UUIdV4)
|
- [UUIdV4](https://github.com/duke-git/lancet/blob/v1/docs/random.md#UUIdV4)
|
||||||
|
|
||||||
### 9. retry 重试执行函数直到函数运行成功或被 context cancel。
|
### 11. retry 重试执行函数直到函数运行成功或被 context cancel。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/retry"
|
import "github.com/duke-git/lancet/retry"
|
||||||
@@ -288,7 +334,7 @@ import "github.com/duke-git/lancet/retry"
|
|||||||
- [RetryDuration](https://github.com/duke-git/lancet/blob/v1/docs/retry_zh-CN.md#RetryDuration)
|
- [RetryDuration](https://github.com/duke-git/lancet/blob/v1/docs/retry_zh-CN.md#RetryDuration)
|
||||||
- [RetryTimes](https://github.com/duke-git/lancet/blob/v1/docs/retry_zh-CN.md#RetryTimes)
|
- [RetryTimes](https://github.com/duke-git/lancet/blob/v1/docs/retry_zh-CN.md#RetryTimes)
|
||||||
|
|
||||||
### 10. slice 包包含操作切片的方法集合。
|
### 12. slice 包包含操作切片的方法集合。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/slice"
|
import "github.com/duke-git/lancet/slice"
|
||||||
@@ -337,7 +383,7 @@ import "github.com/duke-git/lancet/slice"
|
|||||||
- [UpdateByIndex](https://github.com/duke-git/lancet/blob/v1/docs/slice_zh-CN.md#UpdateByIndex)
|
- [UpdateByIndex](https://github.com/duke-git/lancet/blob/v1/docs/slice_zh-CN.md#UpdateByIndex)
|
||||||
- [Without](https://github.com/duke-git/lancet/blob/v1/docs/slice_zh-CN.md#Without)
|
- [Without](https://github.com/duke-git/lancet/blob/v1/docs/slice_zh-CN.md#Without)
|
||||||
|
|
||||||
### 12. strutil 包含处理字符串的相关函数。
|
### 13. strutil 包含处理字符串的相关函数。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/strutil"
|
import "github.com/duke-git/lancet/strutil"
|
||||||
@@ -351,6 +397,8 @@ import "github.com/duke-git/lancet/strutil"
|
|||||||
- [BeforeLast](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#BeforeLast)
|
- [BeforeLast](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#BeforeLast)
|
||||||
- [CamelCase](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#CamelCase)
|
- [CamelCase](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#CamelCase)
|
||||||
- [Capitalize](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#Capitalize)
|
- [Capitalize](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#Capitalize)
|
||||||
|
- [ContainsAll](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#ContainsAll)
|
||||||
|
- [ContainsAny](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#ContainsAny)
|
||||||
- [IsString](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#IsString)
|
- [IsString](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#IsString)
|
||||||
- [KebabCase](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#KebabCase)
|
- [KebabCase](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#KebabCase)
|
||||||
- [UpperKebabCase](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#UpperKebabCase)
|
- [UpperKebabCase](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#UpperKebabCase)
|
||||||
@@ -367,8 +415,19 @@ import "github.com/duke-git/lancet/strutil"
|
|||||||
- [Unwrap](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#Unwrap)
|
- [Unwrap](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#Unwrap)
|
||||||
- [SplitWords](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#SplitWords)
|
- [SplitWords](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#SplitWords)
|
||||||
- [WordCount](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#WordCount)
|
- [WordCount](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#WordCount)
|
||||||
|
- [RemoveNonPrintable](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#RemoveNonPrintable)
|
||||||
|
- [StringToBytes](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#StringToBytes)
|
||||||
|
- [BytesToString](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#BytesToString)
|
||||||
|
- [IsBlank](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#IsBlank)
|
||||||
|
- [HasPrefixAny](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#HasPrefixAny)
|
||||||
|
- [HasSuffixAny](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#HasSuffixAny)
|
||||||
|
- [IndexOffset](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#IndexOffset)
|
||||||
|
- [ReplaceWithMap](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#ReplaceWithMap)
|
||||||
|
- [Trim](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#Trim)
|
||||||
|
- [SplitAndTrim](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#SplitAndTrim)
|
||||||
|
- [HideString](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#HideString)
|
||||||
|
|
||||||
### 13. system 包含 os, runtime, shell command 相关函数。
|
### 14. system 包含 os, runtime, shell command 相关函数。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/system"
|
import "github.com/duke-git/lancet/system"
|
||||||
@@ -386,7 +445,7 @@ import "github.com/duke-git/lancet/system"
|
|||||||
- [ExecCommand](https://github.com/duke-git/lancet/blob/v1/docs/system_zh-CN.md#ExecCommand)
|
- [ExecCommand](https://github.com/duke-git/lancet/blob/v1/docs/system_zh-CN.md#ExecCommand)
|
||||||
- [GetOsBits](https://github.com/duke-git/lancet/blob/v1/docs/system_zh-CN.md#GetOsBits)
|
- [GetOsBits](https://github.com/duke-git/lancet/blob/v1/docs/system_zh-CN.md#GetOsBits)
|
||||||
|
|
||||||
### 14. validator 验证器包,包含常用字符串格式验证函数。
|
### 15. validator 验证器包,包含常用字符串格式验证函数。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/validator"
|
import "github.com/duke-git/lancet/validator"
|
||||||
@@ -409,11 +468,14 @@ import "github.com/duke-git/lancet/validator"
|
|||||||
- [IsDns](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsDns)
|
- [IsDns](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsDns)
|
||||||
- [IsEmail](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsEmail)
|
- [IsEmail](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsEmail)
|
||||||
- [IsEmptyString](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsEmptyString)
|
- [IsEmptyString](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsEmptyString)
|
||||||
|
- [IsInt](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsInt)
|
||||||
|
- [IsFloat](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsFloat)
|
||||||
|
- [IsNumber](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsNumber)
|
||||||
|
- [IsIntStr](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsIntStr)
|
||||||
- [IsFloatStr](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsFloatStr)
|
- [IsFloatStr](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsFloatStr)
|
||||||
- [IsNumberStr](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsNumberStr)
|
- [IsNumberStr](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsNumberStr)
|
||||||
- [IsJSON](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsJSON)
|
- [IsJSON](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsJSON)
|
||||||
- [IsRegexMatch](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsRegexMatch)
|
- [IsRegexMatch](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsRegexMatch)
|
||||||
- [IsIntStr](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsIntStr)
|
|
||||||
- [IsIp](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsIp)
|
- [IsIp](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsIp)
|
||||||
- [IsIpV4](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsIpV4)
|
- [IsIpV4](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsIpV4)
|
||||||
- [IsIpV6](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsIpV6)
|
- [IsIpV6](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsIpV6)
|
||||||
@@ -422,6 +484,8 @@ import "github.com/duke-git/lancet/validator"
|
|||||||
- [IsWeakPassword](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsWeakPassword)
|
- [IsWeakPassword](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsWeakPassword)
|
||||||
- [IsZeroValue](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsZeroValue)
|
- [IsZeroValue](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsZeroValue)
|
||||||
- [IsGBK](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsGBK)
|
- [IsGBK](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsGBK)
|
||||||
|
- [IsASCII](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsASCII)
|
||||||
|
- [IsPrintable](https://github.com/duke-git/lancet/blob/v1/docs/validator_zh-CN.md#IsPrintable)
|
||||||
|
|
||||||
## 如何贡献代码
|
## 如何贡献代码
|
||||||
|
|
||||||
|
|||||||
58
compare/compare.go
Normal file
58
compare/compare.go
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
// Copyright 2023 dudaodong@gmail.com. All rights resulterved.
|
||||||
|
// Use of this source code is governed by MIT license
|
||||||
|
|
||||||
|
// Package compare provides a lightweight comparison function on interface{} type.
|
||||||
|
// reference: https://github.com/stretchr/testify
|
||||||
|
package compare
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/convertor"
|
||||||
|
)
|
||||||
|
|
||||||
|
// operator type
|
||||||
|
const (
|
||||||
|
equal = "eq"
|
||||||
|
lessThan = "lt"
|
||||||
|
greaterThan = "gt"
|
||||||
|
lessOrEqual = "le"
|
||||||
|
greaterOrEqual = "ge"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
timeType = reflect.TypeOf(time.Time{})
|
||||||
|
bytesType = reflect.TypeOf([]byte{})
|
||||||
|
)
|
||||||
|
|
||||||
|
// Equal checks if two values are equal or not. (check both type and value)
|
||||||
|
func Equal(left, right interface{}) bool {
|
||||||
|
return compareValue(equal, left, right)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EqualValue checks if two values are equal or not. (check value only)
|
||||||
|
func EqualValue(left, right interface{}) bool {
|
||||||
|
ls, rs := convertor.ToString(left), convertor.ToString(right)
|
||||||
|
return ls == rs
|
||||||
|
}
|
||||||
|
|
||||||
|
// LessThan checks if value `left` less than value `right`.
|
||||||
|
func LessThan(left, right interface{}) bool {
|
||||||
|
return compareValue(lessThan, left, right)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GreaterThan checks if value `left` greater than value `right`.
|
||||||
|
func GreaterThan(left, right interface{}) bool {
|
||||||
|
return compareValue(greaterThan, left, right)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LessOrEqual checks if value `left` less than or equal to value `right`.
|
||||||
|
func LessOrEqual(left, right interface{}) bool {
|
||||||
|
return compareValue(lessOrEqual, left, right)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GreaterOrEqual checks if value `left` greater than or equal to value `right`.
|
||||||
|
func GreaterOrEqual(left, right interface{}) bool {
|
||||||
|
return compareValue(greaterOrEqual, left, right)
|
||||||
|
}
|
||||||
170
compare/compare_example_test.go
Normal file
170
compare/compare_example_test.go
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
package compare
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExampleEqual() {
|
||||||
|
result1 := Equal(1, 1)
|
||||||
|
result2 := Equal("1", "1")
|
||||||
|
result3 := Equal([]int{1, 2, 3}, []int{1, 2, 3})
|
||||||
|
result4 := Equal(map[int]string{1: "a", 2: "b"}, map[int]string{1: "a", 2: "b"})
|
||||||
|
|
||||||
|
result5 := Equal(1, "1")
|
||||||
|
result6 := Equal(1, int64(1))
|
||||||
|
result7 := Equal([]int{1, 2}, []int{1, 2, 3})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
fmt.Println(result6)
|
||||||
|
fmt.Println(result7)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleEqualValue() {
|
||||||
|
result1 := EqualValue(1, 1)
|
||||||
|
result2 := EqualValue(int(1), int64(1))
|
||||||
|
result3 := EqualValue(1, "1")
|
||||||
|
result4 := EqualValue(1, "2")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleLessThan() {
|
||||||
|
result1 := LessThan(1, 2)
|
||||||
|
result2 := LessThan(1.1, 2.2)
|
||||||
|
result3 := LessThan("a", "b")
|
||||||
|
|
||||||
|
time1 := time.Now()
|
||||||
|
time2 := time1.Add(time.Second)
|
||||||
|
result4 := LessThan(time1, time2)
|
||||||
|
|
||||||
|
result5 := LessThan(2, 1)
|
||||||
|
result6 := LessThan(1, int64(2))
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
fmt.Println(result6)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleGreaterThan() {
|
||||||
|
result1 := GreaterThan(2, 1)
|
||||||
|
result2 := GreaterThan(2.2, 1.1)
|
||||||
|
result3 := GreaterThan("b", "a")
|
||||||
|
|
||||||
|
time1 := time.Now()
|
||||||
|
time2 := time1.Add(time.Second)
|
||||||
|
result4 := GreaterThan(time2, time1)
|
||||||
|
|
||||||
|
result5 := GreaterThan(1, 2)
|
||||||
|
result6 := GreaterThan(int64(2), 1)
|
||||||
|
result7 := GreaterThan("b", "c")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
fmt.Println(result6)
|
||||||
|
fmt.Println(result7)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleLessOrEqual() {
|
||||||
|
result1 := LessOrEqual(1, 1)
|
||||||
|
result2 := LessOrEqual(1.1, 2.2)
|
||||||
|
result3 := LessOrEqual("a", "b")
|
||||||
|
|
||||||
|
time1 := time.Now()
|
||||||
|
time2 := time1.Add(time.Second)
|
||||||
|
result4 := LessOrEqual(time1, time2)
|
||||||
|
|
||||||
|
result5 := LessOrEqual(2, 1)
|
||||||
|
result6 := LessOrEqual(1, int64(2))
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
fmt.Println(result6)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleGreaterOrEqual() {
|
||||||
|
result1 := GreaterOrEqual(1, 1)
|
||||||
|
result2 := GreaterOrEqual(2.2, 1.1)
|
||||||
|
result3 := GreaterOrEqual("b", "b")
|
||||||
|
|
||||||
|
time1 := time.Now()
|
||||||
|
time2 := time1.Add(time.Second)
|
||||||
|
result4 := GreaterOrEqual(time2, time1)
|
||||||
|
|
||||||
|
result5 := GreaterOrEqual(1, 2)
|
||||||
|
result6 := GreaterOrEqual(int64(2), 1)
|
||||||
|
result7 := GreaterOrEqual("b", "c")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
fmt.Println(result6)
|
||||||
|
fmt.Println(result7)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
}
|
||||||
323
compare/compare_internal.go
Normal file
323
compare/compare_internal.go
Normal file
@@ -0,0 +1,323 @@
|
|||||||
|
package compare
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"reflect"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/convertor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func compareValue(operator string, left, right interface{}) bool {
|
||||||
|
leftType, rightType := reflect.TypeOf(left), reflect.TypeOf(right)
|
||||||
|
|
||||||
|
if leftType.Kind() != rightType.Kind() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
switch leftType.Kind() {
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||||
|
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
||||||
|
reflect.Float32, reflect.Float64, reflect.Bool, reflect.String:
|
||||||
|
return compareBasicValue(operator, left, right)
|
||||||
|
|
||||||
|
case reflect.Struct, reflect.Slice, reflect.Map:
|
||||||
|
return compareRefValue(operator, left, right, leftType.Kind())
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func compareRefValue(operator string, leftObj, rightObj interface{}, kind reflect.Kind) bool {
|
||||||
|
leftVal, rightVal := reflect.ValueOf(leftObj), reflect.ValueOf(rightObj)
|
||||||
|
|
||||||
|
switch kind {
|
||||||
|
case reflect.Struct:
|
||||||
|
|
||||||
|
// compare time
|
||||||
|
if leftVal.CanConvert(timeType) {
|
||||||
|
timeObj1, ok := leftObj.(time.Time)
|
||||||
|
if !ok {
|
||||||
|
timeObj1 = leftVal.Convert(timeType).Interface().(time.Time)
|
||||||
|
}
|
||||||
|
|
||||||
|
timeObj2, ok := rightObj.(time.Time)
|
||||||
|
if !ok {
|
||||||
|
timeObj2 = rightVal.Convert(timeType).Interface().(time.Time)
|
||||||
|
}
|
||||||
|
|
||||||
|
return compareBasicValue(operator, timeObj1.UnixNano(), timeObj2.UnixNano())
|
||||||
|
}
|
||||||
|
|
||||||
|
// for other struct type, only process equal operator
|
||||||
|
switch operator {
|
||||||
|
case equal:
|
||||||
|
return objectsAreEqualValues(leftObj, rightObj)
|
||||||
|
}
|
||||||
|
|
||||||
|
case reflect.Slice:
|
||||||
|
// compare []byte
|
||||||
|
if leftVal.CanConvert(bytesType) {
|
||||||
|
bytesObj1, ok := leftObj.([]byte)
|
||||||
|
if !ok {
|
||||||
|
bytesObj1 = leftVal.Convert(bytesType).Interface().([]byte)
|
||||||
|
}
|
||||||
|
bytesObj2, ok := rightObj.([]byte)
|
||||||
|
if !ok {
|
||||||
|
bytesObj2 = rightVal.Convert(bytesType).Interface().([]byte)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch operator {
|
||||||
|
case equal:
|
||||||
|
if bytes.Compare(bytesObj1, bytesObj2) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case lessThan:
|
||||||
|
if bytes.Compare(bytesObj1, bytesObj2) == -1 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case greaterThan:
|
||||||
|
if bytes.Compare(bytesObj1, bytesObj2) == 1 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case lessOrEqual:
|
||||||
|
if bytes.Compare(bytesObj1, bytesObj2) <= 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case greaterOrEqual:
|
||||||
|
if bytes.Compare(bytesObj1, bytesObj2) >= 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// for other type slice, only process equal operator
|
||||||
|
switch operator {
|
||||||
|
case equal:
|
||||||
|
return reflect.DeepEqual(leftObj, rightObj)
|
||||||
|
}
|
||||||
|
|
||||||
|
case reflect.Map:
|
||||||
|
// only process equal operator
|
||||||
|
switch operator {
|
||||||
|
case equal:
|
||||||
|
return reflect.DeepEqual(leftObj, rightObj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func objectsAreEqualValues(expected, actual interface{}) bool {
|
||||||
|
if objectsAreEqual(expected, actual) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
actualType := reflect.TypeOf(actual)
|
||||||
|
if actualType == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
expectedValue := reflect.ValueOf(expected)
|
||||||
|
if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) {
|
||||||
|
// Attempt comparison after type conversion
|
||||||
|
return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func objectsAreEqual(expected, actual interface{}) bool {
|
||||||
|
if expected == nil || actual == nil {
|
||||||
|
return expected == actual
|
||||||
|
}
|
||||||
|
|
||||||
|
exp, ok := expected.([]byte)
|
||||||
|
if !ok {
|
||||||
|
return reflect.DeepEqual(expected, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
act, ok := actual.([]byte)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if exp == nil || act == nil {
|
||||||
|
return exp == nil && act == nil
|
||||||
|
}
|
||||||
|
return bytes.Equal(exp, act)
|
||||||
|
}
|
||||||
|
|
||||||
|
// compareBasic compare basic value: integer, float, string, bool
|
||||||
|
func compareBasicValue(operator string, leftValue, rightValue interface{}) bool {
|
||||||
|
if leftValue == nil && rightValue == nil && operator == equal {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
switch leftVal := leftValue.(type) {
|
||||||
|
case json.Number:
|
||||||
|
if left, err := leftVal.Float64(); err == nil {
|
||||||
|
switch rightVal := rightValue.(type) {
|
||||||
|
case json.Number:
|
||||||
|
if right, err := rightVal.Float64(); err == nil {
|
||||||
|
switch operator {
|
||||||
|
case equal:
|
||||||
|
if left == right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case lessThan:
|
||||||
|
if left < right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case greaterThan:
|
||||||
|
if left > right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case lessOrEqual:
|
||||||
|
if left <= right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case greaterOrEqual:
|
||||||
|
if left >= right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
case float32, float64, int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64:
|
||||||
|
right, err := convertor.ToFloat(rightValue)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
switch operator {
|
||||||
|
case equal:
|
||||||
|
if left == right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case lessThan:
|
||||||
|
if left < right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case greaterThan:
|
||||||
|
if left > right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case lessOrEqual:
|
||||||
|
if left <= right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case greaterOrEqual:
|
||||||
|
if left >= right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
case float32, float64, int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64:
|
||||||
|
left, err := convertor.ToFloat(leftValue)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
switch rightVal := rightValue.(type) {
|
||||||
|
case json.Number:
|
||||||
|
if right, err := rightVal.Float64(); err == nil {
|
||||||
|
switch operator {
|
||||||
|
case equal:
|
||||||
|
if left == right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case lessThan:
|
||||||
|
if left < right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case greaterThan:
|
||||||
|
if left > right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case lessOrEqual:
|
||||||
|
if left <= right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case greaterOrEqual:
|
||||||
|
if left >= right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case float32, float64, int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64:
|
||||||
|
right, err := convertor.ToFloat(rightValue)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
switch operator {
|
||||||
|
case equal:
|
||||||
|
if left == right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case lessThan:
|
||||||
|
if left < right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case greaterThan:
|
||||||
|
if left > right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case lessOrEqual:
|
||||||
|
if left <= right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case greaterOrEqual:
|
||||||
|
if left >= right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case string:
|
||||||
|
left := leftVal
|
||||||
|
switch right := rightValue.(type) {
|
||||||
|
case string:
|
||||||
|
switch operator {
|
||||||
|
case equal:
|
||||||
|
if left == right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case lessThan:
|
||||||
|
if left < right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case greaterThan:
|
||||||
|
if left > right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case lessOrEqual:
|
||||||
|
if left <= right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case greaterOrEqual:
|
||||||
|
if left >= right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case bool:
|
||||||
|
left := leftVal
|
||||||
|
switch right := rightValue.(type) {
|
||||||
|
case bool:
|
||||||
|
switch operator {
|
||||||
|
case equal:
|
||||||
|
if left == right {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
134
compare/compare_test.go
Normal file
134
compare/compare_test.go
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
package compare
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEqual(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestEqual")
|
||||||
|
|
||||||
|
assert.Equal(true, Equal(1, 1))
|
||||||
|
assert.Equal(true, Equal(int64(1), int64(1)))
|
||||||
|
assert.Equal(true, Equal("a", "a"))
|
||||||
|
assert.Equal(true, Equal(true, true))
|
||||||
|
assert.Equal(true, Equal([]int{1, 2, 3}, []int{1, 2, 3}))
|
||||||
|
assert.Equal(true, Equal(map[int]string{1: "a", 2: "b"}, map[int]string{1: "a", 2: "b"}))
|
||||||
|
|
||||||
|
assert.Equal(false, Equal(1, 2))
|
||||||
|
assert.Equal(false, Equal(1, int64(1)))
|
||||||
|
assert.Equal(false, Equal("a", "b"))
|
||||||
|
assert.Equal(false, Equal(true, false))
|
||||||
|
assert.Equal(false, Equal([]int{1, 2}, []int{1, 2, 3}))
|
||||||
|
assert.Equal(false, Equal(map[int]string{1: "a", 2: "b"}, map[int]string{1: "a"}))
|
||||||
|
|
||||||
|
time1 := time.Now()
|
||||||
|
time2 := time1.Add(time.Second)
|
||||||
|
time3 := time1.Add(time.Second)
|
||||||
|
|
||||||
|
assert.Equal(false, Equal(time1, time2))
|
||||||
|
assert.Equal(true, Equal(time2, time3))
|
||||||
|
|
||||||
|
st1 := struct {
|
||||||
|
A string
|
||||||
|
B string
|
||||||
|
}{
|
||||||
|
A: "a",
|
||||||
|
B: "b",
|
||||||
|
}
|
||||||
|
|
||||||
|
st2 := struct {
|
||||||
|
A string
|
||||||
|
B string
|
||||||
|
}{
|
||||||
|
A: "a",
|
||||||
|
B: "b",
|
||||||
|
}
|
||||||
|
|
||||||
|
st3 := struct {
|
||||||
|
A string
|
||||||
|
B string
|
||||||
|
}{
|
||||||
|
A: "a1",
|
||||||
|
B: "b",
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(true, Equal(st1, st2))
|
||||||
|
assert.Equal(false, Equal(st1, st3))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEqualValue(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestEqualValue")
|
||||||
|
|
||||||
|
assert.Equal(true, EqualValue(1, 1))
|
||||||
|
assert.Equal(true, EqualValue(int(1), int64(1)))
|
||||||
|
assert.Equal(true, EqualValue(1, "1"))
|
||||||
|
|
||||||
|
assert.Equal(false, EqualValue(1, "2"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLessThan(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestLessThan")
|
||||||
|
|
||||||
|
assert.Equal(true, LessThan(1, 2))
|
||||||
|
assert.Equal(true, LessThan(1.1, 2.2))
|
||||||
|
assert.Equal(true, LessThan("a", "b"))
|
||||||
|
|
||||||
|
time1 := time.Now()
|
||||||
|
time2 := time1.Add(time.Second)
|
||||||
|
assert.Equal(true, LessThan(time1, time2))
|
||||||
|
|
||||||
|
assert.Equal(false, LessThan(1, 1))
|
||||||
|
assert.Equal(false, LessThan(1, int64(1)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGreaterThan(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestGreaterThan")
|
||||||
|
|
||||||
|
assert.Equal(true, GreaterThan(2, 1))
|
||||||
|
assert.Equal(true, GreaterThan(2.2, 1.1))
|
||||||
|
assert.Equal(true, GreaterThan("b", "a"))
|
||||||
|
|
||||||
|
time1 := time.Now()
|
||||||
|
time2 := time1.Add(time.Second)
|
||||||
|
assert.Equal(true, GreaterThan(time2, time1))
|
||||||
|
|
||||||
|
assert.Equal(false, GreaterThan(1, 2))
|
||||||
|
assert.Equal(false, GreaterThan(int64(2), 1))
|
||||||
|
assert.Equal(false, GreaterThan("b", "c"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLessOrEqual(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestLessOrEqual")
|
||||||
|
|
||||||
|
assert.Equal(true, LessOrEqual(1, 2))
|
||||||
|
assert.Equal(true, LessOrEqual(1, 1))
|
||||||
|
assert.Equal(true, LessOrEqual(1.1, 2.2))
|
||||||
|
assert.Equal(true, LessOrEqual("a", "b"))
|
||||||
|
|
||||||
|
time1 := time.Now()
|
||||||
|
time2 := time1.Add(time.Second)
|
||||||
|
assert.Equal(true, LessOrEqual(time1, time2))
|
||||||
|
|
||||||
|
assert.Equal(false, LessOrEqual(2, 1))
|
||||||
|
assert.Equal(false, LessOrEqual(1, int64(2)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGreaterOrEqual(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestGreaterThan")
|
||||||
|
|
||||||
|
assert.Equal(true, GreaterOrEqual(2, 1))
|
||||||
|
assert.Equal(true, GreaterOrEqual(1, 1))
|
||||||
|
assert.Equal(true, GreaterOrEqual(2.2, 1.1))
|
||||||
|
assert.Equal(true, GreaterOrEqual("b", "b"))
|
||||||
|
|
||||||
|
time1 := time.Now()
|
||||||
|
time2 := time1.Add(time.Second)
|
||||||
|
assert.Equal(true, GreaterOrEqual(time2, time1))
|
||||||
|
|
||||||
|
assert.Equal(false, GreaterOrEqual(1, 2))
|
||||||
|
assert.Equal(false, GreaterOrEqual(int64(2), 1))
|
||||||
|
assert.Equal(false, GreaterOrEqual("b", "c"))
|
||||||
|
}
|
||||||
@@ -278,44 +278,99 @@ func DeepClone(src interface{}) interface{} {
|
|||||||
return result.Interface()
|
return result.Interface()
|
||||||
}
|
}
|
||||||
|
|
||||||
// CopyProperties copies each field from the source into the destination. It recursively copies struct pointers and interfaces that contain struct pointers.
|
// // CopyProperties copies each field from the source into the destination. It recursively copies struct pointers and interfaces that contain struct pointers.
|
||||||
func CopyProperties(dst, src interface{}) (err error) {
|
// func CopyProperties(dst, src interface{}) (err error) {
|
||||||
defer func() {
|
// defer func() {
|
||||||
if e := recover(); e != nil {
|
// if e := recover(); e != nil {
|
||||||
err = errors.New(fmt.Sprintf("%v", e))
|
// err = errors.New(fmt.Sprintf("%v", e))
|
||||||
}
|
// }
|
||||||
}()
|
// }()
|
||||||
|
|
||||||
dstType, dstValue := reflect.TypeOf(dst), reflect.ValueOf(dst)
|
// dstType, dstValue := reflect.TypeOf(dst), reflect.ValueOf(dst)
|
||||||
srcType, srcValue := reflect.TypeOf(src), reflect.ValueOf(src)
|
// srcType, srcValue := reflect.TypeOf(src), reflect.ValueOf(src)
|
||||||
|
|
||||||
|
// if dstType.Kind() != reflect.Ptr || dstType.Elem().Kind() != reflect.Struct {
|
||||||
|
// return errors.New("CopyProperties: param dst should be struct pointer")
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if srcType.Kind() == reflect.Ptr {
|
||||||
|
// srcType, srcValue = srcType.Elem(), srcValue.Elem()
|
||||||
|
// }
|
||||||
|
// if srcType.Kind() != reflect.Struct {
|
||||||
|
// return errors.New("CopyProperties: param src should be a struct or struct pointer")
|
||||||
|
// }
|
||||||
|
|
||||||
|
// dstType, dstValue = dstType.Elem(), dstValue.Elem()
|
||||||
|
|
||||||
|
// propertyNums := dstType.NumField()
|
||||||
|
|
||||||
|
// for i := 0; i < propertyNums; i++ {
|
||||||
|
// property := dstType.Field(i)
|
||||||
|
// propertyValue := srcValue.FieldByName(property.Name)
|
||||||
|
|
||||||
|
// if !propertyValue.IsValid() || property.Type != propertyValue.Type() {
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if dstValue.Field(i).CanSet() {
|
||||||
|
// dstValue.Field(i).Set(propertyValue)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return nil
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
func CopyProperties(dst, src interface{}) error {
|
||||||
|
dstType, srcType := reflect.TypeOf(dst), reflect.TypeOf(src)
|
||||||
|
|
||||||
if dstType.Kind() != reflect.Ptr || dstType.Elem().Kind() != reflect.Struct {
|
if dstType.Kind() != reflect.Ptr || dstType.Elem().Kind() != reflect.Struct {
|
||||||
return errors.New("CopyProperties: param dst should be struct pointer")
|
return errors.New("CopyProperties: parameter dst should be struct pointer")
|
||||||
}
|
}
|
||||||
|
|
||||||
if srcType.Kind() == reflect.Ptr {
|
if srcType.Kind() == reflect.Ptr {
|
||||||
srcType, srcValue = srcType.Elem(), srcValue.Elem()
|
srcType = srcType.Elem()
|
||||||
}
|
}
|
||||||
if srcType.Kind() != reflect.Struct {
|
if srcType.Kind() != reflect.Struct {
|
||||||
return errors.New("CopyProperties: param src should be a struct or struct pointer")
|
return errors.New("CopyProperties: parameter src should be a struct or struct pointer")
|
||||||
}
|
}
|
||||||
|
|
||||||
dstType, dstValue = dstType.Elem(), dstValue.Elem()
|
bytes, err := json.Marshal(src)
|
||||||
|
if err != nil {
|
||||||
propertyNums := dstType.NumField()
|
return fmt.Errorf("CopyProperties: unable to marshal src: %s", err)
|
||||||
|
}
|
||||||
for i := 0; i < propertyNums; i++ {
|
err = json.Unmarshal(bytes, dst)
|
||||||
property := dstType.Field(i)
|
if err != nil {
|
||||||
propertyValue := srcValue.FieldByName(property.Name)
|
return fmt.Errorf("CopyProperties: unable to unmarshal into dst: %s", err)
|
||||||
|
|
||||||
if !propertyValue.IsValid() || property.Type != propertyValue.Type() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if dstValue.Field(i).CanSet() {
|
|
||||||
dstValue.Field(i).Set(propertyValue)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToInterface converts reflect value to its interface type.
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -262,49 +262,80 @@ func TestDeepClone(t *testing.T) {
|
|||||||
func TestCopyProperties(t *testing.T) {
|
func TestCopyProperties(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestCopyProperties")
|
assert := internal.NewAssert(t, "TestCopyProperties")
|
||||||
|
|
||||||
type Address struct {
|
type Disk struct {
|
||||||
Country string
|
Name string `json:"name"`
|
||||||
ZipCode string
|
Total string `json:"total"`
|
||||||
|
Used string `json:"used"`
|
||||||
|
Percent float64 `json:"percent"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type User struct {
|
type DiskVO struct {
|
||||||
Name string
|
Name string `json:"name"`
|
||||||
Age int
|
Total string `json:"total"`
|
||||||
Role string
|
Used string `json:"used"`
|
||||||
Addr Address
|
Percent float64 `json:"percent"`
|
||||||
Hobbys []string
|
|
||||||
salary int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Employee struct {
|
type Indicator struct {
|
||||||
Name string
|
Id string `json:"id"`
|
||||||
Age int
|
Ip string `json:"ip"`
|
||||||
Role string
|
UpTime string `json:"upTime"`
|
||||||
Addr Address
|
LoadAvg string `json:"loadAvg"`
|
||||||
Hobbys []string
|
Cpu int `json:"cpu"`
|
||||||
salary int
|
Disk []Disk `json:"disk"`
|
||||||
|
Stop chan bool `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
user := User{Name: "user001", Age: 10, Role: "Admin", Addr: Address{Country: "CN", ZipCode: "001"}, Hobbys: []string{"a", "b"}, salary: 1000}
|
type IndicatorVO struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Ip string `json:"ip"`
|
||||||
|
UpTime string `json:"upTime"`
|
||||||
|
LoadAvg string `json:"loadAvg"`
|
||||||
|
Cpu int64 `json:"cpu"`
|
||||||
|
Disk []DiskVO `json:"disk"`
|
||||||
|
}
|
||||||
|
|
||||||
employee1 := Employee{}
|
indicator := &Indicator{Id: "001", Ip: "127.0.0.1", Cpu: 1, Disk: []Disk{
|
||||||
|
{Name: "disk-001", Total: "100", Used: "1", Percent: 10},
|
||||||
|
{Name: "disk-002", Total: "200", Used: "1", Percent: 20},
|
||||||
|
{Name: "disk-003", Total: "300", Used: "1", Percent: 30},
|
||||||
|
}}
|
||||||
|
|
||||||
err := CopyProperties(&employee1, &user)
|
indicatorVO := IndicatorVO{}
|
||||||
|
|
||||||
|
err := CopyProperties(&indicatorVO, indicator)
|
||||||
|
|
||||||
assert.IsNil(err)
|
assert.IsNil(err)
|
||||||
assert.Equal("user001", employee1.Name)
|
assert.Equal("001", indicatorVO.Id)
|
||||||
assert.Equal("Admin", employee1.Role)
|
assert.Equal("127.0.0.1", indicatorVO.Ip)
|
||||||
assert.Equal("CN", employee1.Addr.Country)
|
assert.Equal(3, len(indicatorVO.Disk))
|
||||||
assert.Equal(0, employee1.salary)
|
}
|
||||||
|
|
||||||
employee2 := Employee{Name: "employee001", Age: 20, Role: "User",
|
func TestToInterface(t *testing.T) {
|
||||||
Addr: Address{Country: "UK", ZipCode: "002"}, salary: 500}
|
assert := internal.NewAssert(t, "TestToInterface")
|
||||||
|
|
||||||
err = CopyProperties(&employee2, &user)
|
cases := []reflect.Value{
|
||||||
|
reflect.ValueOf("abc"),
|
||||||
assert.IsNil(err)
|
reflect.ValueOf(int(0)), reflect.ValueOf(int8(1)), reflect.ValueOf(int16(-1)), reflect.ValueOf(int32(123)), reflect.ValueOf(int64(123)),
|
||||||
assert.Equal("user001", employee2.Name)
|
reflect.ValueOf(uint(123)), reflect.ValueOf(uint8(123)), reflect.ValueOf(uint16(123)), reflect.ValueOf(uint32(123)), reflect.ValueOf(uint64(123)),
|
||||||
assert.Equal("Admin", employee2.Role)
|
reflect.ValueOf(float64(12.3)), reflect.ValueOf(float32(12.3)),
|
||||||
assert.Equal("CN", employee2.Addr.Country)
|
reflect.ValueOf(true), reflect.ValueOf(false),
|
||||||
assert.Equal(500, employee2.salary)
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,24 +4,24 @@
|
|||||||
// Package datetime implements some functions to format date and time.
|
// Package datetime implements some functions to format date and time.
|
||||||
// Note:
|
// Note:
|
||||||
// 1. `format` param in FormatTimeToStr function should be as flow:
|
// 1. `format` param in FormatTimeToStr function should be as flow:
|
||||||
//"yyyy-mm-dd hh:mm:ss"
|
// "yyyy-mm-dd hh:mm:ss"
|
||||||
//"yyyy-mm-dd hh:mm"
|
// "yyyy-mm-dd hh:mm"
|
||||||
//"yyyy-mm-dd hh"
|
// "yyyy-mm-dd hh"
|
||||||
//"yyyy-mm-dd"
|
// "yyyy-mm-dd"
|
||||||
//"yyyy-mm"
|
// "yyyy-mm"
|
||||||
//"mm-dd"
|
// "mm-dd"
|
||||||
//"dd-mm-yy hh:mm:ss"
|
// "dd-mm-yy hh:mm:ss"
|
||||||
//"yyyy/mm/dd hh:mm:ss"
|
// "yyyy/mm/dd hh:mm:ss"
|
||||||
//"yyyy/mm/dd hh:mm"
|
// "yyyy/mm/dd hh:mm"
|
||||||
//"yyyy/mm/dd hh"
|
// "yyyy/mm/dd hh"
|
||||||
//"yyyy/mm/dd"
|
// "yyyy/mm/dd"
|
||||||
//"yyyy/mm"
|
// "yyyy/mm"
|
||||||
//"mm/dd"
|
// "mm/dd"
|
||||||
//"dd/mm/yy hh:mm:ss"
|
// "dd/mm/yy hh:mm:ss"
|
||||||
//"yyyy"
|
// "yyyy"
|
||||||
//"mm"
|
// "mm"
|
||||||
//"hh:mm:ss"
|
// "hh:mm:ss"
|
||||||
//"mm:ss"
|
// "mm:ss"
|
||||||
package datetime
|
package datetime
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -35,7 +35,7 @@ func init() {
|
|||||||
timeFormat = map[string]string{
|
timeFormat = map[string]string{
|
||||||
"yyyy-mm-dd hh:mm:ss": "2006-01-02 15:04:05",
|
"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: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-dd": "2006-01-02",
|
||||||
"yyyy-mm": "2006-01",
|
"yyyy-mm": "2006-01",
|
||||||
"mm-dd": "01-02",
|
"mm-dd": "01-02",
|
||||||
@@ -69,6 +69,11 @@ func AddDay(t time.Time, day int64) time.Time {
|
|||||||
return t.Add(24 * time.Hour * time.Duration(day))
|
return t.Add(24 * time.Hour * time.Duration(day))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddYear add or sub year to the time.
|
||||||
|
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
|
// GetNowDate return format yyyy-mm-dd of current date
|
||||||
func GetNowDate() string {
|
func GetNowDate() string {
|
||||||
return time.Now().Format("2006-01-02")
|
return time.Now().Format("2006-01-02")
|
||||||
@@ -180,3 +185,28 @@ func BeginOfYear(t time.Time) time.Time {
|
|||||||
func EndOfYear(t time.Time) time.Time {
|
func EndOfYear(t time.Time) time.Time {
|
||||||
return BeginOfYear(t).AddDate(1, 0, 0).Add(-time.Nanosecond)
|
return BeginOfYear(t).AddDate(1, 0, 0).Add(-time.Nanosecond)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsLeapYear check if param year is leap year or not.
|
||||||
|
func IsLeapYear(year int) bool {
|
||||||
|
return year%4 == 0 && (year%100 != 0 || year%400 == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BetweenSeconds returns the number of seconds between two times.
|
||||||
|
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.
|
||||||
|
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.
|
||||||
|
func IsWeekend(t time.Time) bool {
|
||||||
|
return time.Saturday == t.Weekday() || time.Sunday == t.Weekday()
|
||||||
|
}
|
||||||
|
|||||||
@@ -46,6 +46,19 @@ func TestAddMinute(t *testing.T) {
|
|||||||
assert.Equal(float64(-2), diff2.Minutes())
|
assert.Equal(float64(-2), diff2.Minutes())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 TestGetNowDate(t *testing.T) {
|
func TestGetNowDate(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestGetNowDate")
|
assert := internal.NewAssert(t, "TestGetNowDate")
|
||||||
expected := time.Now().Format("2006-01-02")
|
expected := time.Now().Format("2006-01-02")
|
||||||
@@ -231,3 +244,57 @@ func TestEndOfYear(t *testing.T) {
|
|||||||
|
|
||||||
assert.Equal(expected, actual)
|
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 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 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)
|
||||||
|
}
|
||||||
|
|||||||
326
docs/compare.md
Normal file
326
docs/compare.md
Normal file
@@ -0,0 +1,326 @@
|
|||||||
|
# Compare
|
||||||
|
|
||||||
|
Package compare provides a lightweight comparison function on any type.
|
||||||
|
|
||||||
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
## Source:
|
||||||
|
|
||||||
|
- [https://github.com/duke-git/lancet/blob/v1/compare/compare.go](https://github.com/duke-git/lancet/blob/v1/compare/compare.go)
|
||||||
|
|
||||||
|
- [https://github.com/duke-git/lancet/blob/v1/compare/compare_internal.go](https://github.com/duke-git/lancet/blob/v1/compare/compare_internal.go)
|
||||||
|
|
||||||
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
## Usage:
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"github.com/duke-git/lancet/condition"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
## Index
|
||||||
|
|
||||||
|
- [Equal](#Equal)
|
||||||
|
- [EqualValue](#EqualValue)
|
||||||
|
- [LessThan](#LessThan)
|
||||||
|
- [GreaterThan](#GreaterThan)
|
||||||
|
- [LessOrEqual](#LessOrEqual)
|
||||||
|
- [GreaterOrEqual](#GreaterOrEqual)
|
||||||
|
|
||||||
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
### <span id="Equal">Equal</span>
|
||||||
|
|
||||||
|
<p>Checks if two values are equal or not. (check both type and value)</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Equal(left, right any) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/compare"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := compare.Equal(1, 1)
|
||||||
|
result2 := compare.Equal("1", "1")
|
||||||
|
result3 := compare.Equal([]int{1, 2, 3}, []int{1, 2, 3})
|
||||||
|
result4 := compare.Equal(map[int]string{1: "a", 2: "b"}, map[int]string{1: "a", 2: "b"})
|
||||||
|
|
||||||
|
result5 := compare.Equal(1, "1")
|
||||||
|
result6 := compare.Equal(1, int64(1))
|
||||||
|
result7 := compare.Equal([]int{1, 2}, []int{1, 2, 3})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
fmt.Println(result6)
|
||||||
|
fmt.Println(result7)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="EqualValue">EqualValue</span>
|
||||||
|
|
||||||
|
<p>Checks if two values are equal or not. (check value only)</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func EqualValue(left, right any) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/compare"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := compare.EqualValue(1, 1)
|
||||||
|
result2 := compare.EqualValue(int(1), int64(1))
|
||||||
|
result3 := compare.EqualValue(1, "1")
|
||||||
|
result4 := compare.EqualValue(1, "2")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="LessThan">LessThan</span>
|
||||||
|
|
||||||
|
<p>Checks if value `left` less than value `right`.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func LessThan(left, right any) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/compare"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := compare.LessThan(1, 2)
|
||||||
|
result2 := compare.LessThan(1.1, 2.2)
|
||||||
|
result3 := compare.LessThan("a", "b")
|
||||||
|
|
||||||
|
time1 := time.Now()
|
||||||
|
time2 := time1.Add(time.Second)
|
||||||
|
result4 := compare.LessThan(time1, time2)
|
||||||
|
|
||||||
|
result5 := compare.LessThan(2, 1)
|
||||||
|
result6 := compare.LessThan(1, int64(2))
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
fmt.Println(result6)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="GreaterThan">GreaterThan</span>
|
||||||
|
|
||||||
|
<p>Checks if value `left` greater than value `right`.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func GreaterThan(left, right any) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/compare"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := compare.GreaterThan(2, 1)
|
||||||
|
result2 := compare.GreaterThan(2.2, 1.1)
|
||||||
|
result3 := compare.GreaterThan("b", "a")
|
||||||
|
|
||||||
|
time1 := time.Now()
|
||||||
|
time2 := time1.Add(time.Second)
|
||||||
|
result4 := compare.GreaterThan(time2, time1)
|
||||||
|
|
||||||
|
result5 := compare.GreaterThan(1, 2)
|
||||||
|
result6 := compare.GreaterThan(int64(2), 1)
|
||||||
|
result7 := compare.GreaterThan("b", "c")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
fmt.Println(result6)
|
||||||
|
fmt.Println(result7)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="LessOrEqual">LessOrEqual</span>
|
||||||
|
|
||||||
|
<p>Checks if value `left` less than or equal than value `right`.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func LessOrEqual(left, right any) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/compare"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := compare.LessOrEqual(1, 1)
|
||||||
|
result2 := compare.LessOrEqual(1.1, 2.2)
|
||||||
|
result3 := compare.LessOrEqual("a", "b")
|
||||||
|
|
||||||
|
time1 := time.Now()
|
||||||
|
time2 := time1.Add(time.Second)
|
||||||
|
result4 := compare.LessOrEqual(time1, time2)
|
||||||
|
|
||||||
|
result5 := compare.LessOrEqual(2, 1)
|
||||||
|
result6 := compare.LessOrEqual(1, int64(2))
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
fmt.Println(result6)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="GreaterOrEqual">GreaterOrEqual</span>
|
||||||
|
|
||||||
|
<p>Checks if value `left` less greater or equal than value `right`.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func GreaterOrEqual(left, right any) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/compare"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := compare.GreaterOrEqual(1, 1)
|
||||||
|
result2 := compare.GreaterOrEqual(2.2, 1.1)
|
||||||
|
result3 := compare.GreaterOrEqual("b", "b")
|
||||||
|
|
||||||
|
time1 := time.Now()
|
||||||
|
time2 := time1.Add(time.Second)
|
||||||
|
result4 := compare.GreaterOrEqual(time2, time1)
|
||||||
|
|
||||||
|
result5 := compare.GreaterOrEqual(1, 2)
|
||||||
|
result6 := compare.GreaterOrEqual(int64(2), 1)
|
||||||
|
result7 := compare.GreaterOrEqual("b", "c")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
fmt.Println(result6)
|
||||||
|
fmt.Println(result7)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
326
docs/compare_zh-CN.md
Normal file
326
docs/compare_zh-CN.md
Normal file
@@ -0,0 +1,326 @@
|
|||||||
|
# Compare
|
||||||
|
|
||||||
|
compare包提供几个轻量级的类型比较函数。
|
||||||
|
|
||||||
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
## 源码:
|
||||||
|
|
||||||
|
- [https://github.com/duke-git/lancet/blob/v1/compare/compare.go](https://github.com/duke-git/lancet/blob/v1/compare/compare.go)
|
||||||
|
|
||||||
|
- [https://github.com/duke-git/lancet/blob/v1/compare/compare_internal.go](https://github.com/duke-git/lancet/blob/v1/compare/compare_internal.go)
|
||||||
|
|
||||||
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
## 用法:
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"github.com/duke-git/lancet/condition"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
## 目录
|
||||||
|
|
||||||
|
- [Equal](#Equal)
|
||||||
|
- [EqualValue](#EqualValue)
|
||||||
|
- [LessThan](#LessThan)
|
||||||
|
- [GreaterThan](#GreaterThan)
|
||||||
|
- [LessOrEqual](#LessOrEqual)
|
||||||
|
- [GreaterOrEqual](#GreaterOrEqual)
|
||||||
|
|
||||||
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
### <span id="Equal">Equal</span>
|
||||||
|
|
||||||
|
<p>检查两个值是否相等(检查类型和值)</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Equal(left, right any) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/compare"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := compare.Equal(1, 1)
|
||||||
|
result2 := compare.Equal("1", "1")
|
||||||
|
result3 := compare.Equal([]int{1, 2, 3}, []int{1, 2, 3})
|
||||||
|
result4 := compare.Equal(map[int]string{1: "a", 2: "b"}, map[int]string{1: "a", 2: "b"})
|
||||||
|
|
||||||
|
result5 := compare.Equal(1, "1")
|
||||||
|
result6 := compare.Equal(1, int64(1))
|
||||||
|
result7 := compare.Equal([]int{1, 2}, []int{1, 2, 3})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
fmt.Println(result6)
|
||||||
|
fmt.Println(result7)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="EqualValue">EqualValue</span>
|
||||||
|
|
||||||
|
<p>检查两个值是否相等(只检查值)</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func EqualValue(left, right any) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/compare"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := compare.EqualValue(1, 1)
|
||||||
|
result2 := compare.EqualValue(int(1), int64(1))
|
||||||
|
result3 := compare.EqualValue(1, "1")
|
||||||
|
result4 := compare.EqualValue(1, "2")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="LessThan">LessThan</span>
|
||||||
|
|
||||||
|
<p>验证参数`left`的值是否小于参数`right`的值。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func LessThan(left, right any) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/compare"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := compare.LessThan(1, 2)
|
||||||
|
result2 := compare.LessThan(1.1, 2.2)
|
||||||
|
result3 := compare.LessThan("a", "b")
|
||||||
|
|
||||||
|
time1 := time.Now()
|
||||||
|
time2 := time1.Add(time.Second)
|
||||||
|
result4 := compare.LessThan(time1, time2)
|
||||||
|
|
||||||
|
result5 := compare.LessThan(2, 1)
|
||||||
|
result6 := compare.LessThan(1, int64(2))
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
fmt.Println(result6)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="GreaterThan">GreaterThan</span>
|
||||||
|
|
||||||
|
<p>验证参数`left`的值是否大于参数`right`的值。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func GreaterThan(left, right any) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/compare"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := compare.GreaterThan(2, 1)
|
||||||
|
result2 := compare.GreaterThan(2.2, 1.1)
|
||||||
|
result3 := compare.GreaterThan("b", "a")
|
||||||
|
|
||||||
|
time1 := time.Now()
|
||||||
|
time2 := time1.Add(time.Second)
|
||||||
|
result4 := compare.GreaterThan(time2, time1)
|
||||||
|
|
||||||
|
result5 := compare.GreaterThan(1, 2)
|
||||||
|
result6 := compare.GreaterThan(int64(2), 1)
|
||||||
|
result7 := compare.GreaterThan("b", "c")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
fmt.Println(result6)
|
||||||
|
fmt.Println(result7)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="LessOrEqual">LessOrEqual</span>
|
||||||
|
|
||||||
|
<p>验证参数`left`的值是否小于或等于参数`right`的值。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func LessOrEqual(left, right any) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/compare"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := compare.LessOrEqual(1, 1)
|
||||||
|
result2 := compare.LessOrEqual(1.1, 2.2)
|
||||||
|
result3 := compare.LessOrEqual("a", "b")
|
||||||
|
|
||||||
|
time1 := time.Now()
|
||||||
|
time2 := time1.Add(time.Second)
|
||||||
|
result4 := compare.LessOrEqual(time1, time2)
|
||||||
|
|
||||||
|
result5 := compare.LessOrEqual(2, 1)
|
||||||
|
result6 := compare.LessOrEqual(1, int64(2))
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
fmt.Println(result6)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="GreaterOrEqual">GreaterOrEqual</span>
|
||||||
|
|
||||||
|
<p>验证参数`left`的值是否大于或参数`right`的值。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func GreaterOrEqual(left, right any) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/compare"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := compare.GreaterOrEqual(1, 1)
|
||||||
|
result2 := compare.GreaterOrEqual(2.2, 1.1)
|
||||||
|
result3 := compare.GreaterOrEqual("b", "b")
|
||||||
|
|
||||||
|
time1 := time.Now()
|
||||||
|
time2 := time1.Add(time.Second)
|
||||||
|
result4 := compare.GreaterOrEqual(time2, time1)
|
||||||
|
|
||||||
|
result5 := compare.GreaterOrEqual(1, 2)
|
||||||
|
result6 := compare.GreaterOrEqual(int64(2), 1)
|
||||||
|
result7 := compare.GreaterOrEqual("b", "c")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
fmt.Println(result6)
|
||||||
|
fmt.Println(result7)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -36,6 +36,9 @@ import (
|
|||||||
- [EncodeByte](#EncodeByte)
|
- [EncodeByte](#EncodeByte)
|
||||||
- [DecodeByte](#DecodeByte)
|
- [DecodeByte](#DecodeByte)
|
||||||
- [DeepClone](#DeepClone)
|
- [DeepClone](#DeepClone)
|
||||||
|
- [CopyProperties](#CopyProperties)
|
||||||
|
- [ToInterface](#ToInterface)
|
||||||
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -501,3 +504,117 @@ func main() {
|
|||||||
// &{test 1 0.1 true <nil> } false
|
// &{test 1 0.1 true <nil> } false
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <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>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func CopyProperties(dst, src interface{}) error
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/convertor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
type Disk struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Total string `json:"total"`
|
||||||
|
Used string `json:"used"`
|
||||||
|
Percent float64 `json:"percent"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DiskVO struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Total string `json:"total"`
|
||||||
|
Used string `json:"used"`
|
||||||
|
Percent float64 `json:"percent"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Indicator struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Ip string `json:"ip"`
|
||||||
|
UpTime string `json:"upTime"`
|
||||||
|
LoadAvg string `json:"loadAvg"`
|
||||||
|
Cpu int `json:"cpu"`
|
||||||
|
Disk []Disk `json:"disk"`
|
||||||
|
Stop chan bool `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type IndicatorVO struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Ip string `json:"ip"`
|
||||||
|
UpTime string `json:"upTime"`
|
||||||
|
LoadAvg string `json:"loadAvg"`
|
||||||
|
Cpu int64 `json:"cpu"`
|
||||||
|
Disk []DiskVO `json:"disk"`
|
||||||
|
}
|
||||||
|
|
||||||
|
indicator := &Indicator{Id: "001", Ip: "127.0.0.1", Cpu: 1, Disk: []Disk{
|
||||||
|
{Name: "disk-001", Total: "100", Used: "1", Percent: 10},
|
||||||
|
{Name: "disk-002", Total: "200", Used: "1", Percent: 20},
|
||||||
|
{Name: "disk-003", Total: "300", Used: "1", Percent: 30},
|
||||||
|
}}
|
||||||
|
|
||||||
|
indicatorVO := IndicatorVO{}
|
||||||
|
|
||||||
|
err := convertor.CopyProperties(&indicatorVO, indicator)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(indicatorVO.Id)
|
||||||
|
fmt.Println(indicatorVO.Ip)
|
||||||
|
fmt.Println(len(indicatorVO.Disk))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 001
|
||||||
|
// 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/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
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -36,6 +36,8 @@ import (
|
|||||||
- [EncodeByte](#EncodeByte)
|
- [EncodeByte](#EncodeByte)
|
||||||
- [DecodeByte](#DecodeByte)
|
- [DecodeByte](#DecodeByte)
|
||||||
- [DeepClone](#DeepClone)
|
- [DeepClone](#DeepClone)
|
||||||
|
- [CopyProperties](#CopyProperties)
|
||||||
|
- [ToInterface](#ToInterface)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -211,7 +213,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/convertor"
|
"github.com/duke-git/lancet/convertor"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -401,7 +403,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/convertor"
|
"github.com/duke-git/lancet/convertor"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -427,7 +429,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/convertor"
|
"github.com/duke-git/lancet/convertor"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -501,3 +503,118 @@ func main() {
|
|||||||
// &{test 1 0.1 true <nil> } false
|
// &{test 1 0.1 true <nil> } false
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="CopyProperties">CopyProperties</span>
|
||||||
|
|
||||||
|
<p>拷贝不同结构体之间的同名字段。使用json.Marshal序列化,需要设置dst和src struct字段的json tag。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func CopyProperties(dst, src interface{}) error
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/convertor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
type Disk struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Total string `json:"total"`
|
||||||
|
Used string `json:"used"`
|
||||||
|
Percent float64 `json:"percent"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DiskVO struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Total string `json:"total"`
|
||||||
|
Used string `json:"used"`
|
||||||
|
Percent float64 `json:"percent"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Indicator struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Ip string `json:"ip"`
|
||||||
|
UpTime string `json:"upTime"`
|
||||||
|
LoadAvg string `json:"loadAvg"`
|
||||||
|
Cpu int `json:"cpu"`
|
||||||
|
Disk []Disk `json:"disk"`
|
||||||
|
Stop chan bool `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type IndicatorVO struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Ip string `json:"ip"`
|
||||||
|
UpTime string `json:"upTime"`
|
||||||
|
LoadAvg string `json:"loadAvg"`
|
||||||
|
Cpu int64 `json:"cpu"`
|
||||||
|
Disk []DiskVO `json:"disk"`
|
||||||
|
}
|
||||||
|
|
||||||
|
indicator := &Indicator{Id: "001", Ip: "127.0.0.1", Cpu: 1, Disk: []Disk{
|
||||||
|
{Name: "disk-001", Total: "100", Used: "1", Percent: 10},
|
||||||
|
{Name: "disk-002", Total: "200", Used: "1", Percent: 20},
|
||||||
|
{Name: "disk-003", Total: "300", Used: "1", Percent: 30},
|
||||||
|
}}
|
||||||
|
|
||||||
|
indicatorVO := IndicatorVO{}
|
||||||
|
|
||||||
|
err := convertor.CopyProperties(&indicatorVO, indicator)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(indicatorVO.Id)
|
||||||
|
fmt.Println(indicatorVO.Ip)
|
||||||
|
fmt.Println(len(indicatorVO.Disk))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 001
|
||||||
|
// 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/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
|
||||||
|
}
|
||||||
|
```
|
||||||
252
docs/datetime.md
252
docs/datetime.md
@@ -25,6 +25,7 @@ import (
|
|||||||
- [AddDay](#AddDay)
|
- [AddDay](#AddDay)
|
||||||
- [AddHour](#AddHour)
|
- [AddHour](#AddHour)
|
||||||
- [AddMinute](#AddMinute)
|
- [AddMinute](#AddMinute)
|
||||||
|
- [AddYear](#AddYear)
|
||||||
- [BeginOfMinute](#BeginOfMinute)
|
- [BeginOfMinute](#BeginOfMinute)
|
||||||
- [BeginOfHour](#BeginOfHour)
|
- [BeginOfHour](#BeginOfHour)
|
||||||
- [BeginOfDay](#BeginOfDay)
|
- [BeginOfDay](#BeginOfDay)
|
||||||
@@ -52,6 +53,10 @@ import (
|
|||||||
- [ToFormat](#ToFormat)
|
- [ToFormat](#ToFormat)
|
||||||
- [ToFormatForTpl](#ToFormatForTpl)
|
- [ToFormatForTpl](#ToFormatForTpl)
|
||||||
- [ToIso8601](#ToIso8601)
|
- [ToIso8601](#ToIso8601)
|
||||||
|
- [IsLeapYear](#IsLeapYear)
|
||||||
|
- [BetweenSeconds](#BetweenSeconds)
|
||||||
|
- [DayOfYear](#DayOfYear)
|
||||||
|
- [IsWeekend](#IsWeekend)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -170,6 +175,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/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>
|
### <span id="BeginOfMinute">BeginOfMinute</span>
|
||||||
|
|
||||||
<p>Return beginning minute time of day.</p>
|
<p>Return beginning minute time of day.</p>
|
||||||
@@ -720,7 +764,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/datetime"
|
"github.com/duke-git/lancet/datetime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -749,7 +793,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/datetime"
|
"github.com/duke-git/lancet/datetime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -778,7 +822,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/datetime"
|
"github.com/duke-git/lancet/datetime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -807,7 +851,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/datetime"
|
"github.com/duke-git/lancet/datetime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -833,7 +877,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/datetime"
|
"github.com/duke-git/lancet/datetime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -859,7 +903,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/datetime"
|
"github.com/duke-git/lancet/datetime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -885,7 +929,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/datetime"
|
"github.com/duke-git/lancet/datetime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -912,7 +956,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/datetime"
|
"github.com/duke-git/lancet/datetime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -921,3 +965,195 @@ func main() {
|
|||||||
fmt.Println(ts) //"2006-01-02T23:04:05+08:00"
|
fmt.Println(ts) //"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/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/datetime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
today := time.Now()
|
||||||
|
tomorrow := AddDay(today, 1)
|
||||||
|
yesterday := 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/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/datetime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
date1 := time.Date(2023, 06, 03, 0, 0, 0, 0, time.Local)
|
||||||
|
date2 := time.Date(2023, 06, 04, 0, 0, 0, 0, time.Local)
|
||||||
|
date3 := time.Date(2023, 06, 02, 0, 0, 0, 0, time.Local)
|
||||||
|
|
||||||
|
result1 := datetime.IsWeekend(date1)
|
||||||
|
result2 := datetime.IsWeekend(date2)
|
||||||
|
result3 := datetime.IsWeekend(date3)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="IsWeekend">IsWeekend</span>
|
||||||
|
|
||||||
|
<p>判断日期是否是周末。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsWeekend(t time.Time) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/datetime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
date1 := time.Date(2023, 06, 03, 0, 0, 0, 0, time.Local)
|
||||||
|
date2 := time.Date(2023, 06, 04, 0, 0, 0, 0, time.Local)
|
||||||
|
date3 := time.Date(2023, 06, 02, 0, 0, 0, 0, time.Local)
|
||||||
|
|
||||||
|
result1 := datetime.IsWeekend(date1)
|
||||||
|
result2 := datetime.IsWeekend(date2)
|
||||||
|
result3 := datetime.IsWeekend(date3)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import (
|
|||||||
- [AddDay](#AddDay)
|
- [AddDay](#AddDay)
|
||||||
- [AddHour](#AddHour)
|
- [AddHour](#AddHour)
|
||||||
- [AddMinute](#AddMinute)
|
- [AddMinute](#AddMinute)
|
||||||
|
- [AddYear](#AddYear)
|
||||||
- [BeginOfMinute](#BeginOfMinute)
|
- [BeginOfMinute](#BeginOfMinute)
|
||||||
- [BeginOfHour](#BeginOfHour)
|
- [BeginOfHour](#BeginOfHour)
|
||||||
- [BeginOfDay](#BeginOfDay)
|
- [BeginOfDay](#BeginOfDay)
|
||||||
@@ -52,6 +53,11 @@ import (
|
|||||||
- [ToFormat](#ToFormat)
|
- [ToFormat](#ToFormat)
|
||||||
- [ToFormatForTpl](#ToFormatForTpl)
|
- [ToFormatForTpl](#ToFormatForTpl)
|
||||||
- [ToIso8601](#ToIso8601)
|
- [ToIso8601](#ToIso8601)
|
||||||
|
- [IsLeapYear](#IsLeapYear)
|
||||||
|
- [BetweenSeconds](#BetweenSeconds)
|
||||||
|
- [DayOfYear](#DayOfYear)
|
||||||
|
- [IsWeekend](#IsWeekend)
|
||||||
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -170,6 +176,45 @@ 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/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>
|
### <span id="BeginOfMinute">BeginOfMinute</span>
|
||||||
|
|
||||||
<p>返回指定时间的分钟开始时间</p>
|
<p>返回指定时间的分钟开始时间</p>
|
||||||
@@ -720,7 +765,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/datetime"
|
"github.com/duke-git/lancet/datetime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -749,7 +794,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/datetime"
|
"github.com/duke-git/lancet/datetime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -778,7 +823,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/datetime"
|
"github.com/duke-git/lancet/datetime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -807,7 +852,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/datetime"
|
"github.com/duke-git/lancet/datetime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -833,7 +878,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/datetime"
|
"github.com/duke-git/lancet/datetime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -859,7 +904,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/datetime"
|
"github.com/duke-git/lancet/datetime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -885,7 +930,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/datetime"
|
"github.com/duke-git/lancet/datetime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -912,7 +957,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/datetime"
|
"github.com/duke-git/lancet/datetime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -921,3 +966,114 @@ func main() {
|
|||||||
fmt.Println(ts) //"2006-01-02T23:04:05+08:00"
|
fmt.Println(ts) //"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/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/datetime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
today := time.Now()
|
||||||
|
tomorrow := AddDay(today, 1)
|
||||||
|
yesterday := 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/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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
295
docs/fileutil.md
295
docs/fileutil.md
@@ -37,6 +37,14 @@ import (
|
|||||||
- [ReadFileByLine](#ReadFileByLine)
|
- [ReadFileByLine](#ReadFileByLine)
|
||||||
- [Zip](#Zip)
|
- [Zip](#Zip)
|
||||||
- [UnZip](#UnZip)
|
- [UnZip](#UnZip)
|
||||||
|
- [CurrentPath](#CurrentPath)
|
||||||
|
- [IsZipFile](#IsZipFile)
|
||||||
|
- [FileSize](#FileSize)
|
||||||
|
- [MTime](#MTime)
|
||||||
|
- [Sha](#Sha)
|
||||||
|
- [ReadCsvFile](#ReadCsvFile)
|
||||||
|
- [WriteStringToFile](#WriteStringToFile)
|
||||||
|
- [WriteBytesToFile](#WriteBytesToFile)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -468,3 +476,290 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="CurrentPath">CurrentPath</span>
|
||||||
|
|
||||||
|
<p>return current absolute path.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func CurrentPath() string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/fileutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
absPath := CurrentPath()
|
||||||
|
fmt.Println(absPath)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="IsZipFile">IsZipFile</span>
|
||||||
|
|
||||||
|
<p>Checks if file is zip file or not.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsZipFile(filepath string) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/fileutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
isZip := IsZipFile("./zipfile.zip")
|
||||||
|
fmt.Println(isZip)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="FileSize">FileSize</span>
|
||||||
|
|
||||||
|
<p>Returns file size in bytes.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func FileSize(path string) (int64, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/fileutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
size, err := fileutil.FileSize("./testdata/test.txt")
|
||||||
|
|
||||||
|
fmt.Println(size)
|
||||||
|
fmt.Println(err)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 20
|
||||||
|
// <nil>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="MTime">MTime</span>
|
||||||
|
|
||||||
|
<p>Returns file modified time(unix timestamp).</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func MTime(filepath string) (int64, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/fileutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
mtime, err := fileutil.MTime("./testdata/test.txt")
|
||||||
|
|
||||||
|
fmt.Println(mtime)
|
||||||
|
fmt.Println(err)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1682391110
|
||||||
|
// <nil>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Sha">Sha</span>
|
||||||
|
|
||||||
|
<p>returns file sha value, param `shaType` should be 1, 256 or 512.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Sha(filepath string, shaType ...int) (string, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/fileutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
sha1, err := fileutil.Sha("./testdata/test.txt", 1)
|
||||||
|
sha256, _ := fileutil.Sha("./testdata/test.txt", 256)
|
||||||
|
sha512, _ := fileutil.Sha("./testdata/test.txt", 512)
|
||||||
|
|
||||||
|
fmt.Println(sha1)
|
||||||
|
fmt.Println(sha256)
|
||||||
|
fmt.Println(sha512)
|
||||||
|
fmt.Println(err)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// dda3cf10c5a6ff6c6659a497bf7261b287af2bc7
|
||||||
|
// aa6d0a3fbc3442c228d606da09e0c1dc98c69a1cac3da1909199e0266171df35
|
||||||
|
// d22aba2a1b7a2e2f512756255cc1c3708905646920cb1eb95e45b531ba74774dbbb89baebf1f716220eb9cf4908f1cfc5b2a01267704d9a59f59d77cab609870
|
||||||
|
// <nil>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ReadCsvFile">ReadCsvFile</span>
|
||||||
|
|
||||||
|
<p>Reads file content into slice.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ReadCsvFile(filepath string) ([][]string, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/fileutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
content, err := fileutil.ReadCsvFile("./testdata/test.csv")
|
||||||
|
|
||||||
|
fmt.Println(content)
|
||||||
|
fmt.Println(err)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [[Bob 12 male] [Duke 14 male] [Lucy 16 female]]
|
||||||
|
// <nil>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <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/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/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,6 +37,14 @@ import (
|
|||||||
- [ReadFileByLine](#ReadFileByLine)
|
- [ReadFileByLine](#ReadFileByLine)
|
||||||
- [Zip](#Zip)
|
- [Zip](#Zip)
|
||||||
- [UnZip](#UnZip)
|
- [UnZip](#UnZip)
|
||||||
|
- [CurrentPath](#CurrentPath)
|
||||||
|
- [IsZipFile](#IsZipFile)
|
||||||
|
- [FileSize](#FileSize)
|
||||||
|
- [MTime](#MTime)
|
||||||
|
- [Sha](#Sha)
|
||||||
|
- [ReadCsvFile](#ReadCsvFile)
|
||||||
|
- [WriteStringToFile](#WriteStringToFile)
|
||||||
|
- [WriteBytesToFile](#WriteBytesToFile)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -445,7 +453,7 @@ func main() {
|
|||||||
|
|
||||||
<p>zip解压缩文件并保存在目录中</p>
|
<p>zip解压缩文件并保存在目录中</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func UnZip(zipFile string, destPath string) error
|
func UnZip(zipFile string, destPath string) error
|
||||||
@@ -468,3 +476,289 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="CurrentPath">CurrentPath</span>
|
||||||
|
|
||||||
|
<p>返回当前位置的绝对路径。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func CurrentPath() string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/fileutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
absPath := CurrentPath()
|
||||||
|
fmt.Println(absPath)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="IsZipFile">IsZipFile</span>
|
||||||
|
|
||||||
|
<p>判断文件是否是zip压缩文件。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsZipFile(filepath string) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/fileutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
isZip := IsZipFile("./zipfile.zip")
|
||||||
|
fmt.Println(isZip)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="FileSize">FileSize</span>
|
||||||
|
|
||||||
|
<p>返回文件字节大小。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func FileSize(path string) (int64, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/fileutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
size, err := fileutil.FileSize("./testdata/test.txt")
|
||||||
|
|
||||||
|
fmt.Println(size)
|
||||||
|
fmt.Println(err)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 20
|
||||||
|
// <nil>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="MTime">MTime</span>
|
||||||
|
|
||||||
|
<p>返回文件修改时间(unix timestamp).</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func MTime(filepath string) (int64, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/fileutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
mtime, err := fileutil.MTime("./testdata/test.txt")
|
||||||
|
|
||||||
|
fmt.Println(mtime)
|
||||||
|
fmt.Println(err)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1682391110
|
||||||
|
// <nil>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Sha">Sha</span>
|
||||||
|
|
||||||
|
<p>返回文件sha值,参数`shaType` 应传值为: 1, 256,512.</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Sha(filepath string, shaType ...int) (string, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/fileutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
sha1, err := fileutil.Sha("./testdata/test.txt", 1)
|
||||||
|
sha256, _ := fileutil.Sha("./testdata/test.txt", 256)
|
||||||
|
sha512, _ := fileutil.Sha("./testdata/test.txt", 512)
|
||||||
|
|
||||||
|
fmt.Println(sha1)
|
||||||
|
fmt.Println(sha256)
|
||||||
|
fmt.Println(sha512)
|
||||||
|
fmt.Println(err)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// dda3cf10c5a6ff6c6659a497bf7261b287af2bc7
|
||||||
|
// aa6d0a3fbc3442c228d606da09e0c1dc98c69a1cac3da1909199e0266171df35
|
||||||
|
// d22aba2a1b7a2e2f512756255cc1c3708905646920cb1eb95e45b531ba74774dbbb89baebf1f716220eb9cf4908f1cfc5b2a01267704d9a59f59d77cab609870
|
||||||
|
// <nil>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ReadCsvFile">ReadCsvFile</span>
|
||||||
|
|
||||||
|
<p>读取csv文件内容到切片</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ReadCsvFile(filepath string) ([][]string, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/fileutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
content, err := fileutil.ReadCsvFile("./testdata/test.csv")
|
||||||
|
|
||||||
|
fmt.Println(content)
|
||||||
|
fmt.Println(err)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [[Bob 12 male] [Duke 14 male] [Lucy 16 female]]
|
||||||
|
// <nil>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <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/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/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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@@ -23,6 +23,12 @@ import (
|
|||||||
## Index
|
## Index
|
||||||
|
|
||||||
- [Comma](#Comma)
|
- [Comma](#Comma)
|
||||||
|
- [Pretty](#Pretty)
|
||||||
|
- [PrettyToWriter](#PrettyToWriter)
|
||||||
|
- [DecimalBytes](#DecimalBytes)
|
||||||
|
- [BinaryBytes](#BinaryBytes)
|
||||||
|
- [ParseDecimalBytes](#ParseDecimalBytes)
|
||||||
|
- [ParseBinaryBytes](#ParseBinaryBytes)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -36,7 +42,7 @@ Param should be number or numberic string.</p>
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func Comma(v interface{}, symbol string) string
|
func Comma(value interface{}, symbol string) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
@@ -54,3 +60,241 @@ func main() {
|
|||||||
fmt.Println(formatter.Comma(12345.67, "¥")) // "¥12,345.67"
|
fmt.Println(formatter.Comma(12345.67, "¥")) // "¥12,345.67"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="Pretty">Pretty</span>
|
||||||
|
|
||||||
|
<p>Pretty data to JSON string.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Pretty(v interface{}) (string, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1, _ := formatter.Pretty([]string{"a", "b", "c"})
|
||||||
|
result2, _ := formatter.Pretty(map[string]int{"a": 1})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [
|
||||||
|
// "a",
|
||||||
|
// "b",
|
||||||
|
// "c"
|
||||||
|
// ]
|
||||||
|
// {
|
||||||
|
// "a": 1
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="PrettyToWriter">PrettyToWriter</span>
|
||||||
|
|
||||||
|
<p>Pretty encode data to writer.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func PrettyToWriter(v interface{}, out io.Writer) error
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
type User struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Aage uint `json:"age"`
|
||||||
|
}
|
||||||
|
user := User{Name: "King", Aage: 10000}
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
err := formatter.PrettyToWriter(user, buf)
|
||||||
|
|
||||||
|
fmt.Println(buf)
|
||||||
|
fmt.Println(err)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// {
|
||||||
|
// "name": "King",
|
||||||
|
// "age": 10000
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// <nil>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="DecimalBytes">DecimalBytes</span>
|
||||||
|
|
||||||
|
<p>Returns a human readable byte size under decimal standard (base 1000). The precision parameter specifies the number of digits after the decimal point, which is 4 for default.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func DecimalBytes(size float64, precision ...int) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := formatter.DecimalBytes(1000)
|
||||||
|
result2 := formatter.DecimalBytes(1024)
|
||||||
|
result3 := formatter.DecimalBytes(1234567)
|
||||||
|
result4 := formatter.DecimalBytes(1234567, 3)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1KB
|
||||||
|
// 1.024KB
|
||||||
|
// 1.2346MB
|
||||||
|
// 1.235MB
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="BinaryBytes">BinaryBytes</span>
|
||||||
|
|
||||||
|
<p>Returns a human readable byte size under binary standard (base 1024). The precision parameter specifies the number of digits after the decimal point, which is 4 for default.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func BinaryBytes(size float64, precision ...int) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := formatter.BinaryBytes(1024)
|
||||||
|
result2 := formatter.BinaryBytes(1024 * 1024)
|
||||||
|
result3 := formatter.BinaryBytes(1234567)
|
||||||
|
result4 := formatter.BinaryBytes(1234567, 2)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1KiB
|
||||||
|
// 1MiB
|
||||||
|
// 1.1774MiB
|
||||||
|
// 1.18MiB
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ParseDecimalBytes">ParseDecimalBytes</span>
|
||||||
|
|
||||||
|
<p>Returns the human readable bytes size string into the amount it represents(base 1000).</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ParseDecimalBytes(size string) (uint64, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1, _ := formatter.ParseDecimalBytes("12")
|
||||||
|
result2, _ := formatter.ParseDecimalBytes("12k")
|
||||||
|
result3, _ := formatter.ParseDecimalBytes("12 Kb")
|
||||||
|
result4, _ := formatter.ParseDecimalBytes("12.2 kb")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 12
|
||||||
|
// 12000
|
||||||
|
// 12000
|
||||||
|
// 12200
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ParseBinaryBytes">ParseBinaryBytes</span>
|
||||||
|
|
||||||
|
<p>Returns the human readable bytes size string into the amount it represents(base 1024).</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ParseBinaryBytes(size string) (uint64, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1, _ := formatter.ParseBinaryBytes("12")
|
||||||
|
result2, _ := formatter.ParseBinaryBytes("12ki")
|
||||||
|
result3, _ := formatter.ParseBinaryBytes("12 KiB")
|
||||||
|
result4, _ := formatter.ParseBinaryBytes("12.2 kib")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 12
|
||||||
|
// 12288
|
||||||
|
// 12288
|
||||||
|
// 12492
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@@ -23,6 +23,12 @@ import (
|
|||||||
## 目录
|
## 目录
|
||||||
|
|
||||||
- [Comma](#Comma)
|
- [Comma](#Comma)
|
||||||
|
- [Pretty](#Pretty)
|
||||||
|
- [PrettyToWriter](#PrettyToWriter)
|
||||||
|
- [DecimalBytes](#DecimalBytes)
|
||||||
|
- [BinaryBytes](#BinaryBytes)
|
||||||
|
- [ParseDecimalBytes](#ParseDecimalBytes)
|
||||||
|
- [ParseBinaryBytes](#ParseBinaryBytes)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -53,3 +59,241 @@ func main() {
|
|||||||
fmt.Println(formatter.Comma(12345.67, "¥")) // "¥12,345.67"
|
fmt.Println(formatter.Comma(12345.67, "¥")) // "¥12,345.67"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="Pretty">Pretty</span>
|
||||||
|
|
||||||
|
<p>返回pretty JSON字符串.</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Pretty(v interface{}) (string, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1, _ := formatter.Pretty([]string{"a", "b", "c"})
|
||||||
|
result2, _ := formatter.Pretty(map[string]int{"a": 1})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [
|
||||||
|
// "a",
|
||||||
|
// "b",
|
||||||
|
// "c"
|
||||||
|
// ]
|
||||||
|
// {
|
||||||
|
// "a": 1
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="PrettyToWriter">PrettyToWriter</span>
|
||||||
|
|
||||||
|
<p>Pretty encode数据到writer。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func PrettyToWriter(v interface{}, out io.Writer) error
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
type User struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Aage uint `json:"age"`
|
||||||
|
}
|
||||||
|
user := User{Name: "King", Aage: 10000}
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
err := formatter.PrettyToWriter(user, buf)
|
||||||
|
|
||||||
|
fmt.Println(buf)
|
||||||
|
fmt.Println(err)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// {
|
||||||
|
// "name": "King",
|
||||||
|
// "age": 10000
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// <nil>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="DecimalBytes">DecimalBytes</span>
|
||||||
|
|
||||||
|
<p>返回十进制标准(以1000为基数)下的可读字节单位字符串。precision参数指定小数点后的位数,默认为4。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func DecimalBytes(size float64, precision ...int) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := formatter.DecimalBytes(1000)
|
||||||
|
result2 := formatter.DecimalBytes(1024)
|
||||||
|
result3 := formatter.DecimalBytes(1234567)
|
||||||
|
result4 := formatter.DecimalBytes(1234567, 3)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1KB
|
||||||
|
// 1.024KB
|
||||||
|
// 1.2346MB
|
||||||
|
// 1.235MB
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="BinaryBytes">BinaryBytes</span>
|
||||||
|
|
||||||
|
<p>返回binary标准(以1024为基数)下的可读字节单位字符串。precision参数指定小数点后的位数,默认为4。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func BinaryBytes(size float64, precision ...int) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := formatter.BinaryBytes(1024)
|
||||||
|
result2 := formatter.BinaryBytes(1024 * 1024)
|
||||||
|
result3 := formatter.BinaryBytes(1234567)
|
||||||
|
result4 := formatter.BinaryBytes(1234567, 2)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1KiB
|
||||||
|
// 1MiB
|
||||||
|
// 1.1774MiB
|
||||||
|
// 1.18MiB
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ParseDecimalBytes">ParseDecimalBytes</span>
|
||||||
|
|
||||||
|
<p>将字节单位字符串转换成其所表示的字节数(以1000为基数)。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ParseDecimalBytes(size string) (uint64, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1, _ := formatter.ParseDecimalBytes("12")
|
||||||
|
result2, _ := formatter.ParseDecimalBytes("12k")
|
||||||
|
result3, _ := formatter.ParseDecimalBytes("12 Kb")
|
||||||
|
result4, _ := formatter.ParseDecimalBytes("12.2 kb")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 12
|
||||||
|
// 12000
|
||||||
|
// 12000
|
||||||
|
// 12200
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ParseBinaryBytes">ParseBinaryBytes</span>
|
||||||
|
|
||||||
|
<p>将字节单位字符串转换成其所表示的字节数(以1024为基数)。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ParseBinaryBytes(size string) (uint64, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1, _ := formatter.ParseBinaryBytes("12")
|
||||||
|
result2, _ := formatter.ParseBinaryBytes("12ki")
|
||||||
|
result3, _ := formatter.ParseBinaryBytes("12 KiB")
|
||||||
|
result4, _ := formatter.ParseBinaryBytes("12.2 kib")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 12
|
||||||
|
// 12288
|
||||||
|
// 12288
|
||||||
|
// 12492
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
313
docs/mathutil.md
313
docs/mathutil.md
@@ -29,6 +29,14 @@ import (
|
|||||||
- [RoundToFloat](#RoundToFloat)
|
- [RoundToFloat](#RoundToFloat)
|
||||||
- [RoundToString](#RoundToString)
|
- [RoundToString](#RoundToString)
|
||||||
- [TruncRound](#TruncRound)
|
- [TruncRound](#TruncRound)
|
||||||
|
- [AngleToRadian](#AngleToRadian)
|
||||||
|
- [RadianToAngle](#RadianToAngle)
|
||||||
|
- [PointDistance](#PointDistance)
|
||||||
|
- [IsPrime](#IsPrime)
|
||||||
|
- [GCD](#GCD)
|
||||||
|
- [LCM](#LCM)
|
||||||
|
- [Cos](#Cos)
|
||||||
|
- [Sin](#Sin)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -230,3 +238,308 @@ func main() {
|
|||||||
fmt.Println(mathutil.TruncRound(0.125, 3)) //0.125
|
fmt.Println(mathutil.TruncRound(0.125, 3)) //0.125
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="AngleToRadian">AngleToRadian</span>
|
||||||
|
|
||||||
|
<p>Converts angle value to radian value.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func AngleToRadian(angle float64) float64
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/mathutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := mathutil.AngleToRadian(45)
|
||||||
|
result2 := mathutil.AngleToRadian(90)
|
||||||
|
result3 := mathutil.AngleToRadian(180)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 0.7853981633974483
|
||||||
|
// 1.5707963267948966
|
||||||
|
// 3.141592653589793
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="RadianToAngle">RadianToAngle</span>
|
||||||
|
|
||||||
|
<p>Converts radian value to angle value.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func RadianToAngle(radian float64) float64
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/mathutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := mathutil.RadianToAngle(math.Pi)
|
||||||
|
result2 := mathutil.RadianToAngle(math.Pi / 2)
|
||||||
|
result3 := mathutil.RadianToAngle(math.Pi / 4)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 180
|
||||||
|
// 90
|
||||||
|
// 45
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="PointDistance">PointDistance</span>
|
||||||
|
|
||||||
|
<p>Caculates two points distance.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func PointDistance(x1, y1, x2, y2 float64) float64
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/mathutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := mathutil.PointDistance(1, 1, 4, 5)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 5
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="IsPrime">IsPrime</span>
|
||||||
|
|
||||||
|
<p>Checks if number is prime number.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsPrime(n int) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/mathutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := mathutil.IsPrime(-1)
|
||||||
|
result2 := mathutil.IsPrime(0)
|
||||||
|
result3 := mathutil.IsPrime(1)
|
||||||
|
result4 := mathutil.IsPrime(2)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// 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(integers ...int) int
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/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(integers ...int) int
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/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/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/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
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -25,11 +25,18 @@ import (
|
|||||||
- [Exponent](#Exponent)
|
- [Exponent](#Exponent)
|
||||||
- [Fibonacci](#Fibonacci)
|
- [Fibonacci](#Fibonacci)
|
||||||
- [Factorial](#Factorial)
|
- [Factorial](#Factorial)
|
||||||
|
|
||||||
- [Percent](#Percent)
|
- [Percent](#Percent)
|
||||||
- [RoundToFloat](#RoundToFloat)
|
- [RoundToFloat](#RoundToFloat)
|
||||||
- [RoundToString](#RoundToString)
|
- [RoundToString](#RoundToString)
|
||||||
- [TruncRound](#TruncRound)
|
- [TruncRound](#TruncRound)
|
||||||
|
- [AngleToRadian](#AngleToRadian)
|
||||||
|
- [RadianToAngle](#RadianToAngle)
|
||||||
|
- [PointDistance](#PointDistance)
|
||||||
|
- [IsPrime](#IsPrime)
|
||||||
|
- [GCD](#GCD)
|
||||||
|
- [LCM](#LCM)
|
||||||
|
- [Cos](#Cos)
|
||||||
|
- [Sin](#Sin)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -231,3 +238,309 @@ func main() {
|
|||||||
fmt.Println(mathutil.TruncRound(0.125, 3)) //0.125
|
fmt.Println(mathutil.TruncRound(0.125, 3)) //0.125
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="AngleToRadian">AngleToRadian</span>
|
||||||
|
|
||||||
|
<p>将角度值转为弧度值</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func AngleToRadian(angle float64) float64
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/mathutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := mathutil.AngleToRadian(45)
|
||||||
|
result2 := mathutil.AngleToRadian(90)
|
||||||
|
result3 := mathutil.AngleToRadian(180)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 0.7853981633974483
|
||||||
|
// 1.5707963267948966
|
||||||
|
// 3.141592653589793
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="RadianToAngle">RadianToAngle</span>
|
||||||
|
|
||||||
|
<p>将弧度值转为角度值</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func RadianToAngle(radian float64) float64
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/mathutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := mathutil.RadianToAngle(math.Pi)
|
||||||
|
result2 := mathutil.RadianToAngle(math.Pi / 2)
|
||||||
|
result3 := mathutil.RadianToAngle(math.Pi / 4)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 180
|
||||||
|
// 90
|
||||||
|
// 45
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="PointDistance">PointDistance</span>
|
||||||
|
|
||||||
|
<p>计算两个坐标点的距离</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func PointDistance(x1, y1, x2, y2 float64) float64
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/mathutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := mathutil.PointDistance(1, 1, 4, 5)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 5
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="IsPrime">IsPrime</span>
|
||||||
|
|
||||||
|
<p>判断质数。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsPrime(n int) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/mathutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := mathutil.IsPrime(-1)
|
||||||
|
result2 := mathutil.IsPrime(0)
|
||||||
|
result3 := mathutil.IsPrime(1)
|
||||||
|
result4 := mathutil.IsPrime(2)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="GCD">GCD</span>
|
||||||
|
|
||||||
|
<p>计算整数最大公约数。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func GCD(integers ...int) int
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/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(integers ...int) int
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/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/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/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
|
||||||
|
}
|
||||||
|
```
|
||||||
201
docs/netutil.md
201
docs/netutil.md
@@ -46,6 +46,10 @@ import (
|
|||||||
- [HttpPut<sup>Deprecated</sup>](#HttpPut)
|
- [HttpPut<sup>Deprecated</sup>](#HttpPut)
|
||||||
- [HttpPatch<sup>Deprecated</sup>](#HttpPatch)
|
- [HttpPatch<sup>Deprecated</sup>](#HttpPatch)
|
||||||
- [ParseHttpResponse](#ParseHttpResponse)
|
- [ParseHttpResponse](#ParseHttpResponse)
|
||||||
|
- [UploadFile](#UploadFile)
|
||||||
|
- [DownloadFile](#DownloadFile)
|
||||||
|
- [IsPingConnected](#IsPingConnected)
|
||||||
|
- [IsTelnetConnected](#IsTelnetConnected)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -556,23 +560,35 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
type TodoQuery struct {
|
type TodoQuery struct {
|
||||||
Id int `json:"id"`
|
Id int `json:"id"`
|
||||||
UserId int `json:"userId"`
|
UserId int `json:"userId"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Status string
|
||||||
}
|
}
|
||||||
todoQuery := TodoQuery{
|
item := TodoQuery{
|
||||||
Id: 1,
|
Id: 1,
|
||||||
UserId: 2,
|
UserId: 123,
|
||||||
|
Name: "test",
|
||||||
|
Status: "completed",
|
||||||
}
|
}
|
||||||
todoValues := netutil.StructToUrlValues(todoQuery)
|
queryValues := netutil.StructToUrlValues(item)
|
||||||
|
|
||||||
fmt.Println(todoValues.Get("id")) //1
|
fmt.Println(todoValues.Get("id"))
|
||||||
fmt.Println(todoValues.Get("userId")) //2
|
fmt.Println(todoValues.Get("userId"))
|
||||||
|
fmt.Println(todoValues.Get("name"))
|
||||||
|
fmt.Println(todoValues.Get("status"))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1
|
||||||
|
// 123
|
||||||
|
// test
|
||||||
|
//
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### <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>
|
<b>Signature:</b>
|
||||||
|
|
||||||
@@ -612,9 +628,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>
|
<b>Signature:</b>
|
||||||
|
|
||||||
@@ -642,28 +658,30 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
url := "https://jsonplaceholder.typicode.com/todos"
|
url := "https://jsonplaceholder.typicode.com/todos"
|
||||||
header := map[string]string{
|
header := map[string]string{
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
}
|
// "Content-Type": "multipart/form-data",
|
||||||
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{}
|
||||||
if err != nil {
|
postData.Add("userId", "1")
|
||||||
log.Fatal(err)
|
postData.Add("title", "TestToDo")
|
||||||
}
|
|
||||||
|
|
||||||
body, _ := ioutil.ReadAll(resp.Body)
|
// postData := make(map[string]string)
|
||||||
fmt.Println(body)
|
// postData["userId"] = "1"
|
||||||
|
// postData["title"] = "title"
|
||||||
|
|
||||||
|
resp, err := netutil.HttpPost(apiUrl, header, nil, postData)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
body, _ := io.ReadAll(resp.Body)
|
||||||
|
t.Log("response: ", resp.StatusCode, string(body))
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### <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>
|
<b>Signature:</b>
|
||||||
|
|
||||||
@@ -711,9 +729,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>
|
<b>Signature:</b>
|
||||||
|
|
||||||
@@ -750,9 +768,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>
|
<b>Signature:</b>
|
||||||
|
|
||||||
@@ -850,3 +868,124 @@ func main() {
|
|||||||
fmt.Println(toDoResp)
|
fmt.Println(toDoResp)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="UploadFile">UploadFile</span>
|
||||||
|
|
||||||
|
<p>upload the file to a server.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func UploadFile(filepath string, server string) (bool, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/netutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ok, err := netutil.UploadFile("./a.jpg", "http://www.xxx.com/bucket/test")
|
||||||
|
|
||||||
|
fmt.Println(ok)
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="DownloadFile">DownloadFile</span>
|
||||||
|
|
||||||
|
<p>download the file exist in url to a local file.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func DownloadFile(filepath string, url string) error
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/netutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
err := DownloadFile("./lancet_logo.jpg", "https://picx.zhimg.com/v2-fc82a4199749de9cfb71e32e54f489d3_720w.jpg?source=172ae18b")
|
||||||
|
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="IsPingConnected">IsPingConnected</span>
|
||||||
|
|
||||||
|
<p>checks if can ping the specified host or not.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsPingConnected(host string) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/netutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := netutil.IsPingConnected("www.baidu.com")
|
||||||
|
result2 := netutil.IsPingConnected("www.!@#&&&.com")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="IsTelnetConnected">IsTelnetConnected</span>
|
||||||
|
|
||||||
|
<p>Checks if can telnet the specified host or not.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsTelnetConnected(host string, port string) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/netutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := netutil.IsTelnetConnected("www.baidu.com", "80")
|
||||||
|
result2 := netutil.IsTelnetConnected("www.baidu.com", "123")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@@ -45,6 +45,10 @@ import (
|
|||||||
- [HttpPut<sup>Deprecated</sup>](#HttpPut)
|
- [HttpPut<sup>Deprecated</sup>](#HttpPut)
|
||||||
- [HttpPatch<sup>Deprecated</sup>](#HttpPatch)
|
- [HttpPatch<sup>Deprecated</sup>](#HttpPatch)
|
||||||
- [ParseHttpResponse](#ParseHttpResponse)
|
- [ParseHttpResponse](#ParseHttpResponse)
|
||||||
|
- [UploadFile](#UploadFile)
|
||||||
|
- [DownloadFile](#DownloadFile)
|
||||||
|
- [IsPingConnected](#IsPingConnected)
|
||||||
|
- [IsTelnetConnected](#IsTelnetConnected)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -555,23 +559,35 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
type TodoQuery struct {
|
type TodoQuery struct {
|
||||||
Id int `json:"id"`
|
Id int `json:"id"`
|
||||||
UserId int `json:"userId"`
|
UserId int `json:"userId"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Status string
|
||||||
}
|
}
|
||||||
todoQuery := TodoQuery{
|
item := TodoQuery{
|
||||||
Id: 1,
|
Id: 1,
|
||||||
UserId: 2,
|
UserId: 123,
|
||||||
|
Name: "test",
|
||||||
|
Status: "completed",
|
||||||
}
|
}
|
||||||
todoValues := netutil.StructToUrlValues(todoQuery)
|
queryValues := netutil.StructToUrlValues(item)
|
||||||
|
|
||||||
fmt.Println(todoValues.Get("id")) //1
|
fmt.Println(todoValues.Get("id"))
|
||||||
fmt.Println(todoValues.Get("userId")) //2
|
fmt.Println(todoValues.Get("userId"))
|
||||||
|
fmt.Println(todoValues.Get("name"))
|
||||||
|
fmt.Println(todoValues.Get("status"))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1
|
||||||
|
// 123
|
||||||
|
// test
|
||||||
|
//
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### <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>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
@@ -611,9 +627,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>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
@@ -641,28 +657,30 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
url := "https://jsonplaceholder.typicode.com/todos"
|
url := "https://jsonplaceholder.typicode.com/todos"
|
||||||
header := map[string]string{
|
header := map[string]string{
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
}
|
// "Content-Type": "multipart/form-data",
|
||||||
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{}
|
||||||
if err != nil {
|
postData.Add("userId", "1")
|
||||||
log.Fatal(err)
|
postData.Add("title", "TestToDo")
|
||||||
}
|
|
||||||
|
|
||||||
body, _ := ioutil.ReadAll(resp.Body)
|
// postData := make(map[string]string)
|
||||||
|
// postData["userId"] = "1"
|
||||||
|
// postData["title"] = "title"
|
||||||
|
|
||||||
|
resp, err := netutil.HttpPost(apiUrl, header, nil, postData)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
body, _ := io.ReadAll(resp.Body)
|
||||||
fmt.Println(body)
|
fmt.Println(body)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### <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>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
@@ -710,9 +728,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>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
@@ -749,9 +767,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>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
@@ -849,3 +867,124 @@ func main() {
|
|||||||
fmt.Println(toDoResp)
|
fmt.Println(toDoResp)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="UploadFile">UploadFile</span>
|
||||||
|
|
||||||
|
<p>将文件上传指定的server地址。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func UploadFile(filepath string, server string) (bool, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>例子:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/netutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ok, err := netutil.UploadFile("./a.jpg", "http://www.xxx.com/bucket/test")
|
||||||
|
|
||||||
|
fmt.Println(ok)
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="DownloadFile">DownloadFile</span>
|
||||||
|
|
||||||
|
<p>从指定的server地址下载文件。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func DownloadFile(filepath string, url string) error
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>例子:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/netutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
err := DownloadFile("./lancet_logo.jpg", "https://picx.zhimg.com/v2-fc82a4199749de9cfb71e32e54f489d3_720w.jpg?source=172ae18b")
|
||||||
|
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="IsPingConnected">IsPingConnected</span>
|
||||||
|
|
||||||
|
<p>检查能否ping通主机。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsPingConnected(host string) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/netutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := netutil.IsPingConnected("www.baidu.com")
|
||||||
|
result2 := netutil.IsPingConnected("www.!@#&&&.com")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="IsTelnetConnected">IsTelnetConnected</span>
|
||||||
|
|
||||||
|
<p>检查能否telnet到主机。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsTelnetConnected(host string, port string) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/netutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := netutil.IsTelnetConnected("www.baidu.com", "80")
|
||||||
|
result2 := netutil.IsTelnetConnected("www.baidu.com", "123")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@@ -1007,7 +1007,7 @@ func ToSlice(value ...interface{}) interface{}
|
|||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/slice"
|
"github.com/duke-git/lancet/slice"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -1031,7 +1031,7 @@ func ToSlicePointer(value ...interface{}) []*interface{}
|
|||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/slice"
|
"github.com/duke-git/lancet/slice"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
417
docs/strutil.md
417
docs/strutil.md
@@ -28,6 +28,8 @@ import (
|
|||||||
- [BeforeLast](#BeforeLast)
|
- [BeforeLast](#BeforeLast)
|
||||||
- [CamelCase](#CamelCase)
|
- [CamelCase](#CamelCase)
|
||||||
- [Capitalize](#Capitalize)
|
- [Capitalize](#Capitalize)
|
||||||
|
- [ContainsAll](#ContainsAll)
|
||||||
|
- [ContainsAny](#ContainsAny)
|
||||||
- [IsString](#IsString)
|
- [IsString](#IsString)
|
||||||
- [KebabCase](#KebabCase)
|
- [KebabCase](#KebabCase)
|
||||||
- [UpperKebabCase](#UpperKebabCase)
|
- [UpperKebabCase](#UpperKebabCase)
|
||||||
@@ -44,6 +46,17 @@ import (
|
|||||||
- [SplitEx](#SplitEx)
|
- [SplitEx](#SplitEx)
|
||||||
- [SplitWords](#SplitWords)
|
- [SplitWords](#SplitWords)
|
||||||
- [WordCount](#WordCount)
|
- [WordCount](#WordCount)
|
||||||
|
- [RemoveNonPrintable](#RemoveNonPrintable)
|
||||||
|
- [StringToBytes](#StringToBytes)
|
||||||
|
- [BytesToString](#BytesToString)
|
||||||
|
- [IsBlank](#IsBlank)
|
||||||
|
- [HasPrefixAny](#HasPrefixAny)
|
||||||
|
- [HasSuffixAny](#HasSuffixAny)
|
||||||
|
- [IndexOffset](#IndexOffset)
|
||||||
|
- [ReplaceWithMap](#ReplaceWithMap)
|
||||||
|
- [Trim](#Trim)
|
||||||
|
- [SplitAndTrim](#SplitAndTrim)
|
||||||
|
- [HideString](#HideString)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -823,3 +836,407 @@ func main() {
|
|||||||
// 0
|
// 0
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="StringToBytes">StringToBytes</span>
|
||||||
|
|
||||||
|
<p>Converts a string to byte slice without a memory allocation.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func StringToBytes(str string) (b []byte)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := strutil.StringToBytes("abc")
|
||||||
|
result2 := reflect.DeepEqual(result1, []byte{'a', 'b', 'c'})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
// Output:
|
||||||
|
// [97 98 99]
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="BytesToString">BytesToString</span>
|
||||||
|
|
||||||
|
<p>Converts a byte slice to string without a memory allocation.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func BytesToString(bytes []byte) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
bytes := []byte{'a', 'b', 'c'}
|
||||||
|
result := strutil.BytesToString(bytes)
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
// Output:
|
||||||
|
// abc
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="IsBlank">IsBlank</span>
|
||||||
|
|
||||||
|
<p>Checks if a string is whitespace or empty.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsBlank(str string) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := 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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="HasPrefixAny">HasPrefixAny</span>
|
||||||
|
|
||||||
|
<p>Checks if a string starts with any of an array of specified strings.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func HasPrefixAny(str string, prefixes []string) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := strutil.HasPrefixAny("foo bar", []string{"fo", "xyz", "hello"})
|
||||||
|
result2 := strutil.HasPrefixAny("foo bar", []string{"oom", "world"})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="HasSuffixAny">HasSuffixAny</span>
|
||||||
|
|
||||||
|
<p>Checks if a string ends with any of an array of specified strings.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func HasSuffixAny(str string, suffixes []string) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := strutil.HasSuffixAny("foo bar", []string{"bar", "xyz", "hello"})
|
||||||
|
result2 := strutil.HasSuffixAny("foo bar", []string{"oom", "world"})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="IndexOffset">IndexOffset</span>
|
||||||
|
|
||||||
|
<p>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.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IndexOffset(str string, substr string, idxFrom int) int
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
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/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/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/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>HideString 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/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/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/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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ import (
|
|||||||
- [Before](#Before)
|
- [Before](#Before)
|
||||||
- [BeforeLast](#BeforeLast)
|
- [BeforeLast](#BeforeLast)
|
||||||
- [CamelCase](#CamelCase)
|
- [CamelCase](#CamelCase)
|
||||||
|
- [ContainsAll](#ContainsAll)
|
||||||
|
- [ContainsAny](#ContainsAny)
|
||||||
- [Capitalize](#Capitalize)
|
- [Capitalize](#Capitalize)
|
||||||
- [IsString](#IsString)
|
- [IsString](#IsString)
|
||||||
- [KebabCase](#KebabCase)
|
- [KebabCase](#KebabCase)
|
||||||
@@ -44,6 +46,17 @@ import (
|
|||||||
- [SplitEx](#SplitEx)
|
- [SplitEx](#SplitEx)
|
||||||
- [SplitWords](#SplitWords)
|
- [SplitWords](#SplitWords)
|
||||||
- [WordCount](#WordCount)
|
- [WordCount](#WordCount)
|
||||||
|
- [RemoveNonPrintable](#RemoveNonPrintable)
|
||||||
|
- [StringToBytes](#StringToBytes)
|
||||||
|
- [BytesToString](#BytesToString)
|
||||||
|
- [IsBlank](#IsBlank)
|
||||||
|
- [HasPrefixAny](#HasPrefixAny)
|
||||||
|
- [HasSuffixAny](#HasSuffixAny)
|
||||||
|
- [IndexOffset](#IndexOffset)
|
||||||
|
- [ReplaceWithMap](#ReplaceWithMap)
|
||||||
|
- [Trim](#Trim)
|
||||||
|
- [SplitAndTrim](#SplitAndTrim)
|
||||||
|
- [HideString](#HideString)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -824,3 +837,438 @@ func main() {
|
|||||||
// 0
|
// 0
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="RemoveNonPrintable">RemoveNonPrintable</span>
|
||||||
|
|
||||||
|
<p>删除字符串中不可打印的字符。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func RemoveNonPrintable(str string) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := strutil.RemoveNonPrintable("hello\u00a0 \u200bworld\n")
|
||||||
|
result2 := strutil.RemoveNonPrintable("你好😄")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
// Output:
|
||||||
|
// hello world
|
||||||
|
// 你好😄
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="StringToBytes">StringToBytes</span>
|
||||||
|
|
||||||
|
<p>在不分配内存的情况下将字符串转换为字节片。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func StringToBytes(str string) (b []byte)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := strutil.StringToBytes("abc")
|
||||||
|
result2 := reflect.DeepEqual(result1, []byte{'a', 'b', 'c'})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
// Output:
|
||||||
|
// [97 98 99]
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="BytesToString">BytesToString</span>
|
||||||
|
|
||||||
|
<p>在不分配内存的情况下将字节切片转换为字符串。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func BytesToString(bytes []byte) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
bytes := []byte{'a', 'b', 'c'}
|
||||||
|
result := strutil.BytesToString(bytes)
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
// Output:
|
||||||
|
// abc
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="IsBlank">IsBlank</span>
|
||||||
|
|
||||||
|
<p>检查字符串是否为空格或空。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsBlank(str string) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := 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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="HasPrefixAny">HasPrefixAny</span>
|
||||||
|
|
||||||
|
<p>检查字符串是否以指定字符串数组中的任何一个开头。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func HasPrefixAny(str string, prefixes []string) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := strutil.HasPrefixAny("foo bar", []string{"fo", "xyz", "hello"})
|
||||||
|
result2 := strutil.HasPrefixAny("foo bar", []string{"oom", "world"})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="HasSuffixAny">HasSuffixAny</span>
|
||||||
|
|
||||||
|
<p>检查字符串是否以指定字符串数组中的任何一个结尾。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func HasSuffixAny(str string, suffixes []string) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := strutil.HasSuffixAny("foo bar", []string{"bar", "xyz", "hello"})
|
||||||
|
result2 := strutil.HasSuffixAny("foo bar", []string{"oom", "world"})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="IndexOffset">IndexOffset</span>
|
||||||
|
|
||||||
|
<p>将字符串偏移idxFrom后,返回字符串中第一个 substr 实例的索引,如果字符串中不存在 substr,则返回 -1。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IndexOffset(str string, substr string, idxFrom int) int
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
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/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/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/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/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/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/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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@@ -207,14 +207,17 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### <span id="ExecCommand">CompareOsEnv</span>
|
### <span id="ExecCommand">ExecCommand</span>
|
||||||
|
|
||||||
<p>use shell /bin/bash -c(linux) or cmd (windows) to execute command.</p>
|
<p>use shell /bin/bash -c(linux) or cmd (windows) to execute command.</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func ExecCommand(command string) (stdout, stderr string, err error)
|
type (
|
||||||
|
Option func(*exec.Cmd)
|
||||||
|
)
|
||||||
|
func ExecCommand(command string, opts ...Option) (stdout, stderr string, err error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
@@ -226,7 +229,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
out, errout, err := system.ExecCommand("ls")
|
out, errout, err := system.ExecCommand("ls", system.WithForeground())
|
||||||
fmt.Println(out)
|
fmt.Println(out)
|
||||||
fmt.Println(errout)
|
fmt.Println(errout)
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
|
|||||||
@@ -207,14 +207,17 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### <span id="ExecCommand">CompareOsEnv</span>
|
### <span id="ExecCommand">ExecCommand</span>
|
||||||
|
|
||||||
<p>使用shell /bin/bash -c(linux) 或 cmd (windows) 执行shell命令</p>
|
<p>使用shell /bin/bash -c(linux) 或 cmd (windows) 执行shell命令</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func ExecCommand(command string) (stdout, stderr string, err error)
|
type (
|
||||||
|
Option func(*exec.Cmd)
|
||||||
|
)
|
||||||
|
func ExecCommand(command string, opts ...Option) (stdout, stderr string, err error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
@@ -226,7 +229,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
out, errout, err := system.ExecCommand("ls")
|
out, errout, err := system.ExecCommand("ls", system.WithForeground())
|
||||||
fmt.Println(out)
|
fmt.Println(out)
|
||||||
fmt.Println(errout)
|
fmt.Println(errout)
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
|
|||||||
@@ -37,11 +37,14 @@ import (
|
|||||||
- [IsDns](#IsDns)
|
- [IsDns](#IsDns)
|
||||||
- [IsEmail](#IsEmail)
|
- [IsEmail](#IsEmail)
|
||||||
- [IsEmptyString](#IsEmptyString)
|
- [IsEmptyString](#IsEmptyString)
|
||||||
|
- [IsInt](#IsInt)
|
||||||
|
- [IsFloat](#IsFloat)
|
||||||
|
- [IsNumber](#IsNumber)
|
||||||
|
- [IsIntStr](#IsIntStr)
|
||||||
- [IsFloatStr](#IsFloatStr)
|
- [IsFloatStr](#IsFloatStr)
|
||||||
- [IsNumberStr](#IsNumberStr)
|
- [IsNumberStr](#IsNumberStr)
|
||||||
- [IsJSON](#IsJSON)
|
- [IsJSON](#IsJSON)
|
||||||
- [IsRegexMatch](#IsRegexMatch)
|
- [IsRegexMatch](#IsRegexMatch)
|
||||||
- [IsIntStr](#IsIntStr)
|
|
||||||
- [IsIp](#IsIp)
|
- [IsIp](#IsIp)
|
||||||
- [IsIpV4](#IsIpV4)
|
- [IsIpV4](#IsIpV4)
|
||||||
- [IsIpV6](#IsIpV6)
|
- [IsIpV6](#IsIpV6)
|
||||||
@@ -50,6 +53,8 @@ import (
|
|||||||
- [IsWeakPassword](#IsWeakPassword)
|
- [IsWeakPassword](#IsWeakPassword)
|
||||||
- [IsZeroValue](#IsZeroValue)
|
- [IsZeroValue](#IsZeroValue)
|
||||||
- [IsGBK](#IsGBK)
|
- [IsGBK](#IsGBK)
|
||||||
|
- [IsASCII](#IsASCII)
|
||||||
|
- [IsAIsPrintableSCII](#IsPrintable)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -478,6 +483,143 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="IsInt">IsInt</span>
|
||||||
|
|
||||||
|
<p>Check if the value is integer(int, unit) or not.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsInt(v interface{}) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := validator.IsInt("")
|
||||||
|
result2 := validator.IsInt("3")
|
||||||
|
result3 := validator.IsInt(0.1)
|
||||||
|
result4 := validator.IsInt(0)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="IsFloat">IsFloat</span>
|
||||||
|
|
||||||
|
<p>Check if the value is float(float32, float34) or not.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsFloat(v interface{}) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := validator.IsFloat("")
|
||||||
|
result2 := validator.IsFloat("3")
|
||||||
|
result3 := validator.IsFloat(0)
|
||||||
|
result4 := validator.IsFloat(0.1)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="IsNumber">IsNumber</span>
|
||||||
|
|
||||||
|
<p>Check if the value is number(integer, float) or not.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsNumber(v interface{}) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := validator.IsNumber("")
|
||||||
|
result2 := validator.IsNumber("3")
|
||||||
|
result3 := validator.IsNumber(0.1)
|
||||||
|
result4 := validator.IsNumber(0)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="IsIntStr">IsIntStr</span>
|
||||||
|
|
||||||
|
<p>Check if the string can convert to a integer.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsIntStr(s string) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println(validator.IsIntStr("+3")) //true
|
||||||
|
fmt.Println(validator.IsIntStr("-3")) //true
|
||||||
|
fmt.Println(validator.IsIntStr("3.")) //false
|
||||||
|
fmt.Println(validator.IsIntStr("abc")) //false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="IsFloatStr">IsFloatStr</span>
|
### <span id="IsFloatStr">IsFloatStr</span>
|
||||||
|
|
||||||
<p>Check if the string can convert to a float.</p>
|
<p>Check if the string can convert to a float.</p>
|
||||||
@@ -587,32 +729,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### <span id="IsIntStr">IsIntStr</span>
|
|
||||||
|
|
||||||
<p>Check if the string can convert to a integer.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func IsIntStr(s string) bool
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/validator"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Println(validator.IsIntStr("+3")) //true
|
|
||||||
fmt.Println(validator.IsIntStr("-3")) //true
|
|
||||||
fmt.Println(validator.IsIntStr("3.")) //false
|
|
||||||
fmt.Println(validator.IsIntStr("abc")) //false
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="IsIp">IsIp</span>
|
### <span id="IsIp">IsIp</span>
|
||||||
|
|
||||||
<p>Check if the string is a ip address.</p>
|
<p>Check if the string is a ip address.</p>
|
||||||
@@ -778,7 +894,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func IsZeroValue(value any) bool
|
func IsZeroValue(value interface{}) bool
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
@@ -831,3 +947,83 @@ func main() {
|
|||||||
fmt.Println("data encoding is unknown")
|
fmt.Println("data encoding is unknown")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="IsASCII">IsASCII</span>
|
||||||
|
|
||||||
|
<p>Checks if string is all ASCII char.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsASCII(str string) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := validator.IsASCII("ABC")
|
||||||
|
result2 := validator.IsASCII("123")
|
||||||
|
result3 := validator.IsASCII("")
|
||||||
|
result4 := validator.IsASCII("😄")
|
||||||
|
result5 := validator.IsASCII("你好")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="IsPrintable">IsPrintable</span>
|
||||||
|
|
||||||
|
<p>Checks if string is all printable chars.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsPrintable(str string) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := validator.IsPrintable("ABC")
|
||||||
|
result2 := validator.IsPrintable("{id: 123}")
|
||||||
|
result3 := validator.IsPrintable("")
|
||||||
|
result4 := validator.IsPrintable("😄")
|
||||||
|
result5 := validator.IsPrintable("\u0000")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -37,11 +37,14 @@ import (
|
|||||||
- [IsDns](#IsDns)
|
- [IsDns](#IsDns)
|
||||||
- [IsEmail](#IsEmail)
|
- [IsEmail](#IsEmail)
|
||||||
- [IsEmptyString](#IsEmptyString)
|
- [IsEmptyString](#IsEmptyString)
|
||||||
|
- [IsInt](#IsInt)
|
||||||
|
- [IsFloat](#IsFloat)
|
||||||
|
- [IsNumber](#IsNumber)
|
||||||
|
- [IsIntStr](#IsIntStr)
|
||||||
- [IsFloatStr](#IsFloatStr)
|
- [IsFloatStr](#IsFloatStr)
|
||||||
- [IsNumberStr](#IsNumberStr)
|
- [IsNumberStr](#IsNumberStr)
|
||||||
- [IsJSON](#IsJSON)
|
- [IsJSON](#IsJSON)
|
||||||
- [IsRegexMatch](#IsRegexMatch)
|
- [IsRegexMatch](#IsRegexMatch)
|
||||||
- [IsIntStr](#IsIntStr)
|
|
||||||
- [IsIp](#IsIp)
|
- [IsIp](#IsIp)
|
||||||
- [IsIpV4](#IsIpV4)
|
- [IsIpV4](#IsIpV4)
|
||||||
- [IsIpV6](#IsIpV6)
|
- [IsIpV6](#IsIpV6)
|
||||||
@@ -50,6 +53,8 @@ import (
|
|||||||
- [IsWeakPassword](#IsWeakPassword)
|
- [IsWeakPassword](#IsWeakPassword)
|
||||||
- [IsZeroValue](#IsZeroValue)
|
- [IsZeroValue](#IsZeroValue)
|
||||||
- [IsGBK](#IsGBK)
|
- [IsGBK](#IsGBK)
|
||||||
|
- [IsASCII](#IsASCII)
|
||||||
|
- [IsPrintable](#IsPrintable)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -478,6 +483,154 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="IsInt">IsInt</span>
|
||||||
|
|
||||||
|
<p>验证参数是否是整数(int, unit)。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsInt(v interface{}) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := validator.IsInt("")
|
||||||
|
result2 := validator.IsInt("3")
|
||||||
|
result3 := validator.IsInt(0.1)
|
||||||
|
result4 := validator.IsInt(0)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="IsFloat">IsFloat</span>
|
||||||
|
|
||||||
|
<p>验证参数是否是浮点数((float32, float34)。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsFloat(v interface{}) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := validator.IsFloat("")
|
||||||
|
result2 := validator.IsFloat("3")
|
||||||
|
result3 := validator.IsFloat(0)
|
||||||
|
result4 := validator.IsFloat(0.1)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="IsNumber">IsNumber</span>
|
||||||
|
|
||||||
|
<p>验证参数是否是数字(integer or float)</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsNumber(v interface{}) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := validator.IsNumber("")
|
||||||
|
result2 := validator.IsNumber("3")
|
||||||
|
result3 := validator.IsNumber(0.1)
|
||||||
|
result4 := validator.IsNumber(0)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="IsIntStr">IsIntStr</span>
|
||||||
|
|
||||||
|
<p>验证字符串是否是可以转换为整数</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsIntStr(s string) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := validator.IsIntStr("+3")
|
||||||
|
result2 := validator.IsIntStr("-3")
|
||||||
|
result3 := validator.IsIntStr("3.")
|
||||||
|
result4 := validator.IsIntStr("abc")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="IsFloatStr">IsFloatStr</span>
|
### <span id="IsFloatStr">IsFloatStr</span>
|
||||||
|
|
||||||
<p>验证字符串是否是可以转换为浮点数</p>
|
<p>验证字符串是否是可以转换为浮点数</p>
|
||||||
@@ -587,32 +740,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### <span id="IsIntStr">IsIntStr</span>
|
|
||||||
|
|
||||||
<p>验证字符串是否是可以转换为整数</p>
|
|
||||||
|
|
||||||
<b>函数签名:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func IsIntStr(s string) bool
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>例子:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/validator"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Println(validator.IsIntStr("+3")) //true
|
|
||||||
fmt.Println(validator.IsIntStr("-3")) //true
|
|
||||||
fmt.Println(validator.IsIntStr("3.")) //false
|
|
||||||
fmt.Println(validator.IsIntStr("abc")) //false
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="IsIp">IsIp</span>
|
### <span id="IsIp">IsIp</span>
|
||||||
|
|
||||||
<p>验证字符串是否是ip地址</p>
|
<p>验证字符串是否是ip地址</p>
|
||||||
@@ -778,7 +905,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func IsZeroValue(value any) bool
|
func IsZeroValue(value interface{}) bool
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
@@ -831,3 +958,82 @@ func main() {
|
|||||||
fmt.Println("data encoding is unknown")
|
fmt.Println("data encoding is unknown")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
### <span id="IsASCII">IsASCII</span>
|
||||||
|
|
||||||
|
<p>验证字符串全部为ASCII字符。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsASCII(str string) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := validator.IsASCII("ABC")
|
||||||
|
result2 := validator.IsASCII("123")
|
||||||
|
result3 := validator.IsASCII("")
|
||||||
|
result4 := validator.IsASCII("😄")
|
||||||
|
result5 := validator.IsASCII("你好")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="IsPrintable">IsPrintable</span>
|
||||||
|
|
||||||
|
<p>检查字符串是否全部为可打印字符。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsPrintable(str string) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := validator.IsPrintable("ABC")
|
||||||
|
result2 := validator.IsPrintable("{id: 123}")
|
||||||
|
result3 := validator.IsPrintable("")
|
||||||
|
result4 := validator.IsPrintable("😄")
|
||||||
|
result5 := validator.IsPrintable("\u0000")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
fmt.Println(result5)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
135
fileutil/file.go
135
fileutil/file.go
@@ -7,6 +7,11 @@ package fileutil
|
|||||||
import (
|
import (
|
||||||
"archive/zip"
|
"archive/zip"
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"crypto/sha1"
|
||||||
|
"crypto/sha256"
|
||||||
|
"crypto/sha512"
|
||||||
|
"encoding/csv"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@@ -16,6 +21,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -88,7 +94,7 @@ func CopyFile(srcFilePath string, dstFilePath string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//ClearFile write empty string to path file
|
// ClearFile write empty string to path file
|
||||||
func ClearFile(path string) error {
|
func ClearFile(path string) error {
|
||||||
f, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
f, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -100,7 +106,7 @@ func ClearFile(path string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//ReadFileToString return string of file content
|
// ReadFileToString return string of file content
|
||||||
func ReadFileToString(path string) (string, error) {
|
func ReadFileToString(path string) (string, error) {
|
||||||
bytes, err := ioutil.ReadFile(path)
|
bytes, err := ioutil.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -318,3 +324,128 @@ func MiMeType(file interface{}) string {
|
|||||||
}
|
}
|
||||||
return mediatype
|
return mediatype
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CurrentPath return current absolute path.
|
||||||
|
func CurrentPath() string {
|
||||||
|
var absPath string
|
||||||
|
_, filename, _, ok := runtime.Caller(1)
|
||||||
|
if ok {
|
||||||
|
absPath = path.Dir(filename)
|
||||||
|
}
|
||||||
|
|
||||||
|
return absPath
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsZipFile checks if file is zip or not.
|
||||||
|
func IsZipFile(filepath string) bool {
|
||||||
|
f, err := os.Open(filepath)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
buf := make([]byte, 4)
|
||||||
|
if n, err := f.Read(buf); err != nil || n < 4 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes.Equal(buf, []byte("PK\x03\x04"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileSize returns file size in bytes.
|
||||||
|
func FileSize(path string) (int64, error) {
|
||||||
|
f, err := os.Stat(path)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return f.Size(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MTime returns file modified time.
|
||||||
|
func MTime(filepath string) (int64, error) {
|
||||||
|
f, err := os.Stat(filepath)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return f.ModTime().Unix(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MTime returns file sha value, param `shaType` should be 1, 256 or 512.
|
||||||
|
func Sha(filepath string, shaType ...int) (string, error) {
|
||||||
|
file, err := os.Open(filepath)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
h := sha1.New()
|
||||||
|
if len(shaType) > 0 {
|
||||||
|
if shaType[0] == 1 {
|
||||||
|
h = sha1.New()
|
||||||
|
} else if shaType[0] == 256 {
|
||||||
|
h = sha256.New()
|
||||||
|
} else if shaType[0] == 512 {
|
||||||
|
h = sha512.New()
|
||||||
|
} else {
|
||||||
|
return "", errors.New("param `shaType` should be 1, 256 or 512.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = io.Copy(h, file)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
sha := fmt.Sprintf("%x", h.Sum(nil))
|
||||||
|
|
||||||
|
return sha, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadCsvFile read file content into slice.
|
||||||
|
func ReadCsvFile(filepath string) ([][]string, error) {
|
||||||
|
f, err := os.Open(filepath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
csvReader := csv.NewReader(f)
|
||||||
|
records, err := csvReader.ReadAll()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return records, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteStringToFile write string to target file.
|
||||||
|
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.
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -221,3 +221,124 @@ func TestMiMeType(t *testing.T) {
|
|||||||
assert.Equal("text/plain; charset=utf-8", MiMeType(f))
|
assert.Equal("text/plain; charset=utf-8", MiMeType(f))
|
||||||
assert.Equal("text/plain; charset=utf-8", MiMeType("./file.go"))
|
assert.Equal("text/plain; charset=utf-8", MiMeType("./file.go"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCurrentPath(t *testing.T) {
|
||||||
|
absPath := CurrentPath()
|
||||||
|
t.Log(absPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsZipFile(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestIsZipFile")
|
||||||
|
|
||||||
|
assert.Equal(false, IsZipFile("./file.go"))
|
||||||
|
assert.Equal(true, IsZipFile("./testdata/file.go.zip"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFileSize(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestFileSize")
|
||||||
|
|
||||||
|
size, err := FileSize("./testdata/test.txt")
|
||||||
|
|
||||||
|
assert.IsNil(err)
|
||||||
|
assert.Equal(int64(20), size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMTime(t *testing.T) {
|
||||||
|
// assert := internal.NewAssert(t, "TestMTime")
|
||||||
|
|
||||||
|
// mtime, err := MTime("./testdata/test.txt")
|
||||||
|
|
||||||
|
// assert.IsNil(err)
|
||||||
|
// assert.Equal(int64(1682478195), mtime)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSha(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestSha")
|
||||||
|
|
||||||
|
sha1, err := Sha("./testdata/test.txt", 1)
|
||||||
|
sha256, err := Sha("./testdata/test.txt", 256)
|
||||||
|
sha512, err := Sha("./testdata/test.txt", 512)
|
||||||
|
|
||||||
|
assert.IsNil(err)
|
||||||
|
assert.Equal("dda3cf10c5a6ff6c6659a497bf7261b287af2bc7", sha1)
|
||||||
|
assert.Equal("aa6d0a3fbc3442c228d606da09e0c1dc98c69a1cac3da1909199e0266171df35", sha256)
|
||||||
|
assert.Equal("d22aba2a1b7a2e2f512756255cc1c3708905646920cb1eb95e45b531ba74774dbbb89baebf1f716220eb9cf4908f1cfc5b2a01267704d9a59f59d77cab609870", sha512)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReadCsvFile(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestReadCsvFile")
|
||||||
|
|
||||||
|
content, err := ReadCsvFile("./testdata/test.csv")
|
||||||
|
t.Log(content)
|
||||||
|
|
||||||
|
assert.IsNil(err)
|
||||||
|
|
||||||
|
assert.Equal(3, len(content))
|
||||||
|
assert.Equal(3, len(content[0]))
|
||||||
|
assert.Equal("Bob", content[0][0])
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|||||||
BIN
fileutil/testdata/file.go.zip
vendored
Normal file
BIN
fileutil/testdata/file.go.zip
vendored
Normal file
Binary file not shown.
3
fileutil/testdata/test.csv
vendored
Normal file
3
fileutil/testdata/test.csv
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
Bob, 12, male
|
||||||
|
Duke, 14, male
|
||||||
|
Lucy, 16, female
|
||||||
|
1
fileutil/testdata/test.txt
vendored
Normal file
1
fileutil/testdata/test.txt
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
this is a test file.
|
||||||
@@ -4,14 +4,176 @@
|
|||||||
// Package formatter implements some functions to format string, struct.
|
// Package formatter implements some functions to format string, struct.
|
||||||
package formatter
|
package formatter
|
||||||
|
|
||||||
import "strings"
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
// Comma add comma to number by every 3 numbers from right. ahead by symbol char
|
"github.com/duke-git/lancet/convertor"
|
||||||
func Comma(v interface{}, symbol string) string {
|
"github.com/duke-git/lancet/strutil"
|
||||||
s := numString(v)
|
"github.com/duke-git/lancet/validator"
|
||||||
dotIndex := strings.Index(s, ".")
|
)
|
||||||
if dotIndex != -1 {
|
|
||||||
return symbol + commaString(s[:dotIndex]) + s[dotIndex:]
|
// Comma add comma to a number value by every 3 numbers from right. ahead by symbol char.
|
||||||
|
// if value is invalid number string eg "aa", return empty string
|
||||||
|
// Comma("12345", "$") => "$12,345", Comma(12345, "$") => "$12,345"
|
||||||
|
func Comma(value interface{}, symbol string) string {
|
||||||
|
if validator.IsInt(value) {
|
||||||
|
v, err := convertor.ToInt(value)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return symbol + commaInt(v)
|
||||||
}
|
}
|
||||||
return symbol + commaString(s)
|
|
||||||
|
if validator.IsFloat(value) {
|
||||||
|
v, err := convertor.ToFloat(value)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return symbol + commaFloat(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if strutil.IsString(value) {
|
||||||
|
v := fmt.Sprintf("%v", value)
|
||||||
|
if validator.IsNumberStr(v) {
|
||||||
|
return symbol + commaStr(v)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pretty data to JSON string.
|
||||||
|
func Pretty(v interface{}) (string, error) {
|
||||||
|
out, err := json.MarshalIndent(v, "", " ")
|
||||||
|
return string(out), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrettyToWriter pretty encode data to writer.
|
||||||
|
func PrettyToWriter(v interface{}, out io.Writer) error {
|
||||||
|
enc := json.NewEncoder(out)
|
||||||
|
enc.SetIndent("", " ")
|
||||||
|
|
||||||
|
if err := enc.Encode(v); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://en.wikipedia.org/wiki/Binary_prefix
|
||||||
|
const (
|
||||||
|
// Decimal
|
||||||
|
UnitB = 1
|
||||||
|
UnitKB = 1000
|
||||||
|
UnitMB = 1000 * UnitKB
|
||||||
|
UnitGB = 1000 * UnitMB
|
||||||
|
UnitTB = 1000 * UnitGB
|
||||||
|
UnitPB = 1000 * UnitTB
|
||||||
|
UnitEB = 1000 * UnitPB
|
||||||
|
|
||||||
|
// Binary
|
||||||
|
UnitBiB = 1
|
||||||
|
UnitKiB = 1024
|
||||||
|
UnitMiB = 1024 * UnitKiB
|
||||||
|
UnitGiB = 1024 * UnitMiB
|
||||||
|
UnitTiB = 1024 * UnitGiB
|
||||||
|
UnitPiB = 1024 * UnitTiB
|
||||||
|
UnitEiB = 1024 * UnitPiB
|
||||||
|
)
|
||||||
|
|
||||||
|
// type byteUnitMap map[byte]int64
|
||||||
|
|
||||||
|
var (
|
||||||
|
decimalByteMap = map[string]uint64{
|
||||||
|
"b": UnitB,
|
||||||
|
"kb": UnitKB,
|
||||||
|
"mb": UnitMB,
|
||||||
|
"gb": UnitGB,
|
||||||
|
"tb": UnitTB,
|
||||||
|
"pb": UnitPB,
|
||||||
|
"eb": UnitEB,
|
||||||
|
|
||||||
|
// Without suffix
|
||||||
|
"": UnitB,
|
||||||
|
"k": UnitKB,
|
||||||
|
"m": UnitMB,
|
||||||
|
"g": UnitGB,
|
||||||
|
"t": UnitTB,
|
||||||
|
"p": UnitPB,
|
||||||
|
"e": UnitEB,
|
||||||
|
}
|
||||||
|
|
||||||
|
binaryByteMap = map[string]uint64{
|
||||||
|
"bi": UnitBiB,
|
||||||
|
"kib": UnitKiB,
|
||||||
|
"mib": UnitMiB,
|
||||||
|
"gib": UnitGiB,
|
||||||
|
"tib": UnitTiB,
|
||||||
|
"pib": UnitPiB,
|
||||||
|
"eib": UnitEiB,
|
||||||
|
|
||||||
|
// Without suffix
|
||||||
|
"": UnitBiB,
|
||||||
|
"ki": UnitKiB,
|
||||||
|
"mi": UnitMiB,
|
||||||
|
"gi": UnitGiB,
|
||||||
|
"ti": UnitTiB,
|
||||||
|
"pi": UnitPiB,
|
||||||
|
"ei": UnitEiB,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
decimalByteUnits = []string{"B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
|
||||||
|
binaryByteUnits = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}
|
||||||
|
)
|
||||||
|
|
||||||
|
// DecimalBytes returns a human readable byte size under decimal standard (base 1000)
|
||||||
|
// The precision parameter specifies the number of digits after the decimal point, which defaults to 4.
|
||||||
|
// Play: https://go.dev/play/p/FPXs1suwRcs
|
||||||
|
func DecimalBytes(size float64, precision ...int) string {
|
||||||
|
p := 5
|
||||||
|
if len(precision) > 0 {
|
||||||
|
p = precision[0] + 1
|
||||||
|
}
|
||||||
|
size, unit := calculateByteSize(size, 1000.0, decimalByteUnits)
|
||||||
|
|
||||||
|
return fmt.Sprintf("%.*g%s", p, size, unit)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BinaryBytes returns a human-readable byte size under binary standard (base 1024)
|
||||||
|
// The precision parameter specifies the number of digits after the decimal point, which defaults to 4.
|
||||||
|
func BinaryBytes(size float64, precision ...int) string {
|
||||||
|
p := 5
|
||||||
|
if len(precision) > 0 {
|
||||||
|
p = precision[0] + 1
|
||||||
|
}
|
||||||
|
size, unit := calculateByteSize(size, 1024.0, binaryByteUnits)
|
||||||
|
|
||||||
|
return fmt.Sprintf("%.*g%s", p, size, unit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func calculateByteSize(size float64, base float64, byteUnits []string) (float64, string) {
|
||||||
|
i := 0
|
||||||
|
unitsLimit := len(byteUnits) - 1
|
||||||
|
for size >= base && i < unitsLimit {
|
||||||
|
size = size / base
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return size, byteUnits[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseDecimalBytes return the human readable bytes size string into the amount it represents(base 1000).
|
||||||
|
// ParseDecimalBytes("42 MB") -> 42000000, nil
|
||||||
|
func ParseDecimalBytes(size string) (uint64, error) {
|
||||||
|
return parseBytes(size, "decimal")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseBinaryBytes return the human readable bytes size string into the amount it represents(base 1024).
|
||||||
|
// ParseBinaryBytes("42 mib") -> 44040192, nil
|
||||||
|
func ParseBinaryBytes(size string) (uint64, error) {
|
||||||
|
return parseBytes(size, "binary")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,134 @@
|
|||||||
package formatter
|
package formatter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"math"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
func commaString(s string) string {
|
// see https://github.com/dustin/go-humanize/blob/master/comma.go
|
||||||
|
func commaInt(v int64) string {
|
||||||
|
sign := ""
|
||||||
|
|
||||||
|
// Min int64 can't be negated to a usable value, so it has to be special cased.
|
||||||
|
if v == math.MinInt64 {
|
||||||
|
return "-9,223,372,036,854,775,808"
|
||||||
|
}
|
||||||
|
|
||||||
|
if v < 0 {
|
||||||
|
sign = "-"
|
||||||
|
v = 0 - v
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := []string{"", "", "", "", "", "", ""}
|
||||||
|
j := len(parts) - 1
|
||||||
|
|
||||||
|
for v > 999 {
|
||||||
|
parts[j] = strconv.FormatInt(v%1000, 10)
|
||||||
|
switch len(parts[j]) {
|
||||||
|
case 2:
|
||||||
|
parts[j] = "0" + parts[j]
|
||||||
|
case 1:
|
||||||
|
parts[j] = "00" + parts[j]
|
||||||
|
}
|
||||||
|
v = v / 1000
|
||||||
|
j--
|
||||||
|
}
|
||||||
|
parts[j] = strconv.Itoa(int(v))
|
||||||
|
return sign + strings.Join(parts[j:], ",")
|
||||||
|
}
|
||||||
|
|
||||||
|
func commaFloat(v float64) string {
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
if v < 0 {
|
||||||
|
buf.Write([]byte{'-'})
|
||||||
|
v = 0 - v
|
||||||
|
}
|
||||||
|
|
||||||
|
comma := []byte{','}
|
||||||
|
|
||||||
|
parts := strings.Split(strconv.FormatFloat(v, 'f', -1, 64), ".")
|
||||||
|
pos := 0
|
||||||
|
if len(parts[0])%3 != 0 {
|
||||||
|
pos += len(parts[0]) % 3
|
||||||
|
buf.WriteString(parts[0][:pos])
|
||||||
|
buf.Write(comma)
|
||||||
|
}
|
||||||
|
for ; pos < len(parts[0]); pos += 3 {
|
||||||
|
buf.WriteString(parts[0][pos : pos+3])
|
||||||
|
buf.Write(comma)
|
||||||
|
}
|
||||||
|
buf.Truncate(buf.Len() - 1)
|
||||||
|
|
||||||
|
if len(parts) > 1 {
|
||||||
|
buf.Write([]byte{'.'})
|
||||||
|
buf.WriteString(parts[1])
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func commaStr(s string) string {
|
||||||
|
dotIndex := strings.Index(s, ".")
|
||||||
|
if dotIndex != -1 {
|
||||||
|
return commaStrRecursive(s[:dotIndex]) + s[dotIndex:]
|
||||||
|
}
|
||||||
|
|
||||||
|
return commaStrRecursive(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func commaStrRecursive(s string) string {
|
||||||
if len(s) <= 3 {
|
if len(s) <= 3 {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
return commaString(s[:len(s)-3]) + "," + commaString(s[len(s)-3:])
|
return commaStrRecursive(s[:len(s)-3]) + "," + commaStrRecursive(s[len(s)-3:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func numString(value interface{}) string {
|
// see https://github.com/dustin/go-humanize/blob/master/bytes.go
|
||||||
switch reflect.TypeOf(value).Kind() {
|
func parseBytes(s string, kind string) (uint64, error) {
|
||||||
case reflect.Int, reflect.Int64, reflect.Float32, reflect.Float64:
|
lastDigit := 0
|
||||||
return fmt.Sprintf("%v", value)
|
hasComma := false
|
||||||
case reflect.String:
|
for _, r := range s {
|
||||||
{
|
if !(unicode.IsDigit(r) || r == '.' || r == ',') {
|
||||||
sv := fmt.Sprintf("%v", value)
|
break
|
||||||
if strings.Contains(sv, ".") {
|
|
||||||
_, err := strconv.ParseFloat(sv, 64)
|
|
||||||
if err == nil {
|
|
||||||
return sv
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_, err := strconv.ParseInt(sv, 10, 64)
|
|
||||||
if err == nil {
|
|
||||||
return sv
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
default:
|
if r == ',' {
|
||||||
return ""
|
hasComma = true
|
||||||
|
}
|
||||||
|
lastDigit++
|
||||||
}
|
}
|
||||||
return ""
|
|
||||||
|
num := s[:lastDigit]
|
||||||
|
if hasComma {
|
||||||
|
num = strings.Replace(num, ",", "", -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := strconv.ParseFloat(num, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
extra := strings.ToLower(strings.TrimSpace(s[lastDigit:]))
|
||||||
|
|
||||||
|
if kind == "decimal" {
|
||||||
|
if m, ok := decimalByteMap[extra]; ok {
|
||||||
|
f *= float64(m)
|
||||||
|
if f >= math.MaxUint64 {
|
||||||
|
return 0, fmt.Errorf("too large: %v", s)
|
||||||
|
}
|
||||||
|
return uint64(f), nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if m, ok := binaryByteMap[extra]; ok {
|
||||||
|
f *= float64(m)
|
||||||
|
if f >= math.MaxUint64 {
|
||||||
|
return 0, fmt.Errorf("too large: %v", s)
|
||||||
|
}
|
||||||
|
return uint64(f), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, fmt.Errorf("unhandled size name: %v", extra)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package formatter
|
package formatter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/internal"
|
"github.com/duke-git/lancet/internal"
|
||||||
@@ -12,12 +13,148 @@ func TestComma(t *testing.T) {
|
|||||||
assert.Equal("", Comma("", ""))
|
assert.Equal("", Comma("", ""))
|
||||||
assert.Equal("", Comma("aa", ""))
|
assert.Equal("", Comma("aa", ""))
|
||||||
assert.Equal("", Comma("aa.a", ""))
|
assert.Equal("", Comma("aa.a", ""))
|
||||||
assert.Equal("", Comma([]int{1}, ""))
|
|
||||||
assert.Equal("123", Comma("123", ""))
|
assert.Equal("123", Comma("123", ""))
|
||||||
assert.Equal("12,345", Comma("12345", ""))
|
assert.Equal("12,345", Comma("12345", ""))
|
||||||
|
assert.Equal("12,345.6789", Comma("12345.6789", ""))
|
||||||
|
assert.Equal("123,456,789,000", Comma("123456789000", ""))
|
||||||
|
assert.Equal("12,345,678.9", Comma("12345678.9", ""))
|
||||||
|
|
||||||
assert.Equal("12,345", Comma(12345, ""))
|
assert.Equal("12,345", Comma(12345, ""))
|
||||||
assert.Equal("$12,345", Comma(12345, "$"))
|
assert.Equal("$12,345", Comma(12345, "$"))
|
||||||
assert.Equal("¥12,345", Comma(12345, "¥"))
|
assert.Equal("¥12,345", Comma(12345, "¥"))
|
||||||
assert.Equal("12,345.6789", Comma(12345.6789, ""))
|
assert.Equal("12,345.6789", Comma(12345.6789, ""))
|
||||||
|
assert.Equal("12,345.6789", Comma(+12345.6789, ""))
|
||||||
|
assert.Equal("12,345,678.9", Comma(12345678.9, ""))
|
||||||
|
assert.Equal("123,456,789,000", Comma(123456789000, ""))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPretty(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestPretty")
|
||||||
|
|
||||||
|
cases := []interface{}{
|
||||||
|
"",
|
||||||
|
"abc",
|
||||||
|
123,
|
||||||
|
[]string{"a", "b", "c"},
|
||||||
|
map[string]int{"a": 1},
|
||||||
|
struct {
|
||||||
|
Abc int `json:"abc"`
|
||||||
|
}{Abc: 123},
|
||||||
|
}
|
||||||
|
|
||||||
|
expects := []string{
|
||||||
|
"\"\"",
|
||||||
|
`"abc"`,
|
||||||
|
"123",
|
||||||
|
"[\n \"a\",\n \"b\",\n \"c\"\n]",
|
||||||
|
"{\n \"a\": 1\n}",
|
||||||
|
"{\n \"abc\": 123\n}",
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, v := range cases {
|
||||||
|
result, err := Pretty(v)
|
||||||
|
|
||||||
|
assert.IsNil(err)
|
||||||
|
|
||||||
|
t.Log("result -> ", result)
|
||||||
|
assert.Equal(expects[i], result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrettyToWriter(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestPrettyToWriter")
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Aage uint `json:"age"`
|
||||||
|
}
|
||||||
|
user := User{Name: "King", Aage: 10000}
|
||||||
|
|
||||||
|
expects := "{\n \"name\": \"King\",\n \"age\": 10000\n}\n"
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
err := PrettyToWriter(user, buf)
|
||||||
|
|
||||||
|
assert.IsNil(err)
|
||||||
|
assert.Equal(expects, buf.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDecimalBytes(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestDecimalBytes")
|
||||||
|
|
||||||
|
assert.Equal("1KB", DecimalBytes(1000))
|
||||||
|
assert.Equal("1.024KB", DecimalBytes(1024))
|
||||||
|
assert.Equal("1.2346MB", DecimalBytes(1234567))
|
||||||
|
assert.Equal("1.235MB", DecimalBytes(1234567, 3))
|
||||||
|
assert.Equal("1.123GB", DecimalBytes(float64(1.123*UnitGB)))
|
||||||
|
assert.Equal("2.123TB", DecimalBytes(float64(2.123*UnitTB)))
|
||||||
|
assert.Equal("3.123PB", DecimalBytes(float64(3.123*UnitPB)))
|
||||||
|
assert.Equal("4.123EB", DecimalBytes(float64(4.123*UnitEB)))
|
||||||
|
assert.Equal("1EB", DecimalBytes(float64(1000*UnitPB)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBinaryBytes(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestBinaryBytes")
|
||||||
|
|
||||||
|
assert.Equal("1KiB", BinaryBytes(1024))
|
||||||
|
assert.Equal("1MiB", BinaryBytes(1024*1024))
|
||||||
|
assert.Equal("1.1774MiB", BinaryBytes(1234567))
|
||||||
|
assert.Equal("1.18MiB", BinaryBytes(1234567, 2))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseDecimalBytes(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestParseDecimalBytes")
|
||||||
|
|
||||||
|
cases := map[string]uint64{
|
||||||
|
"12": uint64(12),
|
||||||
|
"12 k": uint64(12000),
|
||||||
|
"12 kb": uint64(12000),
|
||||||
|
"12kb": uint64(12000),
|
||||||
|
"12k": uint64(12000),
|
||||||
|
"12K": uint64(12000),
|
||||||
|
"12KB": uint64(12000),
|
||||||
|
"12 K": uint64(12000),
|
||||||
|
"12 KB": uint64(12000),
|
||||||
|
"12 Kb": uint64(12000),
|
||||||
|
"12 kB": uint64(12000),
|
||||||
|
"12.2 KB": uint64(12200),
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range cases {
|
||||||
|
result, err := ParseDecimalBytes(k)
|
||||||
|
assert.Equal(v, result)
|
||||||
|
assert.IsNil(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := ParseDecimalBytes("12 AB")
|
||||||
|
assert.IsNotNil(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseBinaryBytes(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestParseBinaryBytes")
|
||||||
|
|
||||||
|
cases := map[string]uint64{
|
||||||
|
"12": uint64(12),
|
||||||
|
"12 ki": uint64(12288),
|
||||||
|
"12 kib": uint64(12288),
|
||||||
|
"12kib": uint64(12288),
|
||||||
|
"12ki": uint64(12288),
|
||||||
|
"12KI": uint64(12288),
|
||||||
|
"12KIB": uint64(12288),
|
||||||
|
"12KiB": uint64(12288),
|
||||||
|
"12 Ki": uint64(12288),
|
||||||
|
"12 KiB": uint64(12288),
|
||||||
|
"12 Kib": uint64(12288),
|
||||||
|
"12 kiB": uint64(12288),
|
||||||
|
"12.2 KiB": uint64(12492),
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range cases {
|
||||||
|
result, err := ParseBinaryBytes(k)
|
||||||
|
assert.Equal(v, result)
|
||||||
|
assert.IsNil(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := ParseDecimalBytes("12 AB")
|
||||||
|
assert.IsNotNil(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
@@ -36,6 +37,52 @@ func (a *Assert) Equal(expected, actual interface{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EqualValues asserts that two objects are equal or convertable to the same types and equal.
|
||||||
|
// https://github.com/stretchr/testify/assert/assertions.go
|
||||||
|
func (a *Assert) EqualValues(expected, actual interface{}) {
|
||||||
|
if !objectsAreEqualValues(expected, actual) {
|
||||||
|
makeTestFailed(a.T, a.CaseName, expected, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func objectsAreEqualValues(expected, actual interface{}) bool {
|
||||||
|
if objectsAreEqual(expected, actual) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
actualType := reflect.TypeOf(actual)
|
||||||
|
if actualType == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
expectedValue := reflect.ValueOf(expected)
|
||||||
|
if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) {
|
||||||
|
// Attempt comparison after type conversion
|
||||||
|
return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func objectsAreEqual(expected, actual interface{}) bool {
|
||||||
|
if expected == nil || actual == nil {
|
||||||
|
return expected == actual
|
||||||
|
}
|
||||||
|
|
||||||
|
exp, ok := expected.([]byte)
|
||||||
|
if !ok {
|
||||||
|
return reflect.DeepEqual(expected, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
act, ok := actual.([]byte)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if exp == nil || act == nil {
|
||||||
|
return exp == nil && act == nil
|
||||||
|
}
|
||||||
|
return bytes.Equal(exp, act)
|
||||||
|
}
|
||||||
|
|
||||||
// NotEqual check if expected is not equal with actual
|
// NotEqual check if expected is not equal with actual
|
||||||
func (a *Assert) NotEqual(expected, actual interface{}) {
|
func (a *Assert) NotEqual(expected, actual interface{}) {
|
||||||
if compare(expected, actual) == compareEqual {
|
if compare(expected, actual) == compareEqual {
|
||||||
|
|||||||
@@ -90,3 +90,102 @@ func TruncRound(x float64, n int) float64 {
|
|||||||
res, _ := strconv.ParseFloat(newFloat, 64)
|
res, _ := strconv.ParseFloat(newFloat, 64)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AngleToRadian converts angle value to radian value.
|
||||||
|
func AngleToRadian(angle float64) float64 {
|
||||||
|
radian := angle * (math.Pi / 180)
|
||||||
|
return radian
|
||||||
|
}
|
||||||
|
|
||||||
|
// RadianToAngle converts radian value to angle value.
|
||||||
|
func RadianToAngle(radian float64) float64 {
|
||||||
|
angle := radian * (180 / math.Pi)
|
||||||
|
return angle
|
||||||
|
}
|
||||||
|
|
||||||
|
// PointDistance get two points distance.
|
||||||
|
func PointDistance(x1, y1, x2, y2 float64) float64 {
|
||||||
|
a := x1 - x2
|
||||||
|
b := y1 - y2
|
||||||
|
c := math.Pow(a, 2) + math.Pow(b, 2)
|
||||||
|
|
||||||
|
return math.Sqrt(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsPrimes checks if number is prime number.
|
||||||
|
func IsPrime(n int) bool {
|
||||||
|
if n < 2 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 2; i <= int(math.Sqrt(float64(n))); i++ {
|
||||||
|
if n%i == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// GCD return greatest common divisor (GCD) of integers.
|
||||||
|
func GCD(integers ...int) int {
|
||||||
|
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(a, b int) int {
|
||||||
|
if b == 0 {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
return gcd(b, a%b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LCM return Least Common Multiple (LCM) of integers.
|
||||||
|
func LCM(integers ...int) int {
|
||||||
|
result := integers[0]
|
||||||
|
|
||||||
|
for k := range integers {
|
||||||
|
result = lcm(integers[k], result)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// find Least Common Multiple (LCM) via GCD.
|
||||||
|
func lcm(a, b int) int {
|
||||||
|
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.
|
||||||
|
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.
|
||||||
|
func Sin(radian float64, precision ...int) float64 {
|
||||||
|
return Cos((math.Pi / 2) - radian)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package mathutil
|
package mathutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/internal"
|
"github.com/duke-git/lancet/internal"
|
||||||
@@ -70,3 +71,104 @@ func TestTruncRound(t *testing.T) {
|
|||||||
assert.Equal(TruncRound(0.125, 3), float64(0.125))
|
assert.Equal(TruncRound(0.125, 3), float64(0.125))
|
||||||
assert.Equal(TruncRound(33.33333, 2), float64(33.33))
|
assert.Equal(TruncRound(33.33333, 2), float64(33.33))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAngleToRadian(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestAngleToRadian")
|
||||||
|
|
||||||
|
result1 := AngleToRadian(45)
|
||||||
|
result2 := AngleToRadian(90)
|
||||||
|
result3 := AngleToRadian(180)
|
||||||
|
|
||||||
|
assert.Equal(0.7853981633974483, result1)
|
||||||
|
assert.Equal(1.5707963267948966, result2)
|
||||||
|
assert.Equal(3.141592653589793, result3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRadianToAngle(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestAngleToRadian")
|
||||||
|
|
||||||
|
result1 := RadianToAngle(math.Pi)
|
||||||
|
result2 := RadianToAngle(math.Pi / 2)
|
||||||
|
result3 := RadianToAngle(math.Pi / 4)
|
||||||
|
|
||||||
|
assert.Equal(float64(180), result1)
|
||||||
|
assert.Equal(float64(90), result2)
|
||||||
|
assert.Equal(float64(45), result3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPointDistance(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestPointDistance")
|
||||||
|
|
||||||
|
result1 := PointDistance(1, 1, 4, 5)
|
||||||
|
|
||||||
|
assert.Equal(float64(5), result1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsPrime(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestIsPrime")
|
||||||
|
|
||||||
|
assert.Equal(false, IsPrime(-1))
|
||||||
|
assert.Equal(false, IsPrime(0))
|
||||||
|
assert.Equal(false, IsPrime(1))
|
||||||
|
assert.Equal(true, IsPrime(2))
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
|||||||
229
netutil/http.go
229
netutil/http.go
@@ -13,30 +13,39 @@
|
|||||||
package netutil
|
package netutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"reflect"
|
||||||
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/slice"
|
||||||
)
|
)
|
||||||
|
|
||||||
//HttpGet send get http request
|
// HttpGet send get http request
|
||||||
func HttpGet(url string, params ...interface{}) (*http.Response, error) {
|
func HttpGet(url string, params ...interface{}) (*http.Response, error) {
|
||||||
return doHttpRequest(http.MethodGet, url, params...)
|
return doHttpRequest(http.MethodGet, url, params...)
|
||||||
}
|
}
|
||||||
|
|
||||||
//HttpPost send post http request
|
// HttpPost send post http request
|
||||||
func HttpPost(url string, params ...interface{}) (*http.Response, error) {
|
func HttpPost(url string, params ...interface{}) (*http.Response, error) {
|
||||||
return doHttpRequest(http.MethodPost, url, params...)
|
return doHttpRequest(http.MethodPost, url, params...)
|
||||||
}
|
}
|
||||||
|
|
||||||
//HttpPut send put http request
|
// HttpPut send put http request
|
||||||
func HttpPut(url string, params ...interface{}) (*http.Response, error) {
|
func HttpPut(url string, params ...interface{}) (*http.Response, error) {
|
||||||
return doHttpRequest(http.MethodPut, url, params...)
|
return doHttpRequest(http.MethodPut, url, params...)
|
||||||
}
|
}
|
||||||
|
|
||||||
//HttpDelete send delete http request
|
// HttpDelete send delete http request
|
||||||
func HttpDelete(url string, params ...interface{}) (*http.Response, error) {
|
func HttpDelete(url string, params ...interface{}) (*http.Response, error) {
|
||||||
return doHttpRequest(http.MethodDelete, url, params...)
|
return doHttpRequest(http.MethodDelete, url, params...)
|
||||||
}
|
}
|
||||||
@@ -77,3 +86,215 @@ func ConvertMapToQueryString(param map[string]interface{}) string {
|
|||||||
}
|
}
|
||||||
return build.String()
|
return build.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type HttpRequest struct {
|
||||||
|
RawURL string
|
||||||
|
Method string
|
||||||
|
Headers http.Header
|
||||||
|
QueryParams url.Values
|
||||||
|
FormData url.Values
|
||||||
|
Body []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// HttpClientConfig contains some configurations for http client
|
||||||
|
type HttpClientConfig struct {
|
||||||
|
SSLEnabled bool
|
||||||
|
TLSConfig *tls.Config
|
||||||
|
Compressed bool
|
||||||
|
HandshakeTimeout time.Duration
|
||||||
|
ResponseTimeout time.Duration
|
||||||
|
Verbose bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// defaultHttpClientConfig defalut client config
|
||||||
|
var defaultHttpClientConfig = &HttpClientConfig{
|
||||||
|
Compressed: false,
|
||||||
|
HandshakeTimeout: 20 * time.Second,
|
||||||
|
ResponseTimeout: 40 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
// HttpClient is used for sending http request
|
||||||
|
type HttpClient struct {
|
||||||
|
*http.Client
|
||||||
|
TLS *tls.Config
|
||||||
|
Request *http.Request
|
||||||
|
Config HttpClientConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewHttpClient make a HttpClient instance
|
||||||
|
func NewHttpClient() *HttpClient {
|
||||||
|
client := &HttpClient{
|
||||||
|
Client: &http.Client{
|
||||||
|
Transport: &http.Transport{
|
||||||
|
TLSHandshakeTimeout: defaultHttpClientConfig.HandshakeTimeout,
|
||||||
|
ResponseHeaderTimeout: defaultHttpClientConfig.ResponseTimeout,
|
||||||
|
DisableCompression: !defaultHttpClientConfig.Compressed,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Config: *defaultHttpClientConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewHttpClientWithConfig make a HttpClient instance with pass config
|
||||||
|
func NewHttpClientWithConfig(config *HttpClientConfig) *HttpClient {
|
||||||
|
if config == nil {
|
||||||
|
config = defaultHttpClientConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &HttpClient{
|
||||||
|
Client: &http.Client{
|
||||||
|
Transport: &http.Transport{
|
||||||
|
TLSHandshakeTimeout: config.HandshakeTimeout,
|
||||||
|
ResponseHeaderTimeout: config.ResponseTimeout,
|
||||||
|
DisableCompression: !config.Compressed,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Config: *config,
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.SSLEnabled {
|
||||||
|
client.TLS = config.TLSConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendRequest send http request
|
||||||
|
func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, error) {
|
||||||
|
err := validateRequest(request)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rawUrl := request.RawURL
|
||||||
|
|
||||||
|
req, err := http.NewRequest(request.Method, rawUrl, bytes.NewBuffer(request.Body))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
client.setTLS(rawUrl)
|
||||||
|
client.setHeader(req, request.Headers)
|
||||||
|
client.setQueryParam(req, rawUrl, request.QueryParams)
|
||||||
|
|
||||||
|
if request.FormData != nil {
|
||||||
|
client.setFormData(req, request.FormData)
|
||||||
|
}
|
||||||
|
|
||||||
|
client.Request = req
|
||||||
|
|
||||||
|
resp, err := client.Client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeResponse decode response into target object
|
||||||
|
func (client *HttpClient) DecodeResponse(resp *http.Response, target interface{}) error {
|
||||||
|
if resp == nil {
|
||||||
|
return errors.New("invalid target param")
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
return json.NewDecoder(resp.Body).Decode(target)
|
||||||
|
}
|
||||||
|
|
||||||
|
// setTLS set http client transport TLSClientConfig
|
||||||
|
func (client *HttpClient) setTLS(rawUrl string) {
|
||||||
|
if strings.HasPrefix(rawUrl, "https") {
|
||||||
|
if transport, ok := client.Client.Transport.(*http.Transport); ok {
|
||||||
|
transport.TLSClientConfig = client.TLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// setHeader set http rquest header
|
||||||
|
func (client *HttpClient) setHeader(req *http.Request, headers http.Header) {
|
||||||
|
if headers == nil {
|
||||||
|
headers = make(http.Header)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := headers["Accept"]; !ok {
|
||||||
|
headers["Accept"] = []string{"*/*"}
|
||||||
|
}
|
||||||
|
if _, ok := headers["Accept-Encoding"]; !ok && client.Config.Compressed {
|
||||||
|
headers["Accept-Encoding"] = []string{"deflate, gzip"}
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header = headers
|
||||||
|
}
|
||||||
|
|
||||||
|
// setQueryParam set http request query string param
|
||||||
|
func (client *HttpClient) setQueryParam(req *http.Request, reqUrl string, queryParam url.Values) error {
|
||||||
|
if queryParam != nil {
|
||||||
|
if !strings.Contains(reqUrl, "?") {
|
||||||
|
reqUrl = reqUrl + "?" + queryParam.Encode()
|
||||||
|
} else {
|
||||||
|
reqUrl = reqUrl + "&" + queryParam.Encode()
|
||||||
|
}
|
||||||
|
u, err := url.Parse(reqUrl)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.URL = u
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *HttpClient) setFormData(req *http.Request, values url.Values) {
|
||||||
|
formData := []byte(values.Encode())
|
||||||
|
req.Body = ioutil.NopCloser(bytes.NewReader(formData))
|
||||||
|
req.ContentLength = int64(len(formData))
|
||||||
|
}
|
||||||
|
|
||||||
|
// validateRequest check if a request has url, and valid method.
|
||||||
|
func validateRequest(req *HttpRequest) error {
|
||||||
|
if req.RawURL == "" {
|
||||||
|
return errors.New("invalid request url")
|
||||||
|
}
|
||||||
|
|
||||||
|
// common HTTP methods
|
||||||
|
methods := []string{"GET", "POST", "PUT", "DELETE", "PATCH",
|
||||||
|
"HEAD", "CONNECT", "OPTIONS", "TRACE"}
|
||||||
|
|
||||||
|
if !slice.Contain(methods, strings.ToUpper(req.Method)) {
|
||||||
|
return errors.New("invalid request method")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// StructToUrlValues convert struct to url valuse,
|
||||||
|
// only convert the field which is exported and has `json` tag
|
||||||
|
func StructToUrlValues(targetStruct interface{}) url.Values {
|
||||||
|
rv := reflect.ValueOf(targetStruct)
|
||||||
|
rt := reflect.TypeOf(targetStruct)
|
||||||
|
|
||||||
|
if rt.Kind() == reflect.Ptr {
|
||||||
|
rt = rt.Elem()
|
||||||
|
}
|
||||||
|
if rt.Kind() != reflect.Struct {
|
||||||
|
panic(fmt.Errorf("data type %T not support, shuld be struct or pointer to struct", targetStruct))
|
||||||
|
}
|
||||||
|
|
||||||
|
result := url.Values{}
|
||||||
|
|
||||||
|
fieldNum := rt.NumField()
|
||||||
|
pattern := `^[A-Z]`
|
||||||
|
regex := regexp.MustCompile(pattern)
|
||||||
|
for i := 0; i < fieldNum; i++ {
|
||||||
|
name := rt.Field(i).Name
|
||||||
|
tag := rt.Field(i).Tag.Get("json")
|
||||||
|
if regex.MatchString(name) && tag != "" {
|
||||||
|
if strings.Contains(tag, "omitempty") {
|
||||||
|
tag = strings.Split(tag, ",")[0]
|
||||||
|
}
|
||||||
|
result.Add(tag, fmt.Sprintf("%v", rv.Field(i).Interface()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,228 +0,0 @@
|
|||||||
package netutil
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/tls"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"reflect"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/duke-git/lancet/slice"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HttpRequest struct is a composed http request
|
|
||||||
type HttpRequest struct {
|
|
||||||
RawURL string
|
|
||||||
Method string
|
|
||||||
Headers http.Header
|
|
||||||
QueryParams url.Values
|
|
||||||
FormData url.Values
|
|
||||||
Body []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// HttpClientConfig contains some configurations for http client
|
|
||||||
type HttpClientConfig struct {
|
|
||||||
SSLEnabled bool
|
|
||||||
TLSConfig *tls.Config
|
|
||||||
Compressed bool
|
|
||||||
HandshakeTimeout time.Duration
|
|
||||||
ResponseTimeout time.Duration
|
|
||||||
Verbose bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// defaultHttpClientConfig defalut client config
|
|
||||||
var defaultHttpClientConfig = &HttpClientConfig{
|
|
||||||
Compressed: false,
|
|
||||||
HandshakeTimeout: 20 * time.Second,
|
|
||||||
ResponseTimeout: 40 * time.Second,
|
|
||||||
}
|
|
||||||
|
|
||||||
// HttpClient is used for sending http request
|
|
||||||
type HttpClient struct {
|
|
||||||
*http.Client
|
|
||||||
TLS *tls.Config
|
|
||||||
Request *http.Request
|
|
||||||
Config HttpClientConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewHttpClient make a HttpClient instance
|
|
||||||
func NewHttpClient() *HttpClient {
|
|
||||||
client := &HttpClient{
|
|
||||||
Client: &http.Client{
|
|
||||||
Transport: &http.Transport{
|
|
||||||
TLSHandshakeTimeout: defaultHttpClientConfig.HandshakeTimeout,
|
|
||||||
ResponseHeaderTimeout: defaultHttpClientConfig.ResponseTimeout,
|
|
||||||
DisableCompression: !defaultHttpClientConfig.Compressed,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Config: *defaultHttpClientConfig,
|
|
||||||
}
|
|
||||||
|
|
||||||
return client
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewHttpClientWithConfig make a HttpClient instance with pass config
|
|
||||||
func NewHttpClientWithConfig(config *HttpClientConfig) *HttpClient {
|
|
||||||
if config == nil {
|
|
||||||
config = defaultHttpClientConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
client := &HttpClient{
|
|
||||||
Client: &http.Client{
|
|
||||||
Transport: &http.Transport{
|
|
||||||
TLSHandshakeTimeout: config.HandshakeTimeout,
|
|
||||||
ResponseHeaderTimeout: config.ResponseTimeout,
|
|
||||||
DisableCompression: !config.Compressed,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Config: *config,
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.SSLEnabled {
|
|
||||||
client.TLS = config.TLSConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
return client
|
|
||||||
}
|
|
||||||
|
|
||||||
// SendRequest send http request
|
|
||||||
func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, error) {
|
|
||||||
err := validateRequest(request)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
rawUrl := request.RawURL
|
|
||||||
|
|
||||||
req, err := http.NewRequest(request.Method, rawUrl, bytes.NewBuffer(request.Body))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
client.setTLS(rawUrl)
|
|
||||||
client.setHeader(req, request.Headers)
|
|
||||||
client.setQueryParam(req, rawUrl, request.QueryParams)
|
|
||||||
|
|
||||||
if request.FormData != nil {
|
|
||||||
client.setFormData(req, request.FormData)
|
|
||||||
}
|
|
||||||
|
|
||||||
client.Request = req
|
|
||||||
|
|
||||||
resp, err := client.Client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeResponse decode response into target object
|
|
||||||
func (client *HttpClient) DecodeResponse(resp *http.Response, target interface{}) error {
|
|
||||||
if resp == nil {
|
|
||||||
return errors.New("invalid target param")
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
return json.NewDecoder(resp.Body).Decode(target)
|
|
||||||
}
|
|
||||||
|
|
||||||
// setTLS set http client transport TLSClientConfig
|
|
||||||
func (client *HttpClient) setTLS(rawUrl string) {
|
|
||||||
if strings.HasPrefix(rawUrl, "https") {
|
|
||||||
if transport, ok := client.Client.Transport.(*http.Transport); ok {
|
|
||||||
transport.TLSClientConfig = client.TLS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// setHeader set http rquest header
|
|
||||||
func (client *HttpClient) setHeader(req *http.Request, headers http.Header) {
|
|
||||||
if headers == nil {
|
|
||||||
headers = make(http.Header)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := headers["Accept"]; !ok {
|
|
||||||
headers["Accept"] = []string{"*/*"}
|
|
||||||
}
|
|
||||||
if _, ok := headers["Accept-Encoding"]; !ok && client.Config.Compressed {
|
|
||||||
headers["Accept-Encoding"] = []string{"deflate, gzip"}
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Header = headers
|
|
||||||
}
|
|
||||||
|
|
||||||
// setQueryParam set http request query string param
|
|
||||||
func (client *HttpClient) setQueryParam(req *http.Request, reqUrl string, queryParam url.Values) error {
|
|
||||||
if queryParam != nil {
|
|
||||||
if !strings.Contains(reqUrl, "?") {
|
|
||||||
reqUrl = reqUrl + "?" + queryParam.Encode()
|
|
||||||
} else {
|
|
||||||
reqUrl = reqUrl + "&" + queryParam.Encode()
|
|
||||||
}
|
|
||||||
u, err := url.Parse(reqUrl)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
req.URL = u
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (client *HttpClient) setFormData(req *http.Request, values url.Values) {
|
|
||||||
formData := []byte(values.Encode())
|
|
||||||
req.Body = ioutil.NopCloser(bytes.NewReader(formData))
|
|
||||||
req.ContentLength = int64(len(formData))
|
|
||||||
}
|
|
||||||
|
|
||||||
// validateRequest check if a request has url, and valid method.
|
|
||||||
func validateRequest(req *HttpRequest) error {
|
|
||||||
if req.RawURL == "" {
|
|
||||||
return errors.New("invalid request url")
|
|
||||||
}
|
|
||||||
|
|
||||||
// common HTTP methods
|
|
||||||
methods := []string{"GET", "POST", "PUT", "DELETE", "PATCH",
|
|
||||||
"HEAD", "CONNECT", "OPTIONS", "TRACE"}
|
|
||||||
|
|
||||||
if !slice.Contain(methods, strings.ToUpper(req.Method)) {
|
|
||||||
return errors.New("invalid request method")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// StructToUrlValues convert struct to url valuse,
|
|
||||||
// only convert the field which is exported and has `json` tag
|
|
||||||
func StructToUrlValues(targetStruct interface{}) url.Values {
|
|
||||||
rv := reflect.ValueOf(targetStruct)
|
|
||||||
rt := reflect.TypeOf(targetStruct)
|
|
||||||
|
|
||||||
if rt.Kind() == reflect.Ptr {
|
|
||||||
rt = rt.Elem()
|
|
||||||
}
|
|
||||||
if rt.Kind() != reflect.Struct {
|
|
||||||
panic(fmt.Errorf("data type %T not support, shuld be struct or pointer to struct", targetStruct))
|
|
||||||
}
|
|
||||||
|
|
||||||
result := url.Values{}
|
|
||||||
|
|
||||||
fieldNum := rt.NumField()
|
|
||||||
pattern := `^[A-Z]`
|
|
||||||
regex := regexp.MustCompile(pattern)
|
|
||||||
for i := 0; i < fieldNum; i++ {
|
|
||||||
name := rt.Field(i).Name
|
|
||||||
tag := rt.Field(i).Tag.Get("json")
|
|
||||||
if regex.MatchString(name) && tag != "" {
|
|
||||||
result.Add(tag, fmt.Sprintf("%v", rv.Field(i).Interface()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
package netutil
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/duke-git/lancet/internal"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestHttpClient_Get(t *testing.T) {
|
|
||||||
assert := internal.NewAssert(t, "TestHttpClient_Get")
|
|
||||||
|
|
||||||
request := &HttpRequest{
|
|
||||||
RawURL: "https://jsonplaceholder.typicode.com/todos/1",
|
|
||||||
Method: "GET",
|
|
||||||
}
|
|
||||||
|
|
||||||
httpClient := NewHttpClient()
|
|
||||||
resp, err := httpClient.SendRequest(request)
|
|
||||||
if err != nil || resp.StatusCode != 200 {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Todo struct {
|
|
||||||
UserId int `json:"userId"`
|
|
||||||
Id int `json:"id"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
Completed bool `json:"completed"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var todo Todo
|
|
||||||
httpClient.DecodeResponse(resp, &todo)
|
|
||||||
|
|
||||||
assert.Equal(1, todo.Id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHttpClent_Post(t *testing.T) {
|
|
||||||
header := http.Header{}
|
|
||||||
header.Add("Content-Type", "multipart/form-data")
|
|
||||||
|
|
||||||
postData := url.Values{}
|
|
||||||
postData.Add("userId", "1")
|
|
||||||
postData.Add("title", "testItem")
|
|
||||||
|
|
||||||
request := &HttpRequest{
|
|
||||||
RawURL: "https://jsonplaceholder.typicode.com/todos",
|
|
||||||
Method: "POST",
|
|
||||||
Headers: header,
|
|
||||||
FormData: postData,
|
|
||||||
}
|
|
||||||
|
|
||||||
httpClient := NewHttpClient()
|
|
||||||
resp, err := httpClient.SendRequest(request)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
body, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
t.Log("response: ", resp.StatusCode, string(body))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestStructToUrlValues(t *testing.T) {
|
|
||||||
assert := internal.NewAssert(t, "TestStructToUrlValues")
|
|
||||||
|
|
||||||
type TodoQuery struct {
|
|
||||||
Id int `json:"id"`
|
|
||||||
UserId int `json:"userId"`
|
|
||||||
}
|
|
||||||
todoQuery := TodoQuery{
|
|
||||||
Id: 1,
|
|
||||||
UserId: 1,
|
|
||||||
}
|
|
||||||
todoValues := StructToUrlValues(todoQuery)
|
|
||||||
|
|
||||||
assert.Equal("1", todoValues.Get("id"))
|
|
||||||
assert.Equal("1", todoValues.Get("userId"))
|
|
||||||
|
|
||||||
request := &HttpRequest{
|
|
||||||
RawURL: "https://jsonplaceholder.typicode.com/todos",
|
|
||||||
Method: "GET",
|
|
||||||
QueryParams: todoValues,
|
|
||||||
}
|
|
||||||
|
|
||||||
httpClient := NewHttpClient()
|
|
||||||
resp, err := httpClient.SendRequest(request)
|
|
||||||
if err != nil || resp.StatusCode != 200 {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
body, _ := ioutil.ReadAll(resp.Body)
|
|
||||||
t.Log("response: ", string(body))
|
|
||||||
}
|
|
||||||
@@ -2,8 +2,10 @@ package netutil
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -50,23 +52,23 @@ func TestHttpPost(t *testing.T) {
|
|||||||
func TestHttpPostFormData(t *testing.T) {
|
func TestHttpPostFormData(t *testing.T) {
|
||||||
apiUrl := "https://jsonplaceholder.typicode.com/todos"
|
apiUrl := "https://jsonplaceholder.typicode.com/todos"
|
||||||
header := map[string]string{
|
header := map[string]string{
|
||||||
// "Content-Type": "application/x-www-form-urlencoded",
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
"Content-Type": "multipart/form-data",
|
// "Content-Type": "multipart/form-data",
|
||||||
}
|
|
||||||
type Todo struct {
|
|
||||||
UserId int `json:"userId"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
postData := url.Values{}
|
postData := url.Values{}
|
||||||
postData.Add("userId", "1")
|
postData.Add("userId", "1")
|
||||||
postData.Add("title", "TestAddToDo")
|
postData.Add("title", "TestToDo")
|
||||||
|
|
||||||
resp, err := HttpPost(apiUrl, header, postData, nil)
|
// postData := make(map[string]string)
|
||||||
|
// postData["userId"] = "1"
|
||||||
|
// postData["title"] = "title"
|
||||||
|
|
||||||
|
resp, err := HttpPost(apiUrl, header, nil, postData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
t.FailNow()
|
|
||||||
}
|
}
|
||||||
body, _ := ioutil.ReadAll(resp.Body)
|
body, _ := io.ReadAll(resp.Body)
|
||||||
t.Log("response: ", resp.StatusCode, string(body))
|
t.Log("response: ", resp.StatusCode, string(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,3 +165,88 @@ func TestParseResponse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Log("response: ", toDoResp)
|
t.Log("response: ", toDoResp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHttpClient_Get(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestHttpClient_Get")
|
||||||
|
|
||||||
|
request := &HttpRequest{
|
||||||
|
RawURL: "https://jsonplaceholder.typicode.com/todos/1",
|
||||||
|
Method: "GET",
|
||||||
|
}
|
||||||
|
|
||||||
|
httpClient := NewHttpClient()
|
||||||
|
resp, err := httpClient.SendRequest(request)
|
||||||
|
if err != nil || resp.StatusCode != 200 {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Todo struct {
|
||||||
|
UserId int `json:"userId"`
|
||||||
|
Id int `json:"id"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Completed bool `json:"completed"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var todo Todo
|
||||||
|
httpClient.DecodeResponse(resp, &todo)
|
||||||
|
|
||||||
|
assert.Equal(1, todo.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHttpClent_Post(t *testing.T) {
|
||||||
|
header := http.Header{}
|
||||||
|
header.Add("Content-Type", "multipart/form-data")
|
||||||
|
|
||||||
|
postData := url.Values{}
|
||||||
|
postData.Add("userId", "1")
|
||||||
|
postData.Add("title", "testItem")
|
||||||
|
|
||||||
|
request := &HttpRequest{
|
||||||
|
RawURL: "https://jsonplaceholder.typicode.com/todos",
|
||||||
|
Method: "POST",
|
||||||
|
Headers: header,
|
||||||
|
FormData: postData,
|
||||||
|
}
|
||||||
|
|
||||||
|
httpClient := NewHttpClient()
|
||||||
|
resp, err := httpClient.SendRequest(request)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
body, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
t.Log("response: ", resp.StatusCode, string(body))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStructToUrlValues(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestStructToUrlValues")
|
||||||
|
|
||||||
|
type TodoQuery struct {
|
||||||
|
Id int `json:"id"`
|
||||||
|
UserId int `json:"userId"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Status string
|
||||||
|
}
|
||||||
|
item1 := TodoQuery{
|
||||||
|
Id: 1,
|
||||||
|
UserId: 123,
|
||||||
|
Name: "test",
|
||||||
|
Status: "completed",
|
||||||
|
}
|
||||||
|
queryValues1 := StructToUrlValues(item1)
|
||||||
|
|
||||||
|
assert.Equal("1", queryValues1.Get("id"))
|
||||||
|
assert.Equal("123", queryValues1.Get("userId"))
|
||||||
|
assert.Equal("test", queryValues1.Get("name"))
|
||||||
|
assert.Equal("", queryValues1.Get("status"))
|
||||||
|
|
||||||
|
item2 := TodoQuery{
|
||||||
|
Id: 2,
|
||||||
|
UserId: 456,
|
||||||
|
}
|
||||||
|
queryValues2 := StructToUrlValues(item2)
|
||||||
|
|
||||||
|
assert.Equal("2", queryValues2.Get("id"))
|
||||||
|
assert.Equal("456", queryValues2.Get("userId"))
|
||||||
|
assert.Equal("", queryValues2.Get("name"))
|
||||||
|
}
|
||||||
|
|||||||
100
netutil/net.go
100
netutil/net.go
@@ -1,12 +1,22 @@
|
|||||||
package netutil
|
package netutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"mime/multipart"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/fileutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetInternalIp return internal ipv4
|
// GetInternalIp return internal ipv4
|
||||||
@@ -170,3 +180,93 @@ func EncodeUrl(urlStr string) (string, error) {
|
|||||||
|
|
||||||
return URL.String(), nil
|
return URL.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DownloadFile will upload the file to a server.
|
||||||
|
func UploadFile(filepath string, server string) (bool, error) {
|
||||||
|
if !fileutil.IsExist(filepath) {
|
||||||
|
return false, errors.New("file not exist")
|
||||||
|
}
|
||||||
|
|
||||||
|
fileInfo, err := os.Stat(filepath)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
bodyBuffer := &bytes.Buffer{}
|
||||||
|
writer := multipart.NewWriter(bodyBuffer)
|
||||||
|
|
||||||
|
formFile, err := writer.CreateFormFile("uploadfile", fileInfo.Name())
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
srcFile, err := os.Open(filepath)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
defer srcFile.Close()
|
||||||
|
|
||||||
|
_, err = io.Copy(formFile, srcFile)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
contentType := writer.FormDataContentType()
|
||||||
|
writer.Close()
|
||||||
|
|
||||||
|
_, err = http.Post(server, contentType, bodyBuffer)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DownloadFile will download the file exist in url to a local file.
|
||||||
|
func DownloadFile(filepath string, url string) error {
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
out, err := os.Create(filepath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer out.Close()
|
||||||
|
|
||||||
|
_, err = io.Copy(out, resp.Body)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsPingConnected checks if can ping specified host or not.
|
||||||
|
func IsPingConnected(host string) bool {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsTelnetConnected checks if can telnet specified host or not.
|
||||||
|
func IsTelnetConnected(host string, port string) bool {
|
||||||
|
adder := host + ":" + port
|
||||||
|
conn, err := net.DialTimeout("tcp", adder, 5*time.Second)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -74,51 +75,34 @@ func setHeaderAndQueryParam(req *http.Request, reqUrl string, header, queryParam
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setHeaderAndQueryAndBody(req *http.Request, reqUrl string, header, queryParam, body interface{}) error {
|
func setHeaderAndQueryAndBody(req *http.Request, reqUrl string, header, queryParam, body interface{}) error {
|
||||||
err := setHeader(req, header)
|
if err := setHeader(req, header); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
} else if err = setQueryParam(req, reqUrl, queryParam); err != nil {
|
||||||
err = setQueryParam(req, reqUrl, queryParam)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
} else if err = setBodyByte(req, body); err != nil {
|
||||||
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 err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setHeader(req *http.Request, header interface{}) error {
|
func setHeader(req *http.Request, header interface{}) error {
|
||||||
if header != nil {
|
if header == nil {
|
||||||
switch v := header.(type) {
|
return nil
|
||||||
case map[string]string:
|
}
|
||||||
for k := range v {
|
|
||||||
req.Header.Add(k, v[k])
|
switch v := header.(type) {
|
||||||
}
|
case map[string]string:
|
||||||
case http.Header:
|
for k := range v {
|
||||||
for k, vv := range v {
|
req.Header.Add(k, v[k])
|
||||||
for _, vvv := range vv {
|
|
||||||
req.Header.Add(k, vvv)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return errors.New("header params type should be http.Header or map[string]string")
|
|
||||||
}
|
}
|
||||||
|
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 != "" {
|
if host := req.Header.Get("Host"); host != "" {
|
||||||
@@ -138,19 +122,22 @@ func setUrl(req *http.Request, reqUrl string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setQueryParam(req *http.Request, reqUrl string, queryParam interface{}) error {
|
func setQueryParam(req *http.Request, reqUrl string, queryParam interface{}) error {
|
||||||
|
if queryParam == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
var values url.Values
|
var values url.Values
|
||||||
if queryParam != nil {
|
|
||||||
switch v := queryParam.(type) {
|
switch v := queryParam.(type) {
|
||||||
case map[string]interface{}:
|
case map[string]interface{}:
|
||||||
values = url.Values{}
|
values = url.Values{}
|
||||||
for k := range v {
|
for k := range v {
|
||||||
values.Set(k, fmt.Sprintf("%v", v[k]))
|
values.Set(k, fmt.Sprintf("%v", v[k]))
|
||||||
}
|
|
||||||
case url.Values:
|
|
||||||
values = v
|
|
||||||
default:
|
|
||||||
return errors.New("query params type should be url.Values or map[string]interface{}")
|
|
||||||
}
|
}
|
||||||
|
case url.Values:
|
||||||
|
values = v
|
||||||
|
default:
|
||||||
|
return errors.New("query params type should be url.Values or map[string]interface{}")
|
||||||
}
|
}
|
||||||
|
|
||||||
// set url
|
// set url
|
||||||
@@ -171,14 +158,36 @@ func setQueryParam(req *http.Request, reqUrl string, queryParam interface{}) err
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setBodyByte(req *http.Request, body interface{}) error {
|
func setBodyByte(req *http.Request, body interface{}) error {
|
||||||
if body != nil {
|
if body == nil {
|
||||||
switch b := body.(type) {
|
return nil
|
||||||
case []byte:
|
}
|
||||||
req.Body = ioutil.NopCloser(bytes.NewReader(b))
|
var bodyReader *bytes.Reader
|
||||||
req.ContentLength = int64(len(b))
|
switch b := body.(type) {
|
||||||
default:
|
case io.Reader:
|
||||||
return errors.New("body type should be []byte")
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,14 +15,14 @@ func TestGetInternalIp(t *testing.T) {
|
|||||||
assert.IsNotNil(ip)
|
assert.IsNotNil(ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetPublicIpInfo(t *testing.T) {
|
// func TestGetPublicIpInfo(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestGetPublicIpInfo")
|
// assert := internal.NewAssert(t, "TestGetPublicIpInfo")
|
||||||
|
|
||||||
publicIpInfo, err := GetPublicIpInfo()
|
// publicIpInfo, err := GetPublicIpInfo()
|
||||||
assert.IsNil(err)
|
// assert.IsNil(err)
|
||||||
|
|
||||||
t.Logf("public ip info is: %+v \n", *publicIpInfo)
|
// t.Logf("public ip info is: %+v \n", *publicIpInfo)
|
||||||
}
|
// }
|
||||||
|
|
||||||
func TestIsPublicIP(t *testing.T) {
|
func TestIsPublicIP(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestIsPublicIP")
|
assert := internal.NewAssert(t, "TestIsPublicIP")
|
||||||
@@ -52,3 +52,30 @@ func TestGetMacAddrs(t *testing.T) {
|
|||||||
macAddrs := GetMacAddrs()
|
macAddrs := GetMacAddrs()
|
||||||
t.Log(macAddrs)
|
t.Log(macAddrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIsPingConnected(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestIsPingConnected")
|
||||||
|
|
||||||
|
result1 := IsPingConnected("www.baidu.com")
|
||||||
|
assert.Equal(true, result1)
|
||||||
|
|
||||||
|
result2 := IsPingConnected("www.!@#&&&.com")
|
||||||
|
assert.Equal(false, result2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTelnetConnected(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestTelnetConnected")
|
||||||
|
|
||||||
|
result1 := IsTelnetConnected("www.baidu.com", "80")
|
||||||
|
assert.Equal(true, result1)
|
||||||
|
|
||||||
|
result2 := IsTelnetConnected("www.baidu.com", "123")
|
||||||
|
assert.Equal(false, result2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// func TestDownloadFile(t *testing.T) {
|
||||||
|
// assert := internal.NewAssert(t, "TestDownloadFile")
|
||||||
|
|
||||||
|
// err := DownloadFile("./lancet_logo.jpg", "https://picx.zhimg.com/v2-fc82a4199749de9cfb71e32e54f489d3_720w.jpg?source=172ae18b")
|
||||||
|
// assert.IsNil(err)
|
||||||
|
// }
|
||||||
|
|||||||
@@ -5,9 +5,11 @@
|
|||||||
package strutil
|
package strutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CamelCase covert string to camelCase string.
|
// CamelCase covert string to camelCase string.
|
||||||
@@ -324,3 +326,180 @@ func WordCount(s string) int {
|
|||||||
|
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemoveNonPrintable remove non-printable characters from a string.
|
||||||
|
func RemoveNonPrintable(str string) string {
|
||||||
|
result := strings.Map(func(r rune) rune {
|
||||||
|
if unicode.IsPrint(r) {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}, str)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToBytes converts a string to byte slice without a memory allocation.
|
||||||
|
func StringToBytes(str string) (b []byte) {
|
||||||
|
sh := *(*reflect.StringHeader)(unsafe.Pointer(&str))
|
||||||
|
bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
|
||||||
|
bh.Data, bh.Len, bh.Cap = sh.Data, sh.Len, sh.Len
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// BytesToString converts a byte slice to string without a memory allocation.
|
||||||
|
// Play: todo
|
||||||
|
func BytesToString(bytes []byte) string {
|
||||||
|
return *(*string)(unsafe.Pointer(&bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsBlank checks if a string is whitespace, empty.
|
||||||
|
func IsBlank(str string) bool {
|
||||||
|
if len(str) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// memory copies will occur here, but UTF8 will be compatible
|
||||||
|
runes := []rune(str)
|
||||||
|
for _, r := range runes {
|
||||||
|
if !unicode.IsSpace(r) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasPrefixAny check if a string starts with any of an array of specified strings.
|
||||||
|
func HasPrefixAny(str string, prefixes []string) bool {
|
||||||
|
if len(str) == 0 || len(prefixes) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, prefix := range prefixes {
|
||||||
|
if strings.HasPrefix(str, prefix) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasSuffixAny check if a string ends with any of an array of specified strings.
|
||||||
|
func HasSuffixAny(str string, suffixes []string) bool {
|
||||||
|
if len(str) == 0 || len(suffixes) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, suffix := range suffixes {
|
||||||
|
if strings.HasSuffix(str, suffix) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
func IndexOffset(str string, substr string, idxFrom int) int {
|
||||||
|
if idxFrom > len(str)-1 || idxFrom < 0 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Index(str[idxFrom:], substr) + idxFrom
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReplaceWithMap returns a copy of `str`, which is replaced by a map in unordered way, case-sensitively.
|
||||||
|
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.
|
||||||
|
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.
|
||||||
|
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)
|
||||||
|
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.
|
||||||
|
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.
|
||||||
|
func ContainsAny(str string, substrs []string) bool {
|
||||||
|
for _, v := range substrs {
|
||||||
|
if strings.Contains(str, v) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package strutil
|
package strutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/internal"
|
"github.com/duke-git/lancet/internal"
|
||||||
@@ -329,3 +330,128 @@ func TestWordCount(t *testing.T) {
|
|||||||
assert.Equal(v, WordCount(k))
|
assert.Equal(v, WordCount(k))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRemoveNonPrintable(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestRemoveNonPrintable")
|
||||||
|
|
||||||
|
assert.Equal("hello world", RemoveNonPrintable("hello\u00a0 \u200bworld\n"))
|
||||||
|
assert.Equal("你好😄", RemoveNonPrintable("你好😄"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStringToBytes(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestStringToBytes")
|
||||||
|
str := "abc"
|
||||||
|
bytes := StringToBytes(str)
|
||||||
|
assert.Equal(reflect.DeepEqual(bytes, []byte{'a', 'b', 'c'}), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBytesToString(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestBytesToString")
|
||||||
|
bytes := []byte{'a', 'b', 'c'}
|
||||||
|
str := BytesToString(bytes)
|
||||||
|
assert.Equal(str == "abc", true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsBlank(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestIsBlank")
|
||||||
|
assert.Equal(IsBlank(""), true)
|
||||||
|
assert.Equal(IsBlank("\t\v\f\n"), true)
|
||||||
|
assert.Equal(IsBlank(" 中文"), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHasPrefixAny(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestHasPrefixAny")
|
||||||
|
str := "foo bar"
|
||||||
|
prefixes := []string{"fo", "xyz", "hello"}
|
||||||
|
notMatches := []string{"oom", "world"}
|
||||||
|
assert.Equal(HasPrefixAny(str, prefixes), true)
|
||||||
|
assert.Equal(HasPrefixAny(str, notMatches), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHasSuffixAny(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestHasSuffixAny")
|
||||||
|
str := "foo bar"
|
||||||
|
suffixes := []string{"bar", "xyz", "hello"}
|
||||||
|
notMatches := []string{"oom", "world"}
|
||||||
|
assert.Equal(HasSuffixAny(str, suffixes), true)
|
||||||
|
assert.Equal(HasSuffixAny(str, notMatches), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIndexOffset(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestIndexOffset")
|
||||||
|
str := "foo bar hello world"
|
||||||
|
assert.Equal(IndexOffset(str, "o", 5), 12)
|
||||||
|
assert.Equal(IndexOffset(str, "o", 0), 1)
|
||||||
|
assert.Equal(IndexOffset(str, "d", len(str)-1), len(str)-1)
|
||||||
|
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"}))
|
||||||
|
}
|
||||||
|
|||||||
13
system/os.go
13
system/os.go
@@ -15,6 +15,10 @@ import (
|
|||||||
"golang.org/x/text/encoding/simplifiedchinese"
|
"golang.org/x/text/encoding/simplifiedchinese"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
Option func(*exec.Cmd)
|
||||||
|
)
|
||||||
|
|
||||||
// IsWindows check if current os is windows
|
// IsWindows check if current os is windows
|
||||||
func IsWindows() bool {
|
func IsWindows() bool {
|
||||||
return runtime.GOOS == "windows"
|
return runtime.GOOS == "windows"
|
||||||
@@ -58,7 +62,7 @@ func CompareOsEnv(key, comparedEnv string) bool {
|
|||||||
// param `command` is a complete command string, like, ls -a (linux), dir(windows), ping 127.0.0.1
|
// param `command` is a complete command string, like, ls -a (linux), dir(windows), ping 127.0.0.1
|
||||||
// in linux, use /bin/bash -c to execute command
|
// in linux, use /bin/bash -c to execute command
|
||||||
// in windows, use powershell.exe to execute command
|
// in windows, use powershell.exe to execute command
|
||||||
func ExecCommand(command string) (stdout, stderr string, err error) {
|
func ExecCommand(command string, opts ...Option) (stdout, stderr string, err error) {
|
||||||
var out bytes.Buffer
|
var out bytes.Buffer
|
||||||
var errOut bytes.Buffer
|
var errOut bytes.Buffer
|
||||||
|
|
||||||
@@ -66,6 +70,13 @@ func ExecCommand(command string) (stdout, stderr string, err error) {
|
|||||||
if IsWindows() {
|
if IsWindows() {
|
||||||
cmd = exec.Command("powershell.exe", command)
|
cmd = exec.Command("powershell.exe", command)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
if opt != nil {
|
||||||
|
opt(cmd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cmd.Stdout = &out
|
cmd.Stdout = &out
|
||||||
cmd.Stderr = &errOut
|
cmd.Stderr = &errOut
|
||||||
|
|
||||||
|
|||||||
25
system/os_darwin.go
Normal file
25
system/os_darwin.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
//go:build darwin
|
||||||
|
|
||||||
|
package system
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
func WithForeground() Option {
|
||||||
|
return func(c *exec.Cmd) {
|
||||||
|
// if c.SysProcAttr == nil {
|
||||||
|
// c.SysProcAttr = &syscall.SysProcAttr{
|
||||||
|
// Foreground: true,
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// c.SysProcAttr.Foreground = true
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithWinHide() Option {
|
||||||
|
return func(c *exec.Cmd) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
26
system/os_linux.go
Normal file
26
system/os_linux.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
//go:build linux
|
||||||
|
|
||||||
|
package system
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func WithForeground() Option {
|
||||||
|
return func(c *exec.Cmd) {
|
||||||
|
if c.SysProcAttr == nil {
|
||||||
|
c.SysProcAttr = &syscall.SysProcAttr{
|
||||||
|
Foreground: true,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.SysProcAttr.Foreground = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithWinHide() Option {
|
||||||
|
return func(c *exec.Cmd) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -45,7 +45,7 @@ func TestExecCommand(t *testing.T) {
|
|||||||
assert := internal.NewAssert(t, "TestExecCommand")
|
assert := internal.NewAssert(t, "TestExecCommand")
|
||||||
|
|
||||||
// linux or mac
|
// linux or mac
|
||||||
stdout, stderr, err := ExecCommand("ls")
|
stdout, stderr, err := ExecCommand("ls", WithForeground())
|
||||||
t.Log("std out: ", stdout)
|
t.Log("std out: ", stdout)
|
||||||
t.Log("std err: ", stderr)
|
t.Log("std err: ", stderr)
|
||||||
assert.Equal("", stderr)
|
assert.Equal("", stderr)
|
||||||
|
|||||||
20
system/os_windows.go
Normal file
20
system/os_windows.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package system
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func WithWinHide() Option {
|
||||||
|
return func(c *exec.Cmd) {
|
||||||
|
if c.SysProcAttr == nil {
|
||||||
|
c.SysProcAttr = &syscall.SysProcAttr{
|
||||||
|
HideWindow: true,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.SysProcAttr.HideWindow = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -316,3 +316,49 @@ func IsGBK(data []byte) bool {
|
|||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsNumberStr check if the value is number(integer, float) or not.
|
||||||
|
func IsNumber(v interface{}) bool {
|
||||||
|
return IsInt(v) || IsFloat(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsFloat check if the value is float(float32, float34) or not.
|
||||||
|
func IsFloat(v interface{}) bool {
|
||||||
|
switch v.(type) {
|
||||||
|
case float32, float64:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsInt check if the value is integer(int, unit) or not.
|
||||||
|
func IsInt(v interface{}) bool {
|
||||||
|
switch v.(type) {
|
||||||
|
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsASCII checks if string is all ASCII char.
|
||||||
|
func IsASCII(str string) bool {
|
||||||
|
for i := 0; i < len(str); i++ {
|
||||||
|
if str[i] > unicode.MaxASCII {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsPrintable checks if string is all printable chars.
|
||||||
|
func IsPrintable(str string) bool {
|
||||||
|
for _, r := range str {
|
||||||
|
if !unicode.IsPrint(r) {
|
||||||
|
if r == '\n' || r == '\r' || r == '\t' || r == '`' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|||||||
@@ -400,3 +400,51 @@ func TestIsGBK(t *testing.T) {
|
|||||||
assert.Equal(true, IsGBK(gbkData))
|
assert.Equal(true, IsGBK(gbkData))
|
||||||
assert.Equal(false, utf8.Valid(gbkData))
|
assert.Equal(false, utf8.Valid(gbkData))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIsNumber(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestIsNumber")
|
||||||
|
|
||||||
|
assert.Equal(false, IsNumber(""))
|
||||||
|
assert.Equal(false, IsNumber("3"))
|
||||||
|
assert.Equal(true, IsNumber(0))
|
||||||
|
assert.Equal(true, IsNumber(0.1))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsFloat(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestIsFloat")
|
||||||
|
|
||||||
|
assert.Equal(false, IsFloat(""))
|
||||||
|
assert.Equal(false, IsFloat("3"))
|
||||||
|
assert.Equal(false, IsFloat(0))
|
||||||
|
assert.Equal(true, IsFloat(0.1))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsInt(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestIsInt")
|
||||||
|
|
||||||
|
assert.Equal(false, IsInt(""))
|
||||||
|
assert.Equal(false, IsInt("3"))
|
||||||
|
assert.Equal(false, IsInt(0.1))
|
||||||
|
assert.Equal(true, IsInt(0))
|
||||||
|
assert.Equal(true, IsInt(-1))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsASCII(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestIsASCII")
|
||||||
|
|
||||||
|
assert.Equal(true, IsASCII("ABC"))
|
||||||
|
assert.Equal(true, IsASCII("123"))
|
||||||
|
assert.Equal(true, IsASCII(""))
|
||||||
|
assert.Equal(false, IsASCII("😄"))
|
||||||
|
assert.Equal(false, IsASCII("你好"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsPrintable(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestIsPrintable")
|
||||||
|
|
||||||
|
assert.Equal(true, IsPrintable("ABC"))
|
||||||
|
assert.Equal(true, IsPrintable("{id: 123}"))
|
||||||
|
assert.Equal(true, IsPrintable(""))
|
||||||
|
assert.Equal(true, IsPrintable("😄"))
|
||||||
|
assert.Equal(false, IsPrintable("\u0000"))
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user