mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-07 06:02:27 +08:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5297ec329 | ||
|
|
aa4b61ff85 | ||
|
|
7dbd7002a3 | ||
|
|
a995db445a | ||
|
|
6e5b67bee7 | ||
|
|
52b8ea8166 | ||
|
|
6fe8a9efe7 | ||
|
|
dcef06e9da | ||
|
|
8f410bf9cb | ||
|
|
9cd6eb4ddf | ||
|
|
bf581162ee | ||
|
|
bd984fa378 | ||
|
|
d7f23e2dee | ||
|
|
3802c715c3 | ||
|
|
4b12173f24 | ||
|
|
31c618c187 | ||
|
|
6497b321b0 | ||
|
|
bda78201f5 | ||
|
|
0753ea2801 | ||
|
|
e25b53712b |
17
README.md
17
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/v2)
|
[](https://pkg.go.dev/github.com/duke-git/lancet/v2)
|
||||||
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
||||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
## <a href="https://www.golancet.cn/en/" target="_blank"> Website</a> | [简体中文](./README_zh-CN.md)
|
## <a href="https://www.golancet.cn/en/" target="_blank"> Website</a> | [简体中文](./README_zh-CN.md)
|
||||||
|
|
||||||
## Feature
|
## Features
|
||||||
|
|
||||||
- 👏 Comprehensive, efficient and reusable.
|
- 👏 Comprehensive, efficient and reusable.
|
||||||
- 💪 600+ go util functions, support string, slice, datetime, net, crypt...
|
- 💪 600+ go util functions, support string, slice, datetime, net, crypt...
|
||||||
@@ -453,10 +453,14 @@ import "github.com/duke-git/lancet/v2/cryptor"
|
|||||||
[[play](https://go.dev/play/p/uef0q1fz53I)]
|
[[play](https://go.dev/play/p/uef0q1fz53I)]
|
||||||
- **<big>GenerateRsaKeyPair</big>** : creates rsa private and public key.
|
- **<big>GenerateRsaKeyPair</big>** : creates rsa private and public key.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/cryptor.md#GenerateRsaKeyPair)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/cryptor.md#GenerateRsaKeyPair)]
|
||||||
|
[[play](https://go.dev/play/p/sSVmkfENKMz)]
|
||||||
- **<big>RsaEncryptOAEP</big>** : encrypts the given data with RSA-OAEP.
|
- **<big>RsaEncryptOAEP</big>** : encrypts the given data with RSA-OAEP.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/cryptor.md#RsaEncryptOAEP)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/cryptor.md#RsaEncryptOAEP)]
|
||||||
|
[[play](https://go.dev/play/p/sSVmkfENKMz)]
|
||||||
- **<big>RsaDecryptOAEP</big>** : decrypts the data with RSA-OAEP
|
- **<big>RsaDecryptOAEP</big>** : decrypts the data with RSA-OAEP
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/cryptor.md#RsaDecryptOAEP)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/cryptor.md#RsaDecryptOAEP)]
|
||||||
|
[[play](https://go.dev/play/p/sSVmkfENKMz)]
|
||||||
|
|
||||||
|
|
||||||
<h3 id="datetime"> 7. Datetime package supports date and time format and compare. <a href="#index">index</a></h3>
|
<h3 id="datetime"> 7. Datetime package supports date and time format and compare. <a href="#index">index</a></h3>
|
||||||
|
|
||||||
@@ -1093,6 +1097,12 @@ import "github.com/duke-git/lancet/v2/random"
|
|||||||
- **<big>RandUniqueIntSlice</big>** : generate a slice of random int of length n that do not repeat.
|
- **<big>RandUniqueIntSlice</big>** : generate a slice of random int of length n that do not repeat.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/random.md#RandUniqueIntSlice)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/random.md#RandUniqueIntSlice)]
|
||||||
[[play](https://go.dev/play/p/uBkRSOz73Ec)]
|
[[play](https://go.dev/play/p/uBkRSOz73Ec)]
|
||||||
|
- **<big>RandSymbolChar</big>** : Generate a random symbol char of specified length.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/random.md#RandSymbolChar)]
|
||||||
|
- **<big>RandFloat</big>** : Generate a random float64 number between [min, max) with specific precision.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/random.md#RandFloat)]
|
||||||
|
- **<big>RandFloats</big>** : Generate a slice of random float64 numbers of length n that do not repeat.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/random.md#RandFloats)]
|
||||||
|
|
||||||
<h3 id="retry"> 17. Retry package is for executing a function repeatedly until it was successful or canceled by the context. <a href="#index">index</a></h3>
|
<h3 id="retry"> 17. Retry package is for executing a function repeatedly until it was successful or canceled by the context. <a href="#index">index</a></h3>
|
||||||
|
|
||||||
@@ -1336,6 +1346,8 @@ import "github.com/duke-git/lancet/v2/slice"
|
|||||||
- **<big>Partition</big>** : partition all slice elements with the evaluation of the given predicate functions.
|
- **<big>Partition</big>** : partition all slice elements with the evaluation of the given predicate functions.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Partition)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Partition)]
|
||||||
[[play](https://go.dev/play/p/lkQ3Ri2NQhV)]
|
[[play](https://go.dev/play/p/lkQ3Ri2NQhV)]
|
||||||
|
- **<big>Random</big>** : get a random item of slice, return its index, when slice is empty, return -1.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/slice.md#Random)]
|
||||||
|
|
||||||
<h3 id="stream"> 19. Stream package implements a sequence of elements supporting sequential and operations. this package is an experiment to explore if stream in go can work as the way java does. its function is very limited. <a href="#index">index</a></h3>
|
<h3 id="stream"> 19. Stream package implements a sequence of elements supporting sequential and operations. this package is an experiment to explore if stream in go can work as the way java does. its function is very limited. <a href="#index">index</a></h3>
|
||||||
|
|
||||||
@@ -1553,6 +1565,7 @@ import "github.com/duke-git/lancet/v2/strutil"
|
|||||||
[[play](https://go.dev/play/p/6zXRH_c0Qd3)]
|
[[play](https://go.dev/play/p/6zXRH_c0Qd3)]
|
||||||
- **<big>IsNotBlank</big>** : checks if a string is not whitespace or not empty.
|
- **<big>IsNotBlank</big>** : checks if a string is not whitespace or not empty.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#IsNotBlank)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#IsNotBlank)]
|
||||||
|
[[play](https://go.dev/play/p/e_oJW0RAquA)]
|
||||||
- **<big>HasPrefixAny</big>** : checks if a string starts with any of an array of specified strings.
|
- **<big>HasPrefixAny</big>** : checks if a string starts with any of an array of specified strings.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#HasPrefixAny)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/strutil.md#HasPrefixAny)]
|
||||||
[[play](https://go.dev/play/p/8UUTl2C5slo)]
|
[[play](https://go.dev/play/p/8UUTl2C5slo)]
|
||||||
|
|||||||
@@ -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/v2)
|
[](https://pkg.go.dev/github.com/duke-git/lancet/v2)
|
||||||
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
||||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||||
@@ -453,10 +453,14 @@ import "github.com/duke-git/lancet/v2/cryptor"
|
|||||||
[[play](https://go.dev/play/p/uef0q1fz53I)]
|
[[play](https://go.dev/play/p/uef0q1fz53I)]
|
||||||
- **<big>GenerateRsaKeyPair</big>** : 创建rsa公钥私钥和key。
|
- **<big>GenerateRsaKeyPair</big>** : 创建rsa公钥私钥和key。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#GenerateRsaKeyPair)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#GenerateRsaKeyPair)]
|
||||||
|
[[play](https://go.dev/play/p/sSVmkfENKMz)]
|
||||||
- **<big>RsaEncryptOAEP</big>** : rsa OAEP加密。
|
- **<big>RsaEncryptOAEP</big>** : rsa OAEP加密。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#RsaEncryptOAEP)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#RsaEncryptOAEP)]
|
||||||
|
[[play](https://go.dev/play/p/sSVmkfENKMz)]
|
||||||
- **<big>RsaDecryptOAEP</big>** : rsa OAEP解密。
|
- **<big>RsaDecryptOAEP</big>** : rsa OAEP解密。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#RsaDecryptOAEP)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/cryptor.md#RsaDecryptOAEP)]
|
||||||
|
[[play](https://go.dev/play/p/sSVmkfENKMz)]
|
||||||
|
|
||||||
|
|
||||||
<h3 id="datetime"> 7. datetime 日期时间处理包,格式化日期,比较日期。 <a href="#index">回到目录</a></h3>
|
<h3 id="datetime"> 7. datetime 日期时间处理包,格式化日期,比较日期。 <a href="#index">回到目录</a></h3>
|
||||||
|
|
||||||
@@ -568,9 +572,6 @@ import "github.com/duke-git/lancet/v2/datetime"
|
|||||||
- **<big>IsLeapYear</big>** :验证是否是闰年。
|
- **<big>IsLeapYear</big>** :验证是否是闰年。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#IsLeapYear)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#IsLeapYear)]
|
||||||
[[play](https://go.dev/play/p/xS1eS2ejGew)]
|
[[play](https://go.dev/play/p/xS1eS2ejGew)]
|
||||||
- **<big>IsLeapYear</big>** : check if param `year` is leap year or not.
|
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#IsLeapYear)]
|
|
||||||
[[play](https://go.dev/play/p/xS1eS2ejGew)]
|
|
||||||
- **<big>BetweenSeconds</big>** : 返回两个时间的间隔秒数。
|
- **<big>BetweenSeconds</big>** : 返回两个时间的间隔秒数。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#BetweenSeconds)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#BetweenSeconds)]
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#BetweenSeconds)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/datetime.md#BetweenSeconds)]
|
||||||
@@ -1097,6 +1098,14 @@ import "github.com/duke-git/lancet/v2/random"
|
|||||||
- **<big>RandUniqueIntSlice</big>** : 生成一个不重复的长度为 n 的随机 int 切片。
|
- **<big>RandUniqueIntSlice</big>** : 生成一个不重复的长度为 n 的随机 int 切片。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandUniqueIntSlice)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandUniqueIntSlice)]
|
||||||
[[play](https://go.dev/play/p/uBkRSOz73Ec)]
|
[[play](https://go.dev/play/p/uBkRSOz73Ec)]
|
||||||
|
- **<big>RandSymbolChar</big>** : 生成给定长度的随机符号字符串。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandSymbolChar)]
|
||||||
|
[[play](https://go.dev/play/p/uBkRSOz73Ec)]
|
||||||
|
- **<big>RandFloat</big>** : 生成随机float64数字,可以指定范围和精度。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandFloat)]
|
||||||
|
[[play](https://go.dev/play/p/uBkRSOz73Ec)]
|
||||||
|
- **<big>RandFloats</big>** : 生成随机float64数字切片,可以指定长度,范围和精度.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/random.md#RandFloats)]
|
||||||
|
|
||||||
<h3 id="retry"> 17. retry 重试执行函数直到函数运行成功或被 context cancel。 <a href="#index">回到目录</a></h3>
|
<h3 id="retry"> 17. retry 重试执行函数直到函数运行成功或被 context cancel。 <a href="#index">回到目录</a></h3>
|
||||||
|
|
||||||
@@ -1122,7 +1131,7 @@ import "github.com/duke-git/lancet/v2/retry"
|
|||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/retry.md#RetryTimes)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/retry.md#RetryTimes)]
|
||||||
[[play](https://go.dev/play/p/ssfVeU2SwLO)]
|
[[play](https://go.dev/play/p/ssfVeU2SwLO)]
|
||||||
|
|
||||||
<h3 id="slice"> 18. slice 包含操作切片的方法集合。 [回到目录](#index)
|
<h3 id="slice"> 18. slice 包含操作切片的方法集合。 <a href="#index">回到目录</a></h3>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/slice"
|
import "github.com/duke-git/lancet/v2/slice"
|
||||||
@@ -1340,6 +1349,9 @@ import "github.com/duke-git/lancet/v2/slice"
|
|||||||
- **<big>Partition</big>** : 根据给定的predicate判断函数分组切片元素。
|
- **<big>Partition</big>** : 根据给定的predicate判断函数分组切片元素。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Partition)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Partition)]
|
||||||
[[play](https://go.dev/play/p/lkQ3Ri2NQhV)]
|
[[play](https://go.dev/play/p/lkQ3Ri2NQhV)]
|
||||||
|
- **<big>Random</big>** : 随机返回切片中元素以及下标, 当切片长度为0时返回下标-1。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/slice.md#Random)]
|
||||||
|
|
||||||
|
|
||||||
<h3 id="stream"> 19. stream 流,该包仅验证简单的 stream 实现,功能有限。 <a href="#index">回到目录</a></h3>
|
<h3 id="stream"> 19. stream 流,该包仅验证简单的 stream 实现,功能有限。 <a href="#index">回到目录</a></h3>
|
||||||
|
|
||||||
@@ -1560,6 +1572,7 @@ import "github.com/duke-git/lancet/v2/strutil"
|
|||||||
[[play](https://go.dev/play/p/6zXRH_c0Qd3)]
|
[[play](https://go.dev/play/p/6zXRH_c0Qd3)]
|
||||||
- **<big>IsNotBlank</big>** : 检查字符串是否不为空。
|
- **<big>IsNotBlank</big>** : 检查字符串是否不为空。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#IsNotBlank)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#IsNotBlank)]
|
||||||
|
[[play](https://go.dev/play/p/e_oJW0RAquA)]
|
||||||
- **<big>HasPrefixAny</big>** : 检查字符串是否以指定字符串数组中的任何一个开头。
|
- **<big>HasPrefixAny</big>** : 检查字符串是否以指定字符串数组中的任何一个开头。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#HasPrefixAny)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/strutil.md#HasPrefixAny)]
|
||||||
[[play](https://go.dev/play/p/8UUTl2C5slo)]
|
[[play](https://go.dev/play/p/8UUTl2C5slo)]
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ func compareRefValue(operator string, leftObj, rightObj any, kind reflect.Kind)
|
|||||||
|
|
||||||
switch operator {
|
switch operator {
|
||||||
case equal:
|
case equal:
|
||||||
if bytes.Compare(bytesObj1, bytesObj2) == 0 {
|
if bytes.Equal(bytesObj1, bytesObj2) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
case lessThan:
|
case lessThan:
|
||||||
|
|||||||
@@ -508,14 +508,14 @@ func RsaDecrypt(data []byte, privateKeyFileName string) []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GenerateRsaKeyPair create rsa private and public key.
|
// GenerateRsaKeyPair create rsa private and public key.
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/sSVmkfENKMz
|
||||||
func GenerateRsaKeyPair(keySize int) (*rsa.PrivateKey, *rsa.PublicKey) {
|
func GenerateRsaKeyPair(keySize int) (*rsa.PrivateKey, *rsa.PublicKey) {
|
||||||
privateKey, _ := rsa.GenerateKey(rand.Reader, keySize)
|
privateKey, _ := rsa.GenerateKey(rand.Reader, keySize)
|
||||||
return privateKey, &privateKey.PublicKey
|
return privateKey, &privateKey.PublicKey
|
||||||
}
|
}
|
||||||
|
|
||||||
// RsaEncryptOAEP encrypts the given data with RSA-OAEP.
|
// RsaEncryptOAEP encrypts the given data with RSA-OAEP.
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/sSVmkfENKMz
|
||||||
func RsaEncryptOAEP(data []byte, label []byte, key rsa.PublicKey) ([]byte, error) {
|
func RsaEncryptOAEP(data []byte, label []byte, key rsa.PublicKey) ([]byte, error) {
|
||||||
encryptedBytes, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, &key, data, label)
|
encryptedBytes, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, &key, data, label)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -526,7 +526,7 @@ func RsaEncryptOAEP(data []byte, label []byte, key rsa.PublicKey) ([]byte, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RsaDecryptOAEP decrypts the data with RSA-OAEP.
|
// RsaDecryptOAEP decrypts the data with RSA-OAEP.
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/sSVmkfENKMz
|
||||||
func RsaDecryptOAEP(ciphertext []byte, label []byte, key rsa.PrivateKey) ([]byte, error) {
|
func RsaDecryptOAEP(ciphertext []byte, label []byte, key rsa.PrivateKey) ([]byte, error) {
|
||||||
decryptedBytes, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, &key, ciphertext, label)
|
decryptedBytes, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, &key, ciphertext, label)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -1437,7 +1437,7 @@ func main() {
|
|||||||
func GenerateRsaKeyPair(keySize int) (*rsa.PrivateKey, *rsa.PublicKey)
|
func GenerateRsaKeyPair(keySize int) (*rsa.PrivateKey, *rsa.PublicKey)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:></b>
|
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/sSVmkfENKMz)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -1462,7 +1462,7 @@ func main() {
|
|||||||
func RsaEncryptOAEP(data []byte, label []byte, key rsa.PublicKey) ([]byte, error)
|
func RsaEncryptOAEP(data []byte, label []byte, key rsa.PublicKey) ([]byte, error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:></b>
|
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/sSVmkfENKMz)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -1505,7 +1505,7 @@ func main() {
|
|||||||
func RsaDecryptOAEP(ciphertext []byte, label []byte, key rsa.PrivateKey) ([]byte, error)
|
func RsaDecryptOAEP(ciphertext []byte, label []byte, key rsa.PrivateKey) ([]byte, error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:></b>
|
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/sSVmkfENKMz)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -843,7 +843,7 @@ func main() {
|
|||||||
|
|
||||||
### <span id="ReadFile">ReadFile</span>
|
### <span id="ReadFile">ReadFile</span>
|
||||||
|
|
||||||
<p>读取文件或者URL</p>
|
<p>读取文件或者URL。</p>
|
||||||
|
|
||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
@@ -851,7 +851,7 @@ func main() {
|
|||||||
func ReadFile(path string) (reader io.ReadCloser, closeFn func(), err error)
|
func ReadFile(path string) (reader io.ReadCloser, closeFn func(), err error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:<span style="float:right;display:inline-block;"></span></b>
|
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/uNep3Tr8fqF)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -862,19 +862,19 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
reader, fn, err := ReadFile("https://httpbin.org/robots.txt")
|
reader, fn, err := fileutil.ReadFile("https://httpbin.org/robots.txt")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer fn()
|
defer fn()
|
||||||
|
|
||||||
dat, err := io.ReadAll(reader)
|
dat, err := io.ReadAll(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fmt.Println(string(dat))
|
fmt.Println(string(dat))
|
||||||
// Output:
|
// Output:
|
||||||
// User-agent: *
|
// User-agent: *
|
||||||
// Disallow: /deny
|
// Disallow: /deny
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -29,8 +29,11 @@ import (
|
|||||||
- [RandLower](#RandLower)
|
- [RandLower](#RandLower)
|
||||||
- [RandNumeral](#RandNumeral)
|
- [RandNumeral](#RandNumeral)
|
||||||
- [RandNumeralOrLetter](#RandNumeralOrLetter)
|
- [RandNumeralOrLetter](#RandNumeralOrLetter)
|
||||||
|
- [RandSymbolChar](#RandSymbolChar)
|
||||||
- [UUIdV4](#UUIdV4)
|
- [UUIdV4](#UUIdV4)
|
||||||
- [RandUniqueIntSlice](#RandUniqueIntSlice)
|
- [RandUniqueIntSlice](#RandUniqueIntSlice)
|
||||||
|
- [RandFloat](#RandFloat)
|
||||||
|
- [RandFloats](#RandFloats)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -218,6 +221,32 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="RandSymbolChar">RandSymbolChar</span>
|
||||||
|
|
||||||
|
<p>生成给定长度的随机符号字符串. 符号字符包括: !@#$%^&*()_+-=[]{}|;':\",./<>?。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func RandSymbolChar(length int) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/random"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
randStr := random.RandSymbolChar(6)
|
||||||
|
fmt.Println(randStr) //@#(_")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="UUIdV4">UUIdV4</span>
|
### <span id="UUIdV4">UUIdV4</span>
|
||||||
|
|
||||||
<p>生成UUID v4字符串</p>
|
<p>生成UUID v4字符串</p>
|
||||||
@@ -272,3 +301,55 @@ func main() {
|
|||||||
fmt.Println(result) //[0 4 7 1 5] (random)
|
fmt.Println(result) //[0 4 7 1 5] (random)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="RandFloat">RandFloat</span>
|
||||||
|
|
||||||
|
<p>生成随机float64数字,可以指定范围和精度。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func RandFloat(min, max float64, precision int) float64
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>实例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/random"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
floatNumber := random.RandFloat(1.0, 5.0, 2)
|
||||||
|
fmt.Println(floatNumber) //2.14 (random number)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="RandFloats">RandFloats</span>
|
||||||
|
|
||||||
|
<p>生成随机float64数字切片,指定长度,范围和精度.</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func RandFloats(n int, min, max float64, precision int) []float64
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>实例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/random"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
floatNumbers := random.RandFloats(5, 1.0, 5.0, 2)
|
||||||
|
fmt.Println(floatNumber) //[3.42 3.99 1.3 2.38 4.23] (random)
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -2488,4 +2488,35 @@ func main() {
|
|||||||
// [[2 4] [1 3 5]]
|
// [[2 4] [1 3 5]]
|
||||||
// [[1 2] [3 4] [5]]
|
// [[1 2] [3 4] [5]]
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="Random">Random</span>
|
||||||
|
|
||||||
|
<p>随机返回切片中元素以及下标, 当切片长度为0时返回下标-1</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Random[T any](slice []T) (val T, idx int)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:<span style="float:right;display:inline-block;">[运行](TODO)</span></b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/slice"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
nums := []int{1, 2, 3, 4, 5}
|
||||||
|
|
||||||
|
val, idx := slice.Random(nums)
|
||||||
|
if idx >= 0 && idx < len(nums) && slice.Contain(nums, val) {
|
||||||
|
fmt.Println("okk")
|
||||||
|
}
|
||||||
|
// Output:
|
||||||
|
// okk
|
||||||
|
}
|
||||||
```
|
```
|
||||||
@@ -1080,13 +1080,13 @@ func main() {
|
|||||||
|
|
||||||
<p>Checks if a string is not whitespace or not empty.</p>
|
<p>Checks if a string is not whitespace or not empty.</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func IsNotBlank(str string) bool
|
func IsNotBlank(str string) bool
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/e_oJW0RAquA)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
@@ -1095,11 +1095,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
result1 := IsNotBlank("")
|
result1 := strutil.IsNotBlank("")
|
||||||
result2 := IsNotBlank(" ")
|
result2 := strutil.IsNotBlank(" ")
|
||||||
result3 := IsNotBlank("\t\v\f\n")
|
result3 := strutil.IsNotBlank("\t\v\f\n")
|
||||||
result4 := IsNotBlank(" 中文")
|
result4 := strutil.IsNotBlank(" 中文")
|
||||||
result5 := IsNotBlank(" world ")
|
result5 := strutil.IsNotBlank(" world ")
|
||||||
|
|
||||||
fmt.Println(result1)
|
fmt.Println(result1)
|
||||||
fmt.Println(result2)
|
fmt.Println(result2)
|
||||||
|
|||||||
@@ -1437,7 +1437,7 @@ func main() {
|
|||||||
func GenerateRsaKeyPair(keySize int) (*rsa.PrivateKey, *rsa.PublicKey)
|
func GenerateRsaKeyPair(keySize int) (*rsa.PrivateKey, *rsa.PublicKey)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:></b>
|
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/sSVmkfENKMz)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -1462,7 +1462,7 @@ func main() {
|
|||||||
func RsaEncryptOAEP(data []byte, label []byte, key rsa.PublicKey) ([]byte, error)
|
func RsaEncryptOAEP(data []byte, label []byte, key rsa.PublicKey) ([]byte, error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:></b>
|
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/sSVmkfENKMz)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -1505,7 +1505,7 @@ func main() {
|
|||||||
func RsaDecryptOAEP(ciphertext []byte, label []byte, key rsa.PrivateKey) ([]byte, error)
|
func RsaDecryptOAEP(ciphertext []byte, label []byte, key rsa.PrivateKey) ([]byte, error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:></b>
|
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/sSVmkfENKMz)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -843,7 +843,7 @@ func main() {
|
|||||||
|
|
||||||
### <span id="ReadFile">ReadFile</span>
|
### <span id="ReadFile">ReadFile</span>
|
||||||
|
|
||||||
<p>Read File/URL</p>
|
<p>Read File or URL.</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
@@ -851,7 +851,7 @@ func main() {
|
|||||||
func ReadFile(path string) (reader io.ReadCloser, closeFn func(), err error)
|
func ReadFile(path string) (reader io.ReadCloser, closeFn func(), err error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:<span style="float:right;display:inline-block;"> </span></b>
|
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/uNep3Tr8fqF)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -862,19 +862,19 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
reader, fn, err := ReadFile("https://httpbin.org/robots.txt")
|
reader, fn, err := fileutil.ReadFile("https://httpbin.org/robots.txt")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer fn()
|
defer fn()
|
||||||
|
|
||||||
dat, err := io.ReadAll(reader)
|
dat, err := io.ReadAll(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fmt.Println(string(dat))
|
fmt.Println(string(dat))
|
||||||
// Output:
|
// Output:
|
||||||
// User-agent: *
|
// User-agent: *
|
||||||
// Disallow: /deny
|
// Disallow: /deny
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -29,8 +29,11 @@ import (
|
|||||||
- [RandLower](#RandLower)
|
- [RandLower](#RandLower)
|
||||||
- [RandNumeral](#RandNumeral)
|
- [RandNumeral](#RandNumeral)
|
||||||
- [RandNumeralOrLetter](#RandNumeralOrLetter)
|
- [RandNumeralOrLetter](#RandNumeralOrLetter)
|
||||||
|
- [RandSymbolChar](#RandSymbolChar)
|
||||||
- [UUIdV4](#UUIdV4)
|
- [UUIdV4](#UUIdV4)
|
||||||
- [RandUniqueIntSlice](#RandUniqueIntSlice)
|
- [RandUniqueIntSlice](#RandUniqueIntSlice)
|
||||||
|
- [RandFloat](#RandFloat)
|
||||||
|
- [RandFloats](#RandFloats)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -218,6 +221,32 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="RandSymbolChar">RandSymbolChar</span>
|
||||||
|
|
||||||
|
<p>Generate a random symbol char of specified length. Symbol chars: !@#$%^&*()_+-=[]{}|;':\",./<>?.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func RandSymbolChar(length int) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/random"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
randStr := random.RandSymbolChar(6)
|
||||||
|
fmt.Println(randStr) //@#(_")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="UUIdV4">UUIdV4</span>
|
### <span id="UUIdV4">UUIdV4</span>
|
||||||
|
|
||||||
<p>Generate a random UUID of version 4 according to RFC 4122.</p>
|
<p>Generate a random UUID of version 4 according to RFC 4122.</p>
|
||||||
@@ -273,3 +302,55 @@ func main() {
|
|||||||
fmt.Println(result) //[0 4 7 1 5] (random)
|
fmt.Println(result) //[0 4 7 1 5] (random)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="RandFloat">RandFloat</span>
|
||||||
|
|
||||||
|
<p>Generate a random float64 number between [min, max) with specific precision.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func RandFloat(min, max float64, precision int) float64
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/random"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
floatNumber := random.RandFloat(1.0, 5.0, 2)
|
||||||
|
fmt.Println(floatNumber) //2.14 (random number)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="RandFloats">RandFloats</span>
|
||||||
|
|
||||||
|
<p>Generate a slice of random float64 numbers of length n that do not repeat.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func RandFloats(n int, min, max float64, precision int) []float64
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/random"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
floatNumbers := random.RandFloats(5, 1.0, 5.0, 2)
|
||||||
|
fmt.Println(floatNumber) //[3.42 3.99 1.3 2.38 4.23] (random)
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -2486,4 +2486,34 @@ func main() {
|
|||||||
// [[2 4] [1 3 5]]
|
// [[2 4] [1 3 5]]
|
||||||
// [[1 2] [3 4] [5]]
|
// [[1 2] [3 4] [5]]
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Random">Random</span>
|
||||||
|
|
||||||
|
<p>Random get a random item of slice, return idx=-1 when slice is empty. </p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Random[T any](slice []T) (val T, idx int)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:<span style="float:right;display:inline-block;">[Run](TODO)</span></b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/slice"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
nums := []int{1, 2, 3, 4, 5}
|
||||||
|
|
||||||
|
val, idx := slice.Random(nums)
|
||||||
|
if idx >= 0 && idx < len(nums) && slice.Contain(nums, val) {
|
||||||
|
fmt.Println("okk")
|
||||||
|
}
|
||||||
|
// Output:
|
||||||
|
// okk
|
||||||
|
}
|
||||||
```
|
```
|
||||||
@@ -1087,7 +1087,7 @@ func main() {
|
|||||||
func IsNotBlank(str string) bool
|
func IsNotBlank(str string) bool
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/e_oJW0RAquA)</span></b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
@@ -1096,11 +1096,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
result1 := IsNotBlank("")
|
result1 := strutil.IsNotBlank("")
|
||||||
result2 := IsNotBlank(" ")
|
result2 := strutil.IsNotBlank(" ")
|
||||||
result3 := IsNotBlank("\t\v\f\n")
|
result3 := strutil.IsNotBlank("\t\v\f\n")
|
||||||
result4 := IsNotBlank(" 中文")
|
result4 := strutil.IsNotBlank(" 中文")
|
||||||
result5 := IsNotBlank(" world ")
|
result5 := strutil.IsNotBlank(" world ")
|
||||||
|
|
||||||
fmt.Println(result1)
|
fmt.Println(result1)
|
||||||
fmt.Println(result2)
|
fmt.Println(result2)
|
||||||
|
|||||||
@@ -627,7 +627,7 @@ func WriteBytesToFile(filepath string, content []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ReadFile get file reader by a url or a local file
|
// ReadFile get file reader by a url or a local file
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/uNep3Tr8fqF
|
||||||
func ReadFile(path string) (reader io.ReadCloser, closeFn func(), err error) {
|
func ReadFile(path string) (reader io.ReadCloser, closeFn func(), err error) {
|
||||||
switch {
|
switch {
|
||||||
case validator.IsUrl(path):
|
case validator.IsUrl(path):
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ package netutil
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
@@ -110,22 +111,23 @@ type HttpClientConfig struct {
|
|||||||
Verbose bool
|
Verbose bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaultHttpClientConfig defalut client config
|
// defaultHttpClientConfig defalut client config.
|
||||||
var defaultHttpClientConfig = &HttpClientConfig{
|
var defaultHttpClientConfig = &HttpClientConfig{
|
||||||
Compressed: false,
|
Compressed: false,
|
||||||
HandshakeTimeout: 20 * time.Second,
|
HandshakeTimeout: 20 * time.Second,
|
||||||
ResponseTimeout: 40 * time.Second,
|
ResponseTimeout: 40 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
// HttpClient is used for sending http request
|
// HttpClient is used for sending http request.
|
||||||
type HttpClient struct {
|
type HttpClient struct {
|
||||||
*http.Client
|
*http.Client
|
||||||
TLS *tls.Config
|
TLS *tls.Config
|
||||||
Request *http.Request
|
Request *http.Request
|
||||||
Config HttpClientConfig
|
Config HttpClientConfig
|
||||||
|
Context context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHttpClient make a HttpClient instance
|
// NewHttpClient make a HttpClient instance.
|
||||||
func NewHttpClient() *HttpClient {
|
func NewHttpClient() *HttpClient {
|
||||||
client := &HttpClient{
|
client := &HttpClient{
|
||||||
Client: &http.Client{
|
Client: &http.Client{
|
||||||
@@ -141,7 +143,7 @@ func NewHttpClient() *HttpClient {
|
|||||||
return client
|
return client
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHttpClientWithConfig make a HttpClient instance with pass config
|
// NewHttpClientWithConfig make a HttpClient instance with pass config.
|
||||||
func NewHttpClientWithConfig(config *HttpClientConfig) *HttpClient {
|
func NewHttpClientWithConfig(config *HttpClientConfig) *HttpClient {
|
||||||
if config == nil {
|
if config == nil {
|
||||||
config = defaultHttpClientConfig
|
config = defaultHttpClientConfig
|
||||||
@@ -176,6 +178,11 @@ func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, err
|
|||||||
rawUrl := request.RawURL
|
rawUrl := request.RawURL
|
||||||
|
|
||||||
req, err := http.NewRequest(request.Method, rawUrl, bytes.NewBuffer(request.Body))
|
req, err := http.NewRequest(request.Method, rawUrl, bytes.NewBuffer(request.Body))
|
||||||
|
|
||||||
|
if client.Context != nil {
|
||||||
|
req, err = http.NewRequestWithContext(client.Context, request.Method, rawUrl, bytes.NewBuffer(request.Body))
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/v2/mathutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -17,13 +19,14 @@ const (
|
|||||||
LowwerLetters = "abcdefghijklmnopqrstuvwxyz"
|
LowwerLetters = "abcdefghijklmnopqrstuvwxyz"
|
||||||
UpperLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
UpperLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
Letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
Letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
SymbolChars = "!@#$%^&*()_+-=[]{}|;':\",./<>?"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rand.Seed(time.Now().UnixNano())
|
rand.Seed(time.Now().UnixNano())
|
||||||
}
|
}
|
||||||
|
|
||||||
// RandInt generate random int between min and max, maybe min, not be max.
|
// RandInt generate random int between [min, max).
|
||||||
// Play: https://go.dev/play/p/pXyyAAI5YxD
|
// Play: https://go.dev/play/p/pXyyAAI5YxD
|
||||||
func RandInt(min, max int) int {
|
func RandInt(min, max int) int {
|
||||||
if min == max {
|
if min == max {
|
||||||
@@ -37,6 +40,22 @@ func RandInt(min, max int) int {
|
|||||||
return rand.Intn(max-min) + min
|
return rand.Intn(max-min) + min
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RandFloat generate random float64 number between [min, max) with specific precision.
|
||||||
|
// Play: todo
|
||||||
|
func RandFloat(min, max float64, precision int) float64 {
|
||||||
|
if min == max {
|
||||||
|
return min
|
||||||
|
}
|
||||||
|
|
||||||
|
if max < min {
|
||||||
|
min, max = max, min
|
||||||
|
}
|
||||||
|
|
||||||
|
n := rand.Float64()*(max-min) + min
|
||||||
|
|
||||||
|
return mathutil.RoundToFloat(n, precision)
|
||||||
|
}
|
||||||
|
|
||||||
// RandBytes generate random byte slice.
|
// RandBytes generate random byte slice.
|
||||||
// Play: https://go.dev/play/p/EkiLESeXf8d
|
// Play: https://go.dev/play/p/EkiLESeXf8d
|
||||||
func RandBytes(length int) []byte {
|
func RandBytes(length int) []byte {
|
||||||
@@ -52,19 +71,19 @@ func RandBytes(length int) []byte {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// RandString generate random string of specified length.
|
// RandString generate random alpha string of specified length.
|
||||||
// Play: https://go.dev/play/p/W2xvRUXA7Mi
|
// Play: https://go.dev/play/p/W2xvRUXA7Mi
|
||||||
func RandString(length int) string {
|
func RandString(length int) string {
|
||||||
return random(Letters, length)
|
return random(Letters, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RandUpper generate a random upper case string.
|
// RandUpper generate a random upper case string of specified length.
|
||||||
// Play: https://go.dev/play/p/29QfOh0DVuh
|
// Play: https://go.dev/play/p/29QfOh0DVuh
|
||||||
func RandUpper(length int) string {
|
func RandUpper(length int) string {
|
||||||
return random(UpperLetters, length)
|
return random(UpperLetters, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RandLower generate a random lower case string.
|
// RandLower generate a random lower case string of specified length.
|
||||||
// Play: https://go.dev/play/p/XJtZ471cmtI
|
// Play: https://go.dev/play/p/XJtZ471cmtI
|
||||||
func RandLower(length int) string {
|
func RandLower(length int) string {
|
||||||
return random(LowwerLetters, length)
|
return random(LowwerLetters, length)
|
||||||
@@ -76,12 +95,19 @@ func RandNumeral(length int) string {
|
|||||||
return random(Numeral, length)
|
return random(Numeral, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RandNumeralOrLetter generate a random numeral or letter string.
|
// RandNumeralOrLetter generate a random numeral or alpha string of specified length.
|
||||||
// Play: https://go.dev/play/p/19CEQvpx2jD
|
// Play: https://go.dev/play/p/19CEQvpx2jD
|
||||||
func RandNumeralOrLetter(length int) string {
|
func RandNumeralOrLetter(length int) string {
|
||||||
return random(Numeral+Letters, length)
|
return random(Numeral+Letters, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RandSymbolChar generate a random symbol char of specified length.
|
||||||
|
// symbol chars: !@#$%^&*()_+-=[]{}|;':\",./<>?.
|
||||||
|
// Play: todo
|
||||||
|
func RandSymbolChar(length int) string {
|
||||||
|
return random(SymbolChars, length)
|
||||||
|
}
|
||||||
|
|
||||||
// random generate a random string based on given string range.
|
// random generate a random string based on given string range.
|
||||||
func random(s string, length int) string {
|
func random(s string, length int) string {
|
||||||
b := make([]byte, length)
|
b := make([]byte, length)
|
||||||
@@ -136,3 +162,21 @@ func RandUniqueIntSlice(n, min, max int) []int {
|
|||||||
|
|
||||||
return nums
|
return nums
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RandFloats generate a slice of random float64 numbers of length n that do not repeat.
|
||||||
|
// Play: todo
|
||||||
|
func RandFloats(n int, min, max float64, precision int) []float64 {
|
||||||
|
nums := make([]float64, n)
|
||||||
|
used := make(map[float64]struct{}, n)
|
||||||
|
for i := 0; i < n; {
|
||||||
|
r := RandFloat(min, max, precision)
|
||||||
|
if _, use := used[r]; use {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
used[r] = struct{}{}
|
||||||
|
nums[i] = r
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
return nums
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package random
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ExampleRandInt() {
|
func ExampleRandInt() {
|
||||||
@@ -134,3 +135,53 @@ func ExampleRandUniqueIntSlice() {
|
|||||||
// Output:
|
// Output:
|
||||||
// ok
|
// ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleRandSymbolChar() {
|
||||||
|
pattern := `^[\W|_]+$`
|
||||||
|
reg := regexp.MustCompile(pattern)
|
||||||
|
|
||||||
|
s := RandSymbolChar(6)
|
||||||
|
|
||||||
|
result1 := reg.MatchString(s)
|
||||||
|
result2 := len(s)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// 6
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleRandFloat() {
|
||||||
|
pattern := `^[\d{1}.\d{2}]+$`
|
||||||
|
reg := regexp.MustCompile(pattern)
|
||||||
|
|
||||||
|
num := RandFloat(1.0, 5.0, 2)
|
||||||
|
|
||||||
|
// check num is a random float in [1.0, 5.0)
|
||||||
|
result1 := num >= 1.0 && num < 5.0
|
||||||
|
result2 := reg.MatchString(strconv.FormatFloat(num, 'f', -1, 64))
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleRandFloats() {
|
||||||
|
isInRange := true
|
||||||
|
numbers := RandFloats(5, 1.0, 5.0, 2)
|
||||||
|
for _, n := range numbers {
|
||||||
|
isInRange = (n >= 1.0 && n < 5.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(isInRange)
|
||||||
|
fmt.Println(len(numbers))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// 5
|
||||||
|
}
|
||||||
|
|||||||
@@ -154,3 +154,45 @@ func hasDuplicate(arr []int) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRandSymbolChar(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
pattern := `^[\W|_]+$`
|
||||||
|
reg := regexp.MustCompile(pattern)
|
||||||
|
|
||||||
|
symbolChars := RandSymbolChar(10)
|
||||||
|
|
||||||
|
assert := internal.NewAssert(t, "TestRandSymbolChar")
|
||||||
|
assert.Equal(10, len(symbolChars))
|
||||||
|
assert.Equal(true, reg.MatchString(symbolChars))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRandFloat(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
assert := internal.NewAssert(t, "TestRandFloat")
|
||||||
|
|
||||||
|
r1 := RandFloat(1.1, 10.1, 2)
|
||||||
|
assert.GreaterOrEqual(r1, 1.1)
|
||||||
|
assert.Less(r1, 10.1)
|
||||||
|
|
||||||
|
r2 := RandFloat(1.1, 1.1, 2)
|
||||||
|
assert.Equal(1.1, r2)
|
||||||
|
|
||||||
|
r3 := RandFloat(10.1, 1.1, 2)
|
||||||
|
assert.GreaterOrEqual(r1, 1.1)
|
||||||
|
assert.Less(r3, 10.1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRandFloats(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
assert := internal.NewAssert(t, "TestRandFloats")
|
||||||
|
|
||||||
|
numbers := RandFloats(5, 1.0, 5.0, 2)
|
||||||
|
for _, n := range numbers {
|
||||||
|
assert.Equal(true, (n >= 1.0 && n < 5.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(len(numbers), 5)
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/v2/random"
|
||||||
"golang.org/x/exp/constraints"
|
"golang.org/x/exp/constraints"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1229,3 +1230,14 @@ func Partition[T any](slice []T, predicates ...func(item T) bool) [][]T {
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Random get a random item of slice, return idx=-1 when slice is empty
|
||||||
|
// Play: todo
|
||||||
|
func Random[T any](slice []T) (val T, idx int) {
|
||||||
|
if len(slice) == 0 {
|
||||||
|
return val, -1
|
||||||
|
}
|
||||||
|
|
||||||
|
idx = random.RandInt(0, len(slice))
|
||||||
|
return slice[idx], idx
|
||||||
|
}
|
||||||
|
|||||||
@@ -1063,3 +1063,14 @@ func ExamplePartition() {
|
|||||||
// [[2 4] [1 3 5]]
|
// [[2 4] [1 3 5]]
|
||||||
// [[1 2] [3 4] [5]]
|
// [[1 2] [3 4] [5]]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleRandom() {
|
||||||
|
nums := []int{1, 2, 3, 4, 5}
|
||||||
|
|
||||||
|
val, idx := Random(nums)
|
||||||
|
if idx >= 0 && idx < len(nums) && Contain(nums, val) {
|
||||||
|
fmt.Println("okk")
|
||||||
|
}
|
||||||
|
// Output:
|
||||||
|
// okk
|
||||||
|
}
|
||||||
|
|||||||
@@ -1185,3 +1185,28 @@ func TestPartition(t *testing.T) {
|
|||||||
assert.Equal([][]int{{2, 4}, {1, 3, 5}}, Partition([]int{1, 2, 3, 4, 5}, func(n int) bool { return n%2 == 0 }))
|
assert.Equal([][]int{{2, 4}, {1, 3, 5}}, Partition([]int{1, 2, 3, 4, 5}, func(n int) bool { return n%2 == 0 }))
|
||||||
assert.Equal([][]int{{1, 2}, {3, 4}, {5}}, Partition([]int{1, 2, 3, 4, 5}, func(n int) bool { return n == 1 || n == 2 }, func(n int) bool { return n == 2 || n == 3 || n == 4 }))
|
assert.Equal([][]int{{1, 2}, {3, 4}, {5}}, Partition([]int{1, 2, 3, 4, 5}, func(n int) bool { return n == 1 || n == 2 }, func(n int) bool { return n == 2 || n == 3 || n == 4 }))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRandom(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
assert := internal.NewAssert(t, "TestRandom")
|
||||||
|
|
||||||
|
var arr []int
|
||||||
|
var val, idx int
|
||||||
|
|
||||||
|
_, idx = Random(arr)
|
||||||
|
assert.Equal(-1, idx)
|
||||||
|
|
||||||
|
arr = []int{}
|
||||||
|
_, idx = Random(arr)
|
||||||
|
assert.Equal(-1, idx)
|
||||||
|
|
||||||
|
arr = []int{1}
|
||||||
|
val, idx = Random(arr)
|
||||||
|
assert.Equal(0, idx)
|
||||||
|
assert.Equal(arr[idx], val)
|
||||||
|
|
||||||
|
arr = []int{1, 2, 3}
|
||||||
|
val, idx = Random(arr)
|
||||||
|
assert.Greater(len(arr), idx)
|
||||||
|
assert.Equal(arr[idx], val)
|
||||||
|
}
|
||||||
|
|||||||
@@ -409,6 +409,7 @@ func IsBlank(str string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IsNotBlank checks if a string is not whitespace, not empty.
|
// IsNotBlank checks if a string is not whitespace, not empty.
|
||||||
|
// Play: https://go.dev/play/p/e_oJW0RAquA
|
||||||
func IsNotBlank(str string) bool {
|
func IsNotBlank(str string) bool {
|
||||||
return !IsBlank(str)
|
return !IsBlank(str)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,8 +32,10 @@ func splitIntoStrings(s string, upperCase bool) []string {
|
|||||||
|
|
||||||
for i := 0; i < len(runes)-1; i++ {
|
for i := 0; i < len(runes)-1; i++ {
|
||||||
if isUpper(runes[i][0]) && isLower(runes[i+1][0]) {
|
if isUpper(runes[i][0]) && isLower(runes[i+1][0]) {
|
||||||
runes[i+1] = append([]rune{runes[i][len(runes[i])-1]}, runes[i+1]...)
|
length := len(runes[i]) - 1
|
||||||
runes[i] = runes[i][:len(runes[i])-1]
|
temp := runes[i][length]
|
||||||
|
runes[i+1] = append([]rune{temp}, runes[i+1]...)
|
||||||
|
runes[i] = runes[i][:length]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,12 +6,14 @@ package validator
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
"unicode"
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -21,10 +23,10 @@ var (
|
|||||||
numberRegexMatcher *regexp.Regexp = regexp.MustCompile(`\d`)
|
numberRegexMatcher *regexp.Regexp = regexp.MustCompile(`\d`)
|
||||||
intStrMatcher *regexp.Regexp = regexp.MustCompile(`^[\+-]?\d+$`)
|
intStrMatcher *regexp.Regexp = regexp.MustCompile(`^[\+-]?\d+$`)
|
||||||
urlMatcher *regexp.Regexp = regexp.MustCompile(`^((ftp|http|https?):\/\/)?(\S+(:\S*)?@)?((([1-9]\d?|1\d\d|2[01]\d|22[0-3])(\.(1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(([a-zA-Z0-9]+([-\.][a-zA-Z0-9]+)*)|((www\.)?))?(([a-z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-z\x{00a1}-\x{ffff}]{2,}))?))(:(\d{1,5}))?((\/|\?|#)[^\s]*)?$`)
|
urlMatcher *regexp.Regexp = regexp.MustCompile(`^((ftp|http|https?):\/\/)?(\S+(:\S*)?@)?((([1-9]\d?|1\d\d|2[01]\d|22[0-3])(\.(1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(([a-zA-Z0-9]+([-\.][a-zA-Z0-9]+)*)|((www\.)?))?(([a-z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-z\x{00a1}-\x{ffff}]{2,}))?))(:(\d{1,5}))?((\/|\?|#)[^\s]*)?$`)
|
||||||
dnsMatcher *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z]([a-zA-Z0-9\-]+[\.]?)*[a-zA-Z0-9]$`)
|
dnsMatcher *regexp.Regexp = regexp.MustCompile(`^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$`)
|
||||||
emailMatcher *regexp.Regexp = regexp.MustCompile(`\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*`)
|
emailMatcher *regexp.Regexp = regexp.MustCompile(`\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*`)
|
||||||
chineseMobileMatcher *regexp.Regexp = regexp.MustCompile(`^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$`)
|
chineseMobileMatcher *regexp.Regexp = regexp.MustCompile(`^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$`)
|
||||||
chineseIdMatcher *regexp.Regexp = regexp.MustCompile(`^[1-9]\d{5}(18|19|20|21|22)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$`)
|
chineseIdMatcher *regexp.Regexp = regexp.MustCompile(`^(\d{17})([0-9]|X|x)$`)
|
||||||
chineseMatcher *regexp.Regexp = regexp.MustCompile("[\u4e00-\u9fa5]")
|
chineseMatcher *regexp.Regexp = regexp.MustCompile("[\u4e00-\u9fa5]")
|
||||||
chinesePhoneMatcher *regexp.Regexp = regexp.MustCompile(`\d{3}-\d{8}|\d{4}-\d{7}|\d{4}-\d{8}`)
|
chinesePhoneMatcher *regexp.Regexp = regexp.MustCompile(`\d{3}-\d{8}|\d{4}-\d{7}|\d{4}-\d{8}`)
|
||||||
creditCardMatcher *regexp.Regexp = regexp.MustCompile(`^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11}|6[27][0-9]{14})$`)
|
creditCardMatcher *regexp.Regexp = regexp.MustCompile(`^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11}|6[27][0-9]{14})$`)
|
||||||
@@ -39,6 +41,52 @@ var (
|
|||||||
chinaUnionPay *regexp.Regexp = regexp.MustCompile(`^62[0-9]{14,17}$`)
|
chinaUnionPay *regexp.Regexp = regexp.MustCompile(`^62[0-9]{14,17}$`)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Identity card formula
|
||||||
|
factor = [17]int{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}
|
||||||
|
// ID verification bit
|
||||||
|
verifyStr = [11]string{"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"}
|
||||||
|
// Starting year of ID card
|
||||||
|
birthStartYear = 1900
|
||||||
|
// Province code
|
||||||
|
provinceKv = map[string]struct{}{
|
||||||
|
"11": {},
|
||||||
|
"12": {},
|
||||||
|
"13": {},
|
||||||
|
"14": {},
|
||||||
|
"15": {},
|
||||||
|
"21": {},
|
||||||
|
"22": {},
|
||||||
|
"23": {},
|
||||||
|
"31": {},
|
||||||
|
"32": {},
|
||||||
|
"33": {},
|
||||||
|
"34": {},
|
||||||
|
"35": {},
|
||||||
|
"36": {},
|
||||||
|
"37": {},
|
||||||
|
"41": {},
|
||||||
|
"42": {},
|
||||||
|
"43": {},
|
||||||
|
"44": {},
|
||||||
|
"45": {},
|
||||||
|
"46": {},
|
||||||
|
"50": {},
|
||||||
|
"51": {},
|
||||||
|
"52": {},
|
||||||
|
"53": {},
|
||||||
|
"54": {},
|
||||||
|
"61": {},
|
||||||
|
"62": {},
|
||||||
|
"63": {},
|
||||||
|
"64": {},
|
||||||
|
"65": {},
|
||||||
|
//"71": {},
|
||||||
|
//"81": {},
|
||||||
|
//"82": {},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// IsAlpha checks if the string contains only letters (a-zA-Z).
|
// IsAlpha checks if the string contains only letters (a-zA-Z).
|
||||||
// Play: https://go.dev/play/p/7Q5sGOz2izQ
|
// Play: https://go.dev/play/p/7Q5sGOz2izQ
|
||||||
func IsAlpha(str string) bool {
|
func IsAlpha(str string) bool {
|
||||||
@@ -120,7 +168,7 @@ func ContainLetter(str string) bool {
|
|||||||
return letterRegexMatcher.MatchString(str)
|
return letterRegexMatcher.MatchString(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainLetter check if the string contain at least one number.
|
// ContainNumber check if the string contain at least one number.
|
||||||
func ContainNumber(input string) bool {
|
func ContainNumber(input string) bool {
|
||||||
return numberRegexMatcher.MatchString(input)
|
return numberRegexMatcher.MatchString(input)
|
||||||
}
|
}
|
||||||
@@ -228,7 +276,32 @@ func IsChineseMobile(mobileNum string) bool {
|
|||||||
// IsChineseIdNum check if the string is chinese id card.
|
// IsChineseIdNum check if the string is chinese id card.
|
||||||
// Play: https://go.dev/play/p/d8EWhl2UGDF
|
// Play: https://go.dev/play/p/d8EWhl2UGDF
|
||||||
func IsChineseIdNum(id string) bool {
|
func IsChineseIdNum(id string) bool {
|
||||||
return chineseIdMatcher.MatchString(id)
|
// All characters should be numbers, and the last digit can be either x or X
|
||||||
|
if !chineseIdMatcher.MatchString(id) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify province codes and complete all province codes according to GB/T2260
|
||||||
|
_, ok := provinceKv[id[0:2]]
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify birthday, must be greater than birthStartYear and less than the current year
|
||||||
|
birthStr := fmt.Sprintf("%s-%s-%s", id[6:10], id[10:12], id[12:14])
|
||||||
|
birthday, err := time.Parse("2006-01-02", birthStr)
|
||||||
|
if err != nil || birthday.After(time.Now()) || birthday.Year() < birthStartYear {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verification code
|
||||||
|
sum := 0
|
||||||
|
for i, c := range id[:17] {
|
||||||
|
v, _ := strconv.Atoi(string(c))
|
||||||
|
sum += v * factor[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
return verifyStr[sum%11] == strings.ToUpper(id[17:18])
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainChinese check if the string contain mandarin chinese.
|
// ContainChinese check if the string contain mandarin chinese.
|
||||||
@@ -384,7 +457,7 @@ func IsGBK(data []byte) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsNumberStr check if the value is number(integer, float) or not.
|
// IsNumber check if the value is number(integer, float) or not.
|
||||||
// Play: https://go.dev/play/p/mdJHOAvtsvF
|
// Play: https://go.dev/play/p/mdJHOAvtsvF
|
||||||
func IsNumber(v any) bool {
|
func IsNumber(v any) bool {
|
||||||
return IsInt(v) || IsFloat(v)
|
return IsInt(v) || IsFloat(v)
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ func ExampleIsChineseMobile() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ExampleIsChineseIdNum() {
|
func ExampleIsChineseIdNum() {
|
||||||
result1 := IsChineseIdNum("210911192105130715")
|
result1 := IsChineseIdNum("210911192105130714")
|
||||||
result2 := IsChineseIdNum("123456")
|
result2 := IsChineseIdNum("123456")
|
||||||
|
|
||||||
fmt.Println(result1)
|
fmt.Println(result1)
|
||||||
@@ -200,7 +200,7 @@ func ExampleIsDns() {
|
|||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// true
|
// true
|
||||||
// false
|
// true
|
||||||
// false
|
// false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -271,7 +271,11 @@ func TestIsDns(t *testing.T) {
|
|||||||
assert := internal.NewAssert(t, "TestIsDns")
|
assert := internal.NewAssert(t, "TestIsDns")
|
||||||
|
|
||||||
assert.Equal(true, IsDns("abc.com"))
|
assert.Equal(true, IsDns("abc.com"))
|
||||||
assert.Equal(false, IsDns("a.b.com"))
|
assert.Equal(true, IsDns("123.cn"))
|
||||||
|
assert.Equal(true, IsDns("a.b.com"))
|
||||||
|
|
||||||
|
assert.Equal(false, IsDns("a.b.c"))
|
||||||
|
assert.Equal(false, IsDns("a@b.com"))
|
||||||
assert.Equal(false, IsDns("http://abc.com"))
|
assert.Equal(false, IsDns("http://abc.com"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,10 +324,13 @@ func TestIsChineseIdNum(t *testing.T) {
|
|||||||
|
|
||||||
assert := internal.NewAssert(t, "TestIsChineseIdNum")
|
assert := internal.NewAssert(t, "TestIsChineseIdNum")
|
||||||
|
|
||||||
assert.Equal(true, IsChineseIdNum("210911192105130715"))
|
assert.Equal(true, IsChineseIdNum("210911192105130714"))
|
||||||
assert.Equal(true, IsChineseIdNum("21091119210513071X"))
|
assert.Equal(true, IsChineseIdNum("11010519491231002X"))
|
||||||
assert.Equal(true, IsChineseIdNum("21091119210513071x"))
|
assert.Equal(true, IsChineseIdNum("11010519491231002x"))
|
||||||
assert.Equal(false, IsChineseIdNum("123456"))
|
assert.Equal(false, IsChineseIdNum("123456"))
|
||||||
|
assert.Equal(false, IsChineseIdNum("990911192105130714"))
|
||||||
|
assert.Equal(false, IsChineseIdNum("990911189905130714"))
|
||||||
|
assert.Equal(false, IsChineseIdNum("210911222205130714"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIsCreditCard(t *testing.T) {
|
func TestIsCreditCard(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user