1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-08 06:32:28 +08:00

Compare commits

...

7 Commits

Author SHA1 Message Date
dudaodong
764a6fe107 release v1.2.0 2022-01-17 14:49:20 +08:00
dudaodong
f3749c52b9 feat: add system package 2022-01-17 11:54:03 +08:00
dudaodong
f368854b2d update text style of readme file 2022-01-17 10:40:41 +08:00
dudaodong
c424b88d40 update style of readme file 2022-01-16 22:17:51 +08:00
Dan Anstis
aeebd63eda docs(readme): fix convertor import example (#23) 2022-01-14 12:33:53 +08:00
dudaodong
22b3c4dd42 feat: add validator functions, IsAllUpper, IsAllLower, ContainUpper, ContainLower, ContainLetter, IsJSON and IsPort 2022-01-13 20:19:41 +08:00
dudaodong
bd976642f6 feat: add try package for executing a function repeatedly 2022-01-13 16:18:49 +08:00
8 changed files with 659 additions and 77 deletions

133
README.md
View File

@@ -1,45 +1,42 @@
<div align="center"> # Lancet
<h1 style="width: 100%; text-align: center;">Lancet</h1> <p style="font-size: 18px">
<p style="font-size: 18px"> Lancet is a comprehensive, efficient, and reusable util function library of go. Inspired by the java apache common package and lodash.js.
Lancet is a comprehensive, efficient, and reusable util function library of go. Inspired by the java apache common package and lodash.js. </p>
</p>
<div align="center" style="text-align: center;">
![Go version](https://img.shields.io/badge/go-%3E%3D1.16<recommend>-9cf) ![Go version](https://img.shields.io/badge/go-%3E%3D1.16<recommend>-9cf)
[![Release](https://img.shields.io/badge/release-1.1.10-green.svg)](https://github.com/duke-git/lancet/releases) [![Release](https://img.shields.io/badge/release-1.2.0-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com//duke-git/lancet?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet) [![GoDoc](https://godoc.org/github.com//duke-git/lancet?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet)](https://goreportcard.com/report/github.com/duke-git/lancet) [![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet)](https://goreportcard.com/report/github.com/duke-git/lancet)
[![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml) [![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
[![codecov](https://codecov.io/gh/duke-git/lancet/branch/main/graph/badge.svg?token=FC48T1F078)](https://codecov.io/gh/duke-git/lancet) [![codecov](https://codecov.io/gh/duke-git/lancet/branch/main/graph/badge.svg?token=FC48T1F078)](https://codecov.io/gh/duke-git/lancet)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/duke-git/lancet/blob/main/LICENSE) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/duke-git/lancet/blob/main/LICENSE)
</div>
English | [简体中文](./README_zh-CN.md) English | [简体中文](./README_zh-CN.md)
</div>
### Feature ## Feature
- 👏 Comprehensive, efficient and reusable. - 👏 Comprehensive, efficient and reusable.
- 💪 140+ common go util functions, support string, slice, datetime, net, crypt... - 💪 160+ common 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.
### Installation ## Installation
```go ```go
go get github.com/duke-git/lancet go get github.com/duke-git/lancet
``` ```
### Usage ## Usage
Lancet organizes the code into package structure, and you need to import the corresponding package name when use it. For example, if you use string-related functions,import the strutil package like below: Lancet organizes the code into package structure, and you need to import the corresponding package name when use it. For example, if you use string-related functions,import the strutil package like below:
```go ```go
import "github.com/duke-git/lancet/strutil" import "github.com/duke-git/lancet/strutil"
``` ```
### Example ## Example
Here takes the string function ReverseStr (reverse order string) as an example, and the strutil package needs to be imported. Here takes the string function ReverseStr (reverse order string) as an example, and the strutil package needs to be imported.
@@ -58,12 +55,11 @@ func main() {
} }
``` ```
### API Documentation ## API Documentation
### 1. convertor contains some functions for data convertion
#### 1. convertor contains some functions for data convertion
- Support conversion between commonly used data types. - Support conversion between commonly used data types.
- Usage: import "github.com/duke-git/lancet/cryptor" - Usage: import "github.com/duke-git/lancet/convertor"
```go ```go
package main package main
@@ -98,7 +94,7 @@ func ToString(value interface{}) string //convert value to string
func StructToMap(value interface{}) (map[string]interface{}, error) //convert struct to map, only convert exported field, tag `json` should be set func StructToMap(value interface{}) (map[string]interface{}, error) //convert struct to map, only convert exported field, tag `json` should be set
``` ```
#### 2. cryptor is for data encryption and decryption ### 2. cryptor is for data encryption and decryption
- Support md5, hmac, aes, des, ras. - Support md5, hmac, aes, des, ras.
- Usage: import "github.com/duke-git/lancet/cryptor" - Usage: import "github.com/duke-git/lancet/cryptor"
@@ -157,7 +153,7 @@ func RsaDecrypt(data []byte, privateKeyFileName string) []byte //RSA decrypt
``` ```
#### 3. datetime parse and format datetime ### 3. datetime parse and format datetime
- Parse and format datetime - Parse and format datetime
- Usage: import "github.com/duke-git/lancet/datetime" - Usage: import "github.com/duke-git/lancet/datetime"
@@ -192,7 +188,7 @@ func FormatTimeToStr(t time.Time, format string) string //convert time to string
func FormatStrToTime(str, format string) time.Time //convert string to time func FormatStrToTime(str, format string) time.Time //convert string to time
``` ```
#### 4. fileutil basic functions for file operations ### 4. fileutil basic functions for file operations
- Basic functions for file operations. - Basic functions for file operations.
- Usage: import "github.com/duke-git/lancet/fileutil" - Usage: import "github.com/duke-git/lancet/fileutil"
@@ -229,7 +225,7 @@ func Zip(fpath string, destPath string) error //create zip file, fpath could be
func UnZip(zipFile string, destPath string) error //unzip the file and save it to destPath func UnZip(zipFile string, destPath string) error //unzip the file and save it to destPath
``` ```
#### 5. formatter is for data format ### 5. formatter is for data format
- Contain some formatting function - Contain some formatting function
- Usage: import "github.com/duke-git/lancet/formatter" - Usage: import "github.com/duke-git/lancet/formatter"
@@ -254,7 +250,7 @@ func main() {
func Comma(v interface{}, symbol string) string //add comma to number by every 3 numbers from right. ahead by symbol char func Comma(v interface{}, symbol string) string //add comma to number by every 3 numbers from right. ahead by symbol char
``` ```
#### 6. function can control the function execution and support functional programming ### 6. function can control the function execution and support functional programming
- Control function execution and support functional programming. - Control function execution and support functional programming.
- Usage: import "github.com/duke-git/lancet/function" - Usage: import "github.com/duke-git/lancet/function"
@@ -290,7 +286,7 @@ func (w *Watcher) Reset() {} //reset the watch timer.
func (w *Watcher) GetElapsedTime() time.Duration //return time duration from watcher start to end. func (w *Watcher) GetElapsedTime() time.Duration //return time duration from watcher start to end.
``` ```
#### 7. netutil is for net process ### 7. netutil is for net process
- Ip and http request method. - Ip and http request method.
- Usage: import "github.com/duke-git/lancet/netutil". - Usage: import "github.com/duke-git/lancet/netutil".
@@ -338,7 +334,7 @@ func ConvertMapToQueryString(param map[string]interface{}) string //convert map
func ParseHttpResponse(resp *http.Response, obj interface{}) error //decode http response to specified interface func ParseHttpResponse(resp *http.Response, obj interface{}) error //decode http response to specified interface
``` ```
#### 8. random is for rand string and int generation ### 8. random is for rand string and int generation
- Generate random string and int. - Generate random string and int.
- Usage: import "github.com/duke-git/lancet/random". - Usage: import "github.com/duke-git/lancet/random".
@@ -367,7 +363,49 @@ func RandInt(min, max int) int //generate random int
func RandString(length int) string //generate random string func RandString(length int) string //generate random string
``` ```
#### 9. slice is for process slice ### 9. retry is for executing a function repeatedly until it was successful or canceled by the context.
- Executes a function repeatedly until it was successful or canceled by the context.
- Default retry times is 5, default retry duration is 3 second.
- Usage: import "github.com/duke-git/lancet/retry".
```go
package main
import (
"fmt"
"io/ioutil"
"log"
"github.com/duke-git/lancet/retry"
)
func main() {
var number int
increaseNumber := func() error {
number++
if number == 3 {
return nil
}
return errors.New("error occurs")
}
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50))
fmt.Println(number) //3
}
```
- Function list:
```go
type RetryFunc func() error //function that retry executes
func RetryTimes(n uint) //set times of retry
func RetryDuration(d time.Duration) //generate random string
func Context(ctx context.Context) //set retry context config
func Retry(retryFunc RetryFunc, opts ...Option) error //executes the retryFunc repeatedly until it was successful or canceled by the context
```
### 10. slice is for process slice
- Contain function for process slice. - Contain function for process slice.
- Usage: import "github.com/duke-git/lancet/slice" - Usage: import "github.com/duke-git/lancet/slice"
@@ -425,7 +463,7 @@ func GroupBy(slice, function interface{}) (interface{}, interface{}) // groups s
func Count(slice, function interface{}) int // Count iterates over elements of slice, returns a count of all matched elements func Count(slice, function interface{}) int // Count iterates over elements of slice, returns a count of all matched elements
``` ```
#### 10. strutil is for processing string ### 11. strutil is for processing string
- Contain functions to precess string - Contain functions to precess string
- Usage: import "github.com/duke-git/lancet/strutil" - Usage: import "github.com/duke-git/lancet/strutil"
@@ -466,8 +504,41 @@ func SnakeCase(s string) string //covert string to snake_case "fooBar" -> "foo_b
func Wrap(str string, wrapWith string) string //wrap a string with another string. func Wrap(str string, wrapWith string) string //wrap a string with another string.
func Unwrap(str string, wrapToken string) string //unwrap a given string from anther string. will change str value func Unwrap(str string, wrapToken string) string //unwrap a given string from anther string. will change str value
``` ```
### 12. system contain some functions about os, runtime, shell command.
#### 11. validator is for data validation - Generate random string and int.
- Usage: import "github.com/duke-git/lancet/system".
```go
package main
import (
"fmt"
"io/ioutil"
"log"
"github.com/duke-git/lancet/system"
)
func main() {
envFoo := system.GetOsEnv("foo")
fmt.Println(envFoo)
}
```
- Function list:
```go
func IsWindows() bool //check if current os is windows
func IsLinux() bool //check if current os is linux
func IsMac() bool //check if current os is macos
func GetOsEnv(key string) string //gets the value of the environment variable named by the key.
func SetOsEnv(key, value string) error //sets the value of the environment variable named by the key.
func RemoveOsEnv(key string) error //remove a single environment variable.
func CompareOsEnv(key, comparedEnv string) bool //gets env named by the key and compare it with comparedEnv
func ExecCommand(command string) (err error, stdout, stderr string) //use shell /bin/bash -c to execute command
```
### 13. validator is for data validation
- Contain function for data validation. - Contain function for data validation.
- Usage: import "github.com/duke-git/lancet/validator". - Usage: import "github.com/duke-git/lancet/validator".
@@ -495,6 +566,12 @@ func main() {
func ContainChinese(s string) bool //check if the string contain mandarin chinese func ContainChinese(s string) bool //check if the string contain mandarin chinese
func IsAlpha(s string) bool //checks if the string contains only letters (a-zA-Z) func IsAlpha(s string) bool //checks if the string contains only letters (a-zA-Z)
func IsBase64(base64 string) bool //check if the string is base64 string func IsBase64(base64 string) bool //check if the string is base64 string
func IsAllUpper(str string) bool //check if the string is all upper case letters A-Z
func IsAllLower(str string) bool //check if the string is all lower case letters a-z
func ContainUpper(str string) bool //check if the string contain at least one upper case letter A-Z
func ContainLower(str string) bool //check if the string contain at least one lower case letter a-z
func ContainLetter(str string) bool //check if the string contain at least one letter
func IsJSON(str string) bool //checks if the string is valid JSON
func IsChineseMobile(mobileNum string) bool //check if the string is chinese mobile number func IsChineseMobile(mobileNum string) bool //check if the string is chinese mobile number
func IsChineseIdNum(id string) bool //check if the string is chinese id number func IsChineseIdNum(id string) bool //check if the string is chinese id number
func IsChinesePhone(phone string) bool //check if the string is chinese phone number func IsChinesePhone(phone string) bool //check if the string is chinese phone number

View File

@@ -1,38 +1,34 @@
<div align="center"> # Lancet
<h1 style="width: 100%; text-align: center;">Lancet</h1> <p style="font-size: 18px">
<p style="font-size: 18px"> lancet柳叶刀是一个全面、高效、可复用的go语言工具函数库。 lancet受到了java apache common包和lodash.js的启发。
lancet柳叶刀是一个全面、高效、可复用的go语言工具函数库。 lancet受到了java apache common包和lodash.js的启发。 </p>
</p>
<div align="center" style="text-align: center;">
![Go version](https://img.shields.io/badge/go-%3E%3D1.16<recommend>-9cf) ![Go version](https://img.shields.io/badge/go-%3E%3D1.16<recommend>-9cf)
[![Release](https://img.shields.io/badge/release-1.1.10-green.svg)](https://github.com/duke-git/lancet/releases) [![Release](https://img.shields.io/badge/release-1.2.0-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com//duke-git/lancet?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet) [![GoDoc](https://godoc.org/github.com//duke-git/lancet?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet)](https://goreportcard.com/report/github.com/duke-git/lancet) [![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet)](https://goreportcard.com/report/github.com/duke-git/lancet)
[![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml) [![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
[![codecov](https://codecov.io/gh/duke-git/lancet/branch/main/graph/badge.svg?token=FC48T1F078)](https://codecov.io/gh/duke-git/lancet) [![codecov](https://codecov.io/gh/duke-git/lancet/branch/main/graph/badge.svg?token=FC48T1F078)](https://codecov.io/gh/duke-git/lancet)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/duke-git/lancet/blob/main/LICENSE) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/duke-git/lancet/blob/main/LICENSE)
</div>
简体中文 | [English](./README.md) 简体中文 | [English](./README.md)
</div>
### 特性 ## 特性
- 👏 全面、高效、可复用 - 👏 全面、高效、可复用
- 💪 140+常用go工具函数支持string、slice、datetime、net、crypt... - 💪 160+常用go工具函数支持string、slice、datetime、net、crypt...
- 💅 只依赖go标准库 - 💅 只依赖go标准库
- 🌍 所有导出函数单元测试覆盖率100% - 🌍 所有导出函数单元测试覆盖率100%
### 安装 ## 安装
```go ```go
go get github.com/duke-git/lancet go get github.com/duke-git/lancet
``` ```
### 用法 ## 用法
lancet是以包的结构组织代码的使用时需要导入相应的包名。例如如果使用字符串相关函数需要导入strutil包: lancet是以包的结构组织代码的使用时需要导入相应的包名。例如如果使用字符串相关函数需要导入strutil包:
@@ -40,7 +36,7 @@ lancet是以包的结构组织代码的使用时需要导入相应的包名
import "github.com/duke-git/lancet/strutil" import "github.com/duke-git/lancet/strutil"
``` ```
### 例子 ## 例子
此处以字符串工具函数ReverseStr逆序字符串为例需要导入strutil包: 此处以字符串工具函数ReverseStr逆序字符串为例需要导入strutil包:
@@ -59,9 +55,8 @@ func main() {
} }
``` ```
### API文档 ## API文档
### 1. convertor数据转换包
#### 1. convertor数据转换包
- 转换函数支持常用数据类型之间的转换 - 转换函数支持常用数据类型之间的转换
- 导入包import "github.com/duke-git/lancet/convertor" - 导入包import "github.com/duke-git/lancet/convertor"
@@ -99,7 +94,7 @@ func ToString(value interface{}) string //interface转成string
func StructToMap(value interface{}) (map[string]interface{}, error) //struct串转成map, 需要设置struct tag `json` func StructToMap(value interface{}) (map[string]interface{}, error) //struct串转成map, 需要设置struct tag `json`
``` ```
#### 2. cryptor加解密包 ### 2. cryptor加解密包
- 加密函数支持md5, hmac, aes, des, ras - 加密函数支持md5, hmac, aes, des, ras
- 导入包import "github.com/duke-git/lancet/cryptor" - 导入包import "github.com/duke-git/lancet/cryptor"
@@ -158,7 +153,7 @@ func RsaDecrypt(data []byte, privateKeyFileName string) []byte //RSA解密
``` ```
#### 3. datetime日期时间处理包 ### 3. datetime日期时间处理包
- 处理日期时间 - 处理日期时间
- 导入包import "github.com/duke-git/lancet/datetime" - 导入包import "github.com/duke-git/lancet/datetime"
@@ -193,7 +188,7 @@ func FormatTimeToStr(t time.Time, format string) string //时间格式化字符
func FormatStrToTime(str, format string) time.Time //字符串转换成时间 func FormatStrToTime(str, format string) time.Time //字符串转换成时间
``` ```
#### 4. fileutil文件处理包 ### 4. fileutil文件处理包
- 文件处理常用函数 - 文件处理常用函数
- 导入包import "github.com/duke-git/lancet/fileutil" - 导入包import "github.com/duke-git/lancet/fileutil"
@@ -230,7 +225,7 @@ func Zip(fpath string, destPath string) error //压缩文件fpath参数可以是
func UnZip(zipFile string, destPath string) error //解压文件并将文件存储在destPath目录中 func UnZip(zipFile string, destPath string) error //解压文件并将文件存储在destPath目录中
``` ```
#### 5. formatter格式化处理包 ### 5. formatter格式化处理包
- 格式化相关处理函数 - 格式化相关处理函数
- 导入包import "github.com/duke-git/lancet/formatter" - 导入包import "github.com/duke-git/lancet/formatter"
@@ -255,7 +250,7 @@ func main() {
func Comma(v interface{}, symbol string) string //用逗号每隔3位分割数字/字符串 func Comma(v interface{}, symbol string) string //用逗号每隔3位分割数字/字符串
``` ```
#### 6. function包可以控制函数执行支持部分函数式编程 ### 6. function包可以控制函数执行支持部分函数式编程
- 控制函数执行,支持部分函数式编程 - 控制函数执行,支持部分函数式编程
- 导入包import "github.com/duke-git/lancet/function" - 导入包import "github.com/duke-git/lancet/function"
@@ -291,7 +286,7 @@ func (w *Watcher) Reset() {} //重置代码watcher
func (w *Watcher) GetElapsedTime() time.Duration //get code excution elapsed time. func (w *Watcher) GetElapsedTime() time.Duration //get code excution elapsed time.
``` ```
#### 7. netutil网络处理包 ### 7. netutil网络处理包
- 处理ip, http请求相关函数 - 处理ip, http请求相关函数
- 导入包import "github.com/duke-git/lancet/netutil" - 导入包import "github.com/duke-git/lancet/netutil"
@@ -339,7 +334,7 @@ func ConvertMapToQueryString(param map[string]interface{}) string //将map转换
func ParseHttpResponse(resp *http.Response, obj interface{}) error //将http响应解码成特定interface func ParseHttpResponse(resp *http.Response, obj interface{}) error //将http响应解码成特定interface
``` ```
#### 8. random随机数处理包 ### 8. random随机数处理包
- 生成和处理随机数 - 生成和处理随机数
- 导入包import "github.com/duke-git/lancet/random" - 导入包import "github.com/duke-git/lancet/random"
@@ -368,7 +363,49 @@ func RandInt(min, max int) int //生成随机int
func RandString(length int) string //生成随机string func RandString(length int) string //生成随机string
``` ```
#### 9. slice切片操作包 ### 9. retry重试执行函数
- 重试执行函数直到函数成功或被context停止
- 默认重试次数5, 默认执行间隔3秒.
- Usage: import "github.com/duke-git/lancet/retry".
```go
package main
import (
"fmt"
"io/ioutil"
"log"
"github.com/duke-git/lancet/retry"
)
func main() {
var number int
increaseNumber := func() error {
number++
if number == 3 {
return nil
}
return errors.New("error occurs")
}
err := retry.Retry(increaseNumber, retry.RetryDuration(time.Microsecond*50))
fmt.Println(number) //3
}
```
- Function list:
```go
type RetryFunc func() error //要重试执行的函数
func RetryTimes(n uint) //设置重试次数默认5次
func RetryDuration(d time.Duration) //设置重试间隔时间默认3秒
func Context(ctx context.Context) //context config
func Retry(retryFunc RetryFunc, opts ...Option) error //重试函数
```
### 10. slice切片操作包
- 切片操作相关函数 - 切片操作相关函数
- 导入包import "github.com/duke-git/lancet/slice" - 导入包import "github.com/duke-git/lancet/slice"
@@ -426,7 +463,7 @@ func GroupBy(slice, function interface{}) (interface{}, interface{}) //根据函
func Count(slice, function interface{}) int func Count(slice, function interface{}) int
``` ```
#### 10. strutil字符串处理包 ### 11. strutil字符串处理包
- 字符串操作相关函数 - 字符串操作相关函数
- 导入包import "github.com/duke-git/lancet/strutil" - 导入包import "github.com/duke-git/lancet/strutil"
@@ -468,7 +505,41 @@ func Unwrap(str string, wrapToken string) string //解包裹字符串 Wrap("*abc
func SnakeCase(s string) string //字符串转为SnakeCase, "fooBar" -> "foo_bar" func SnakeCase(s string) string //字符串转为SnakeCase, "fooBar" -> "foo_bar"
``` ```
#### 11. validator验证器 ### 12. system系统
- 包含一些操作系统运行时shell命令执行的函数.
- Usage: import "github.com/duke-git/lancet/system".
```go
package main
import (
"fmt"
"io/ioutil"
"log"
"github.com/duke-git/lancet/system"
)
func main() {
envFoo := system.GetOsEnv("foo")
fmt.Println(envFoo)
}
```
- Function list:
```go
func IsWindows() bool //判断操作系统是windows
func IsLinux() bool //判断操作系统是linux
func IsMac() bool //判断操作系统是macos
func GetOsEnv(key string) string //获取名称为key的环境变量
func SetOsEnv(key, value string) error //设置环境变量
func RemoveOsEnv(key string) error //删除指定key的环境变量
func CompareOsEnv(key, comparedEnv string) bool //获取名称为key的环境变量并和comparedEnv比较
func ExecCommand(command string) (err error, stdout, stderr string) //执行shell命令/bin/bash)
```
### 13. validator验证器包
- 数据校验相关函数 - 数据校验相关函数
- 导入包import "github.com/duke-git/lancet/validator" - 导入包import "github.com/duke-git/lancet/validator"
@@ -496,6 +567,12 @@ func main() {
func ContainChinese(s string) bool //判断字符串中是否含有中文字符 func ContainChinese(s string) bool //判断字符串中是否含有中文字符
func IsAlpha(s string) bool //判断字符串是否只含有字母 func IsAlpha(s string) bool //判断字符串是否只含有字母
func IsBase64(base64 string) bool //判断字符串是base64 func IsBase64(base64 string) bool //判断字符串是base64
func IsAllUpper(str string) bool //断字符串是否全是大写字母
func IsAllLower(str string) bool //断字符串是否全是小写字母
func ContainUpper(str string) bool //判断字符串是否包含大写字母
func ContainLower(str string) bool //判断字符串是否包含小写字母
func ContainLetter(str string) bool //判断字符串是否包含字母
func IsJSON(str string) bool //判断字符串是否是JSON
func IsChineseMobile(mobileNum string) bool //判断字符串是否是手机号 func IsChineseMobile(mobileNum string) bool //判断字符串是否是手机号
func IsChineseIdNum(id string) bool //判断字符串是否是身份证号 func IsChineseIdNum(id string) bool //判断字符串是否是身份证号
func IsChinesePhone(phone string) bool //判断字符串是否是座机电话号码 func IsChinesePhone(phone string) bool //判断字符串是否是座机电话号码

89
retry/retry.go Normal file
View File

@@ -0,0 +1,89 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package retry is for executing a function repeatedly until it was successful or canceled by the context.
package retry
import (
"context"
"errors"
"fmt"
"reflect"
"runtime"
"strings"
"time"
)
const (
DefaultRetryTimes = 5
DefaultRetryDuration = time.Second * 3
)
// RetryConfig is config for retry
type RetryConfig struct {
context context.Context
retryTimes uint
retryDuration time.Duration
}
// RetryFn is function that retry executes
type RetryFunc func() error
// Option is for adding retry config
type Option func(*RetryConfig)
// RetryTimes set times of retry
func RetryTimes(n uint) Option {
return func(rc *RetryConfig) {
rc.retryTimes = n
}
}
// RetryDuration set duration of retries
func RetryDuration(d time.Duration) Option {
return func(rc *RetryConfig) {
rc.retryDuration = d
}
}
// Context set retry context config
func Context(ctx context.Context) Option {
return func(rc *RetryConfig) {
rc.context = ctx
}
}
// Retry executes the retryFunc repeatedly until it was successful or canceled by the context
// The default times of retries is 5 and the default duration between retries is 3 seconds
func Retry(retryFunc RetryFunc, opts ...Option) error {
config := &RetryConfig{
retryTimes: DefaultRetryTimes,
retryDuration: DefaultRetryDuration,
context: context.TODO(),
}
for _, opt := range opts {
opt(config)
}
var i uint
for i < config.retryTimes {
err := retryFunc()
if err != nil {
select {
case <-time.After(config.retryDuration):
case <-config.context.Done():
return errors.New("retry is cancelled")
}
} else {
return nil
}
i++
}
funcPath := runtime.FuncForPC(reflect.ValueOf(retryFunc).Pointer()).Name()
lastSlash := strings.LastIndex(funcPath, "/")
funcName := funcPath[lastSlash+1:]
return fmt.Errorf("function %s run failed after %d times retry", funcName, i)
}

80
retry/retry_test.go Normal file
View File

@@ -0,0 +1,80 @@
package retry
import (
"context"
"errors"
"testing"
"time"
"github.com/duke-git/lancet/internal"
)
func TestRetryFailed(t *testing.T) {
assert := internal.NewAssert(t, "TestRetryFailed")
var number int
increaseNumber := func() error {
number++
return errors.New("error occurs")
}
err := Retry(increaseNumber, RetryDuration(time.Microsecond*50))
assert.IsNotNil(err)
assert.Equal(DefaultRetryTimes, number)
}
func TestRetrySucceeded(t *testing.T) {
assert := internal.NewAssert(t, "TestRetrySucceeded")
var number int
increaseNumber := func() error {
number++
if number == DefaultRetryTimes {
return nil
}
return errors.New("error occurs")
}
err := Retry(increaseNumber, RetryDuration(time.Microsecond*50))
assert.IsNil(err)
assert.Equal(DefaultRetryTimes, number)
}
func TestSetRetryTimes(t *testing.T) {
assert := internal.NewAssert(t, "TestSetRetryTimes")
var number int
increaseNumber := func() error {
number++
return errors.New("error occurs")
}
err := Retry(increaseNumber, RetryDuration(time.Microsecond*50), RetryTimes(3))
assert.IsNotNil(err)
assert.Equal(3, number)
}
func TestCancelRetry(t *testing.T) {
assert := internal.NewAssert(t, "TestCancelRetry")
ctx, cancel := context.WithCancel(context.TODO())
var number int
increaseNumber := func() error {
number++
if number > 3 {
cancel()
}
return errors.New("error occurs")
}
err := Retry(increaseNumber,
RetryDuration(time.Microsecond*50),
Context(ctx),
)
assert.IsNotNil(err)
assert.Equal(4, number)
}

69
system/os.go Normal file
View File

@@ -0,0 +1,69 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package system contain some functions about os, runtime, shell command.
package system
import (
"bytes"
"os"
"os/exec"
"runtime"
)
// IsWindows check if current os is windows
func IsWindows() bool {
return runtime.GOOS == "windows"
}
// IsLinux check if current os is linux
func IsLinux() bool {
return runtime.GOOS == "linux"
}
// IsMac check if current os is macos
func IsMac() bool {
return runtime.GOOS == "darwin"
}
// GetOsEnv gets the value of the environment variable named by the key.
func GetOsEnv(key string) string {
return os.Getenv(key)
}
// SetOsEnv sets the value of the environment variable named by the key.
func SetOsEnv(key, value string) error {
return os.Setenv(key, value)
}
// RemoveOsEnv remove a single environment variable.
func RemoveOsEnv(key string) error {
return os.Unsetenv(key)
}
// CompareOsEnv gets env named by the key and compare it with comparedEnv
func CompareOsEnv(key, comparedEnv string) bool {
env := GetOsEnv(key)
if env == "" {
return false
}
return env == comparedEnv
}
// ExecCommand use shell /bin/bash -c to execute command
func ExecCommand(command string) (err error, stdout, stderr string) {
var out bytes.Buffer
var errout bytes.Buffer
cmd := exec.Command("/bin/bash", "-c", command)
cmd.Stdout = &out
cmd.Stderr = &errout
err = cmd.Run()
if err != nil {
stderr = string(errout.Bytes())
}
stdout = string(out.Bytes())
return
}

37
system/os_test.go Normal file
View File

@@ -0,0 +1,37 @@
package system
import (
"testing"
"github.com/duke-git/lancet/internal"
)
func TestOsEnvOperation(t *testing.T) {
assert := internal.NewAssert(t, "TestOsEnvOperation")
envNotExist := GetOsEnv("foo")
assert.Equal("", envNotExist)
SetOsEnv("foo", "foo_value")
envExist := GetOsEnv("foo")
assert.Equal("foo_value", envExist)
assert.Equal(true, CompareOsEnv("foo", "foo_value"))
assert.Equal(false, CompareOsEnv("foo", "abc"))
}
func TestExecCommand(t *testing.T) {
assert := internal.NewAssert(t, "TestExecCommand")
err, out, errout := ExecCommand("ls")
assert.IsNil(err)
err, out, errout = ExecCommand("abc")
t.Log("std out: ", out)
t.Log("std err: ", errout)
if err != nil {
t.Logf("error: %v\n", err)
}
assert.IsNotNil(err)
}

View File

@@ -5,17 +5,72 @@
package validator package validator
import ( import (
"encoding/json"
"net" "net"
"regexp" "regexp"
"strconv" "strconv"
"strings"
"unicode" "unicode"
) )
var isAlphaRegexMatcher *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z]+$`) var isAlphaRegexMatcher *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z]+$`)
// IsAlpha checks if the string contains only letters (a-zA-Z) // IsAlpha checks if the string contains only letters (a-zA-Z)
func IsAlpha(s string) bool { func IsAlpha(str string) bool {
return isAlphaRegexMatcher.MatchString(s) return isAlphaRegexMatcher.MatchString(str)
}
// IsAllUpper check if the string is all upper case letters A-Z
func IsAllUpper(str string) bool {
for _, r := range str {
if !unicode.IsUpper(r) {
return false
}
}
return str != ""
}
// IsAllLower check if the string is all lower case letters a-z
func IsAllLower(str string) bool {
for _, r := range str {
if !unicode.IsLower(r) {
return false
}
}
return str != ""
}
// ContainUpper check if the string contain at least one upper case letter A-Z
func ContainUpper(str string) bool {
for _, r := range str {
if unicode.IsUpper(r) && unicode.IsLetter(r) {
return true
}
}
return false
}
// ContainLower check if the string contain at least one lower case letter A-Z
func ContainLower(str string) bool {
for _, r := range str {
if unicode.IsLower(r) && unicode.IsLetter(r) {
return true
}
}
return false
}
var containLetterRegexMatcher *regexp.Regexp = regexp.MustCompile(`[a-zA-Z]`)
// ContainLetter check if the string contain at least one letter
func ContainLetter(str string) bool {
return containLetterRegexMatcher.MatchString(str)
}
// Is checks if the string is valid JSON
func IsJSON(str string) bool {
var js json.RawMessage
return json.Unmarshal([]byte(str), &js) == nil
} }
// IsNumberStr check if the string can convert to a number. // IsNumberStr check if the string can convert to a number.
@@ -24,16 +79,16 @@ func IsNumberStr(s string) bool {
} }
// IsFloatStr check if the string can convert to a float. // IsFloatStr check if the string can convert to a float.
func IsFloatStr(s string) bool { func IsFloatStr(str string) bool {
_, e := strconv.ParseFloat(s, 64) _, e := strconv.ParseFloat(str, 64)
return e == nil return e == nil
} }
var isIntStrRegexMatcher *regexp.Regexp = regexp.MustCompile(`^[\+-]?\d+$`) var isIntStrRegexMatcher *regexp.Regexp = regexp.MustCompile(`^[\+-]?\d+$`)
// IsIntStr check if the string can convert to a integer. // IsIntStr check if the string can convert to a integer.
func IsIntStr(s string) bool { func IsIntStr(str string) bool {
return isIntStrRegexMatcher.MatchString(s) return isIntStrRegexMatcher.MatchString(str)
} }
// IsIp check if the string is a ip address. // IsIp check if the string is a ip address.
@@ -48,13 +103,7 @@ func IsIpV4(ipstr string) bool {
if ip == nil { if ip == nil {
return false return false
} }
for i := 0; i < len(ipstr); i++ { return strings.Contains(ipstr, ".")
switch ipstr[i] {
case '.':
return true
}
}
return false
} }
// IsIpV6 check if the string is a ipv6 address. // IsIpV6 check if the string is a ipv6 address.
@@ -63,11 +112,13 @@ func IsIpV6(ipstr string) bool {
if ip == nil { if ip == nil {
return false return false
} }
for i := 0; i < len(ipstr); i++ { return strings.Contains(ipstr, ":")
switch ipstr[i] { }
case ':':
return true // IsPort check if the string is a valid net port.
} func IsPort(str string) bool {
if i, err := strconv.ParseInt(str, 10, 64); err == nil && i > 0 && i < 65536 {
return true
} }
return false return false
} }
@@ -130,14 +181,14 @@ func IsBase64(base64 string) bool {
} }
// IsEmptyString check if the string is empty. // IsEmptyString check if the string is empty.
func IsEmptyString(s string) bool { func IsEmptyString(str string) bool {
return len(s) == 0 return len(str) == 0
} }
// IsRegexMatch check if the string match the regexp // IsRegexMatch check if the string match the regexp
func IsRegexMatch(s, regex string) bool { func IsRegexMatch(str, regex string) bool {
reg := regexp.MustCompile(regex) reg := regexp.MustCompile(regex)
return reg.MatchString(s) return reg.MatchString(str)
} }
// IsStrongPassword check if the string is strong password, if len(password) is less than the length param, return false // IsStrongPassword check if the string is strong password, if len(password) is less than the length param, return false

View File

@@ -6,6 +6,96 @@ import (
"github.com/duke-git/lancet/internal" "github.com/duke-git/lancet/internal"
) )
func TestIsAllUpper(t *testing.T) {
assert := internal.NewAssert(t, "TestIsAllUpper")
assert.Equal(true, IsAllUpper("ABC"))
assert.Equal(false, IsAllUpper(""))
assert.Equal(false, IsAllUpper("abc"))
assert.Equal(false, IsAllUpper("aBC"))
assert.Equal(false, IsAllUpper("1BC"))
assert.Equal(false, IsAllUpper("1bc"))
assert.Equal(false, IsAllUpper("123"))
assert.Equal(false, IsAllUpper("你好"))
assert.Equal(false, IsAllUpper("A&"))
assert.Equal(false, IsAllUpper("&@#$%^&*"))
}
func TestIsAllLower(t *testing.T) {
assert := internal.NewAssert(t, "TestIsAllLower")
assert.Equal(true, IsAllLower("abc"))
assert.Equal(false, IsAllLower("ABC"))
assert.Equal(false, IsAllLower(""))
assert.Equal(false, IsAllLower("aBC"))
assert.Equal(false, IsAllLower("1BC"))
assert.Equal(false, IsAllLower("1bc"))
assert.Equal(false, IsAllLower("123"))
assert.Equal(false, IsAllLower("你好"))
assert.Equal(false, IsAllLower("A&"))
assert.Equal(false, IsAllLower("&@#$%^&*"))
}
func TestContainLower(t *testing.T) {
assert := internal.NewAssert(t, "TestContainLower")
assert.Equal(true, ContainLower("abc"))
assert.Equal(true, ContainLower("aBC"))
assert.Equal(true, ContainLower("1bc"))
assert.Equal(true, ContainLower("a&"))
assert.Equal(false, ContainLower("ABC"))
assert.Equal(false, ContainLower(""))
assert.Equal(false, ContainLower("1BC"))
assert.Equal(false, ContainLower("123"))
assert.Equal(false, ContainLower("你好"))
assert.Equal(false, ContainLower("&@#$%^&*"))
}
func TestContainUpper(t *testing.T) {
assert := internal.NewAssert(t, "TestContainUpper")
assert.Equal(true, ContainUpper("ABC"))
assert.Equal(true, ContainUpper("aBC"))
assert.Equal(true, ContainUpper("1BC"))
assert.Equal(true, ContainUpper("A&"))
assert.Equal(false, ContainUpper("abc"))
assert.Equal(false, ContainUpper(""))
assert.Equal(false, ContainUpper("1bc"))
assert.Equal(false, ContainUpper("123"))
assert.Equal(false, ContainUpper("你好"))
assert.Equal(false, ContainUpper("&@#$%^&*"))
}
func TestContainLetter(t *testing.T) {
assert := internal.NewAssert(t, "TestContainLetter")
assert.Equal(true, ContainLetter("ABC"))
assert.Equal(true, ContainLetter("1Bc"))
assert.Equal(true, ContainLetter("1ab"))
assert.Equal(true, ContainLetter("A&"))
assert.Equal(false, ContainLetter(""))
assert.Equal(false, ContainLetter("123"))
assert.Equal(false, ContainLetter("你好"))
assert.Equal(false, ContainLetter("&@#$%^&*"))
}
func TestIsJSON(t *testing.T) {
assert := internal.NewAssert(t, "TestIsJSON")
assert.Equal(true, IsJSON("{}"))
assert.Equal(true, IsJSON("{\"name\": \"test\"}"))
assert.Equal(true, IsJSON("[]"))
assert.Equal(true, IsJSON("123"))
assert.Equal(false, IsJSON(""))
assert.Equal(false, IsJSON("abc"))
assert.Equal(false, IsJSON("你好"))
assert.Equal(false, IsJSON("&@#$%^&*"))
}
func TestIsNumberStr(t *testing.T) { func TestIsNumberStr(t *testing.T) {
assert := internal.NewAssert(t, "TestIsNumberStr") assert := internal.NewAssert(t, "TestIsNumberStr")
@@ -35,6 +125,18 @@ func TestIsIntStr(t *testing.T) {
assert.Equal(false, IsIntStr("abc")) assert.Equal(false, IsIntStr("abc"))
} }
func TestIsPort(t *testing.T) {
assert := internal.NewAssert(t, "TestIsPort")
assert.Equal(true, IsPort("1"))
assert.Equal(true, IsPort("65535"))
assert.Equal(false, IsPort("abc"))
assert.Equal(false, IsPort("123abc"))
assert.Equal(false, IsPort(""))
assert.Equal(false, IsPort("-1"))
assert.Equal(false, IsPort("65536"))
}
func TestIsIp(t *testing.T) { func TestIsIp(t *testing.T) {
assert := internal.NewAssert(t, "TestIsIntStr") assert := internal.NewAssert(t, "TestIsIntStr")