mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-08 14:42:27 +08:00
Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a1386f5a7 | ||
|
|
b5541ea177 | ||
|
|
578b1bba65 | ||
|
|
3045d56503 | ||
|
|
f1dbd943aa | ||
|
|
e87f3b70f0 | ||
|
|
26b59dd56b | ||
|
|
143aba7112 | ||
|
|
60f3a72c88 | ||
|
|
d1b74cfcfb | ||
|
|
72a89be8c1 | ||
|
|
0cf59323ff | ||
|
|
afec27fb4e | ||
|
|
3021985df9 | ||
|
|
188d52cd9d | ||
|
|
8c8f991390 | ||
|
|
b7bb7c6ae0 | ||
|
|
2e04a41f34 | ||
|
|
acb7873832 | ||
|
|
8b3cc3266d | ||
|
|
62c570d29b | ||
|
|
4e5d3c2603 | ||
|
|
561b590e13 | ||
|
|
f2ed3c6270 | ||
|
|
fee6cb17f3 | ||
|
|
7d39d1319b | ||
|
|
59d7281967 | ||
|
|
bdf052819d | ||
|
|
0148af4839 | ||
|
|
99b74e6fc6 | ||
|
|
499c1df9bd | ||
|
|
6af13a01de |
22
.github/workflows/codecov.yml
vendored
Normal file
22
.github/workflows/codecov.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
name: Test and coverage
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 2
|
||||||
|
- uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: "1.16"
|
||||||
|
- name: Run coverage
|
||||||
|
run: go test -v ./... -coverprofile=coverage.txt -covermode=atomic
|
||||||
|
- name: Upload coverage to Codecov
|
||||||
|
run: bash <(curl -s https://codecov.io/bash)
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,3 +1,6 @@
|
|||||||
.idea/*
|
.idea/*
|
||||||
.vscode/*
|
.vscode/*
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
cryptor/*.txt
|
||||||
|
fileutil/*.txt
|
||||||
|
cryptor/*.pem
|
||||||
58
README.md
58
README.md
@@ -5,6 +5,13 @@
|
|||||||
</p>
|
</p>
|
||||||
<div align="center" style="text-align: center;">
|
<div align="center" style="text-align: center;">
|
||||||
|
|
||||||
|

|
||||||
|
[](https://github.com/duke-git/lancet/releases)
|
||||||
|
[](https://pkg.go.dev/github.com/duke-git/lancet)
|
||||||
|
[](https://goreportcard.com/report/github.com/duke-git/lancet)
|
||||||
|
[](https://codecov.io/gh/duke-git/lancet)
|
||||||
|
[](https://github.com/duke-git/lancet/blob/main/LICENSE)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
English | [简体中文](./README_zh-CN.md)
|
English | [简体中文](./README_zh-CN.md)
|
||||||
@@ -200,15 +207,18 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- 函数列表:
|
- Function list:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
func ClearFile(path string) error //write empty string to path file
|
||||||
func CreateFile(path string) bool // create a file in path
|
func CreateFile(path string) bool // create a file in path
|
||||||
func CopyFile(srcFilePath string, dstFilePath string) error //copy src file to dst file
|
func CopyFile(srcFilePath string, dstFilePath string) error //copy src file to dst file
|
||||||
func IsExist(path string) bool //checks if a file or directory exists
|
func IsExist(path string) bool //checks if a file or directory exists
|
||||||
func IsDir(path string) bool //checks if the path is directy or not
|
func IsDir(path string) bool //checks if the path is directy or not
|
||||||
func ListFileNames(path string) ([]string, error) //return all file names in the path
|
func ListFileNames(path string) ([]string, error) //return all file names in the path
|
||||||
func RemoveFile(path string) error //remove the path file
|
func RemoveFile(path string) error //remove the path file
|
||||||
|
func ReadFileToString(path string) (string, error) //return string of file content
|
||||||
|
func ReadFileByLine(path string)([]string, error) //read file content by line
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 5. formatter is for data format
|
#### 5. formatter is for data format
|
||||||
@@ -236,7 +246,39 @@ 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. netutil is for net process
|
#### 6. function can control the function execution and support functional programming
|
||||||
|
|
||||||
|
- Control function execution and support functional programming.
|
||||||
|
- Usage: import "github.com/duke-git/lancet/function"
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/function"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var print = func(s string) {
|
||||||
|
fmt.Println(s)
|
||||||
|
}
|
||||||
|
function.Delay(2*time.Second, print, "hello world")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Function list:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func After(n int, fn interface{}) func(args ...interface{}) []reflect.Value //creates a function that invokes func once it's called n or more times
|
||||||
|
func Before(n int, fn interface{}) func(args ...interface{}) []reflect.Value //creates a function that invokes func once it's called less than n times
|
||||||
|
func (f Fn) Curry(i interface{}) func(...interface{}) interface{} //make a curryed function
|
||||||
|
func Compose(fnList ...func(...interface{}) interface{}) func(...interface{}) interface{} //compose the functions from right to left
|
||||||
|
func Delay(delay time.Duration, fn interface{}, args ...interface{}) //invoke function after delayed time
|
||||||
|
func Schedule(d time.Duration, fn interface{}, args ...interface{}) chan bool //invoke function every duration time, util close the returned bool chan
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 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".
|
||||||
@@ -281,9 +323,10 @@ func HttpPut(url string, params ...interface{}) (*http.Response, error) //http p
|
|||||||
func HttpDelete(url string, params ...interface{}) (*http.Response, error) //http delete request
|
func HttpDelete(url string, params ...interface{}) (*http.Response, error) //http delete request
|
||||||
func HttpPatch(url string, params ...interface{}) (*http.Response, error) //http patch request
|
func HttpPatch(url string, params ...interface{}) (*http.Response, error) //http patch request
|
||||||
func ConvertMapToQueryString(param map[string]interface{}) string //convert map to url query string
|
func ConvertMapToQueryString(param map[string]interface{}) string //convert map to url query string
|
||||||
|
func ParseHttpResponse(resp *http.Response, obj interface{}) error //decode http response to specified interface
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 7. 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".
|
||||||
@@ -312,7 +355,7 @@ 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
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 8. slice is for process slice
|
#### 9. 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"
|
||||||
@@ -343,7 +386,9 @@ func Chunk(slice []interface{}, size int) [][]interface{} //creates an slice of
|
|||||||
func ConvertSlice(originalSlice interface{}, newSliceType reflect.Type) interface{} //convert originalSlice to newSliceType
|
func ConvertSlice(originalSlice interface{}, newSliceType reflect.Type) interface{} //convert originalSlice to newSliceType
|
||||||
func Difference(slice1, slice2 interface{}) interface{} //creates an slice of whose element not included in the other given slice
|
func Difference(slice1, slice2 interface{}) interface{} //creates an slice of whose element not included in the other given slice
|
||||||
func DeleteByIndex(slice interface{}, start int, end ...int) (interface{}, error) //delete the element of slice from start index to end index - 1
|
func DeleteByIndex(slice interface{}, start int, end ...int) (interface{}, error) //delete the element of slice from start index to end index - 1
|
||||||
|
func Every(slice, function interface{}) bool //return true if all of the values in the slice pass the predicate function, function signature should be func(index int, value interface{}) bool
|
||||||
func Filter(slice, function interface{}) interface{} //filter slice, function signature should be func(index int, value interface{}) bool
|
func Filter(slice, function interface{}) interface{} //filter slice, function signature should be func(index int, value interface{}) bool
|
||||||
|
func Find(slice, function interface{}) interface{} //iterates over elements of slice, returning the first one that passes a truth test on function.function signature should be func(index int, value interface{}) bool .
|
||||||
func IntSlice(slice interface{}) ([]int, error) //convert value to int slice
|
func IntSlice(slice interface{}) ([]int, error) //convert value to int slice
|
||||||
func InterfaceSlice(slice interface{}) []interface{} //convert value to interface{} slice
|
func InterfaceSlice(slice interface{}) []interface{} //convert value to interface{} slice
|
||||||
func InsertByIndex(slice interface{}, index int, value interface{}) (interface{}, error) //insert the element into slice at index.
|
func InsertByIndex(slice interface{}, index int, value interface{}) (interface{}, error) //insert the element into slice at index.
|
||||||
@@ -351,12 +396,13 @@ func Map(slice, function interface{}) interface{} //map lisce, function signatur
|
|||||||
func ReverseSlice(slice interface{}) //revere slice
|
func ReverseSlice(slice interface{}) //revere slice
|
||||||
func Reduce(slice, function, zero interface{}) interface{} //reduce slice, function signature should be func(index int, value1, value2 interface{}) interface{}
|
func Reduce(slice, function, zero interface{}) interface{} //reduce slice, function signature should be func(index int, value1, value2 interface{}) interface{}
|
||||||
func SortByField(slice interface{}, field string, sortType ...string) error //sort struct slice by field
|
func SortByField(slice interface{}, field string, sortType ...string) error //sort struct slice by field
|
||||||
|
func Some(slice, function interface{}) bool //return true if any of the values in the list pass the predicate function, function signature should be func(index int, value interface{}) bool
|
||||||
func StringSlice(slice interface{}) []string //convert value to string slice
|
func StringSlice(slice interface{}) []string //convert value to string slice
|
||||||
func Unique(slice interface{}) interface{} //remove duplicate elements in slice
|
func Unique(slice interface{}) interface{} //remove duplicate elements in slice
|
||||||
func UpdateByIndex(slice interface{}, index int, value interface{}) (interface{}, error) //update the slice element at index.
|
func UpdateByIndex(slice interface{}, index int, value interface{}) (interface{}, error) //update the slice element at index.
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 9. strutil is for processing string
|
#### 10. 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"
|
||||||
@@ -396,7 +442,7 @@ func ReverseStr(s string) string //return string whose char order is reversed to
|
|||||||
func SnakeCase(s string) string //covert string to snake_case "fooBar" -> "foo_bar"
|
func SnakeCase(s string) string //covert string to snake_case "fooBar" -> "foo_bar"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 10. validator is for data validation
|
#### 11. 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".
|
||||||
|
|||||||
@@ -5,6 +5,12 @@
|
|||||||
</p>
|
</p>
|
||||||
<div align="center" style="text-align: center;">
|
<div align="center" style="text-align: center;">
|
||||||
|
|
||||||
|

|
||||||
|
[](https://github.com/duke-git/lancet/releases)
|
||||||
|
[](https://pkg.go.dev/github.com/duke-git/lancet)
|
||||||
|
[](https://goreportcard.com/report/github.com/duke-git/lancet)
|
||||||
|
[](https://codecov.io/gh/duke-git/lancet)
|
||||||
|
[](https://github.com/duke-git/lancet/blob/main/LICENSE)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -17,7 +23,7 @@
|
|||||||
- 👏 全面、高效、可复用
|
- 👏 全面、高效、可复用
|
||||||
- 💪 100+常用go工具函数,支持string、slice、datetime、net、crypt...
|
- 💪 100+常用go工具函数,支持string、slice、datetime、net、crypt...
|
||||||
- 💅 只依赖go标准库
|
- 💅 只依赖go标准库
|
||||||
- 🌍 所有导出函数单测试覆盖率100%
|
- 🌍 所有导出函数单元测试覆盖率100%
|
||||||
|
|
||||||
### 安装
|
### 安装
|
||||||
|
|
||||||
@@ -57,7 +63,7 @@ func main() {
|
|||||||
#### 1. convertor数据转换包
|
#### 1. convertor数据转换包
|
||||||
|
|
||||||
- 转换函数支持常用数据类型之间的转换
|
- 转换函数支持常用数据类型之间的转换
|
||||||
- 导入包:import "github.com/duke-git/lancet/cryptor"
|
- 导入包:import "github.com/duke-git/lancet/convertor"
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -94,7 +100,7 @@ func StructToMap(value interface{}) (map[string]interface{}, error) //struct串
|
|||||||
|
|
||||||
#### 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"
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -205,12 +211,15 @@ func main() {
|
|||||||
- 函数列表:
|
- 函数列表:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
func ClearFile(path string) error //清空文件内容
|
||||||
func IsExist(path string) bool //判断文件/目录是否存在
|
func IsExist(path string) bool //判断文件/目录是否存在
|
||||||
func CreateFile(path string) bool //创建文件
|
func CreateFile(path string) bool //创建文件
|
||||||
func IsDir(path string) bool //判断是否为目录
|
func IsDir(path string) bool //判断是否为目录
|
||||||
func RemoveFile(path string) error //删除文件
|
func RemoveFile(path string) error //删除文件
|
||||||
func CopyFile(srcFilePath string, dstFilePath string) error //复制文件
|
func CopyFile(srcFilePath string, dstFilePath string) error //复制文件
|
||||||
func ListFileNames(path string) ([]string, error) //列出目录下所有文件名称
|
func ListFileNames(path string) ([]string, error) //列出目录下所有文件名称
|
||||||
|
func ReadFileToString(path string) (string, error) //读取文件内容为字符串
|
||||||
|
func ReadFileByLine(path string)([]string, error) //按行读取文件内容
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 5. formatter格式化处理包
|
#### 5. formatter格式化处理包
|
||||||
@@ -238,7 +247,39 @@ func main() {
|
|||||||
func Comma(v interface{}, symbol string) string //用逗号每隔3位分割数字/字符串
|
func Comma(v interface{}, symbol string) string //用逗号每隔3位分割数字/字符串
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 6. netutil网络处理包
|
#### 6. function包可以控制函数执行,支持部分函数式编程
|
||||||
|
|
||||||
|
- 控制函数执行,支持部分函数式编程
|
||||||
|
- 导入包:import "github.com/duke-git/lancet/function"
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/function"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var print = func(s string) {
|
||||||
|
fmt.Println(s)
|
||||||
|
}
|
||||||
|
function.Delay(2*time.Second, print, "hello world")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Function list:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func After(n int, fn interface{}) func(args ...interface{}) []reflect.Value //创建一个函数, 只有在运行了n次之后才有效果
|
||||||
|
func Before(n int, fn interface{}) func(args ...interface{}) []reflect.Value //创建一个函数,调用不超过n次。 当n已经达到时,最后一个函数调用的结果将被记住并返回
|
||||||
|
func (f Fn) Curry(i interface{}) func(...interface{}) interface{} //函数柯里化
|
||||||
|
func Compose(fnList ...func(...interface{}) interface{}) func(...interface{}) interface{} //从右至左组合函数
|
||||||
|
func Delay(delay time.Duration, fn interface{}, args ...interface{}) //延迟调用函数
|
||||||
|
func Schedule(d time.Duration, fn interface{}, args ...interface{}) chan bool //每隔duration时间调用函数, 关闭返回通道可以停止调用
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 7. netutil网络处理包
|
||||||
|
|
||||||
- 处理ip, http请求相关函数
|
- 处理ip, http请求相关函数
|
||||||
- 导入包:import "github.com/duke-git/lancet/netutil"
|
- 导入包:import "github.com/duke-git/lancet/netutil"
|
||||||
@@ -283,9 +324,10 @@ func HttpPut(url string, params ...interface{}) (*http.Response, error) //http p
|
|||||||
func HttpDelete(url string, params ...interface{}) (*http.Response, error) //http delete请求
|
func HttpDelete(url string, params ...interface{}) (*http.Response, error) //http delete请求
|
||||||
func HttpPatch(url string, params ...interface{}) (*http.Response, error) //http patch请求
|
func HttpPatch(url string, params ...interface{}) (*http.Response, error) //http patch请求
|
||||||
func ConvertMapToQueryString(param map[string]interface{}) string //将map转换成url query string
|
func ConvertMapToQueryString(param map[string]interface{}) string //将map转换成url query string
|
||||||
|
func ParseHttpResponse(resp *http.Response, obj interface{}) error //将http响应解码成特定interface
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 7. random随机数处理包
|
#### 8. random随机数处理包
|
||||||
|
|
||||||
- 生成和处理随机数
|
- 生成和处理随机数
|
||||||
- 导入包:import "github.com/duke-git/lancet/random"
|
- 导入包:import "github.com/duke-git/lancet/random"
|
||||||
@@ -314,7 +356,7 @@ func RandInt(min, max int) int //生成随机int
|
|||||||
func RandString(length int) string //生成随机string
|
func RandString(length int) string //生成随机string
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 8. slice切片操作包
|
#### 9. slice切片操作包
|
||||||
|
|
||||||
- 切片操作相关函数
|
- 切片操作相关函数
|
||||||
- 导入包:import "github.com/duke-git/lancet/slice"
|
- 导入包:import "github.com/duke-git/lancet/slice"
|
||||||
@@ -345,6 +387,8 @@ func Chunk(slice []interface{}, size int) [][]interface{} //均分slice
|
|||||||
func ConvertSlice(originalSlice interface{}, newSliceType reflect.Type) interface{} //将originalSlice转换为 newSliceType
|
func ConvertSlice(originalSlice interface{}, newSliceType reflect.Type) interface{} //将originalSlice转换为 newSliceType
|
||||||
func Difference(slice1, slice2 interface{}) interface{} //返回
|
func Difference(slice1, slice2 interface{}) interface{} //返回
|
||||||
func DeleteByIndex(slice interface{}, start int, end ...int) (interface{}, error) //删除切片中start到end位置的值
|
func DeleteByIndex(slice interface{}, start int, end ...int) (interface{}, error) //删除切片中start到end位置的值
|
||||||
|
func Every(slice, function interface{}) bool //slice中所有元素都符合函数条件时返回true, 否则返回false. 函数签名:func(index int, value interface{}) bool
|
||||||
|
func Find(slice, function interface{}) interface{} //查找slice中第一个符合条件的元素,函数签名:func(index int, value interface{}) bool
|
||||||
func Filter(slice, function interface{}) interface{} //过滤slice, 函数签名:func(index int, value interface{}) bool
|
func Filter(slice, function interface{}) interface{} //过滤slice, 函数签名:func(index int, value interface{}) bool
|
||||||
func IntSlice(slice interface{}) ([]int, error) //转成int切片
|
func IntSlice(slice interface{}) ([]int, error) //转成int切片
|
||||||
func InterfaceSlice(slice interface{}) []interface{} //转成interface{}切片
|
func InterfaceSlice(slice interface{}) []interface{} //转成interface{}切片
|
||||||
@@ -352,13 +396,14 @@ func InsertByIndex(slice interface{}, index int, value interface{}) (interface{}
|
|||||||
func Map(slice, function interface{}) interface{} //遍历切片, 函数签名:func(index int, value interface{}) interface{}
|
func Map(slice, function interface{}) interface{} //遍历切片, 函数签名:func(index int, value interface{}) interface{}
|
||||||
func ReverseSlice(slice interface{}) //反转切片
|
func ReverseSlice(slice interface{}) //反转切片
|
||||||
func Reduce(slice, function, zero interface{}) interface{} //切片reduce操作, 函数签名:func(index int, value1, value2 interface{}) interface{}
|
func Reduce(slice, function, zero interface{}) interface{} //切片reduce操作, 函数签名:func(index int, value1, value2 interface{}) interface{}
|
||||||
|
func Some(slice, function interface{}) bool //slice中任意一个元素都符合函数条件时返回true, 否则返回false. 函数签名:func(index int, value interface{}) bool
|
||||||
func SortByField(slice interface{}, field string, sortType ...string) error //对struct切片进行排序
|
func SortByField(slice interface{}, field string, sortType ...string) error //对struct切片进行排序
|
||||||
func StringSlice(slice interface{}) []string //转为string切片
|
func StringSlice(slice interface{}) []string //转为string切片
|
||||||
func Unique(slice interface{}) interface{} //去重切片
|
func Unique(slice interface{}) interface{} //去重切片
|
||||||
func UpdateByIndex(slice interface{}, index int, value interface{}) (interface{}, error) //在切片中index位置更新value
|
func UpdateByIndex(slice interface{}, index int, value interface{}) (interface{}, error) //在切片中index位置更新value
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 9. strutil字符串处理包
|
#### 10. strutil字符串处理包
|
||||||
|
|
||||||
- 字符串操作相关函数
|
- 字符串操作相关函数
|
||||||
- 导入包:import "github.com/duke-git/lancet/strutil"
|
- 导入包:import "github.com/duke-git/lancet/strutil"
|
||||||
@@ -398,7 +443,7 @@ func ReverseStr(s string) string //字符串逆袭
|
|||||||
func SnakeCase(s string) string //字符串转为SnakeCase, "fooBar" -> "foo_bar"
|
func SnakeCase(s string) string //字符串转为SnakeCase, "fooBar" -> "foo_bar"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 10. validator验证器包
|
#### 11. validator验证器包
|
||||||
|
|
||||||
- 数据校验相关函数
|
- 数据校验相关函数
|
||||||
- 导入包:import "github.com/duke-git/lancet/validator"
|
- 导入包:import "github.com/duke-git/lancet/validator"
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ package convertor
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/utils"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestToChar(t *testing.T) {
|
func TestToChar(t *testing.T) {
|
||||||
@@ -58,8 +59,12 @@ func TestToBytes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestToInt(t *testing.T) {
|
func TestToInt(t *testing.T) {
|
||||||
cases := []interface{}{"123", "-123", 123, "abc", false, "111111111111111111111111111111111111111"}
|
cases := []interface{}{"123", "-123", 123,
|
||||||
expected := []int64{123, -123, 123, 0, 0, 0}
|
uint(123), uint8(123), uint16(123), uint32(123), uint64(123),
|
||||||
|
float32(12.3), float64(12.3),
|
||||||
|
"abc", false, "111111111111111111111111111111111111111"}
|
||||||
|
|
||||||
|
expected := []int64{123, -123, 123, 123, 123, 123, 123, 123, 12, 12, 0, 0, 0}
|
||||||
|
|
||||||
for i := 0; i < len(cases); i++ {
|
for i := 0; i < len(cases); i++ {
|
||||||
res, _ := ToInt(cases[i])
|
res, _ := ToInt(cases[i])
|
||||||
@@ -71,8 +76,14 @@ func TestToInt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestToFloat(t *testing.T) {
|
func TestToFloat(t *testing.T) {
|
||||||
cases := []interface{}{"", "-1", "-.11", "1.23e3", ".123e10", "abc"}
|
cases := []interface{}{
|
||||||
expected := []float64{0, -1, -0.11, 1230, 0.123e10, 0}
|
"", "-1", "-.11", "1.23e3", ".123e10", "abc",
|
||||||
|
int(0), int8(1), int16(-1), int32(123), int64(123),
|
||||||
|
uint(123), uint8(123), uint16(123), uint32(123), uint64(123),
|
||||||
|
float64(12.3), float32(12.3),
|
||||||
|
}
|
||||||
|
expected := []float64{0, -1, -0.11, 1230, 0.123e10, 0,
|
||||||
|
0, 1, -1, 123, 123, 123, 123, 123, 123, 123, 12.3, 12.300000190734863}
|
||||||
|
|
||||||
for i := 0; i < len(cases); i++ {
|
for i := 0; i < len(cases); i++ {
|
||||||
res, _ := ToFloat(cases[i])
|
res, _ := ToFloat(cases[i])
|
||||||
@@ -84,41 +95,37 @@ func TestToFloat(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestToString(t *testing.T) {
|
func TestToString(t *testing.T) {
|
||||||
// basic type
|
|
||||||
toString(t, "a1", "a1")
|
|
||||||
toString(t, 111, "111")
|
|
||||||
toString(t, 111.01, "111.01")
|
|
||||||
toString(t, true, "true")
|
|
||||||
//toString(t, 1.5+10i, "(1.5+10i)")
|
|
||||||
|
|
||||||
// slice
|
|
||||||
aSlice := []int{1, 2, 3}
|
|
||||||
toString(t, aSlice, "[1,2,3]")
|
|
||||||
|
|
||||||
// map
|
// map
|
||||||
aMap := make(map[string]int)
|
aMap := make(map[string]int)
|
||||||
aMap["a"] = 1
|
aMap["a"] = 1
|
||||||
aMap["b"] = 2
|
aMap["b"] = 2
|
||||||
aMap["c"] = 3
|
aMap["c"] = 3
|
||||||
|
|
||||||
toString(t, aMap, "{\"a\":1,\"b\":2,\"c\":3}")
|
|
||||||
|
|
||||||
// struct
|
// struct
|
||||||
type TestStruct struct {
|
type TestStruct struct {
|
||||||
Name string
|
Name string
|
||||||
}
|
}
|
||||||
aStruct := TestStruct{Name: "TestStruct"}
|
aStruct := TestStruct{Name: "TestStruct"}
|
||||||
toString(t, aStruct, "{\"Name\":\"TestStruct\"}")
|
|
||||||
}
|
|
||||||
|
|
||||||
func toString(t *testing.T, test interface{}, expected string) {
|
cases := []interface{}{
|
||||||
res := ToString(test)
|
int(0), int8(1), int16(-1), int32(123), int64(123),
|
||||||
if res != expected {
|
uint(123), uint8(123), uint16(123), uint32(123), uint64(123),
|
||||||
utils.LogFailedTestInfo(t, "ToString", test, expected, res)
|
float64(12.3), float32(12.3),
|
||||||
t.FailNow()
|
true, false,
|
||||||
|
[]int{1, 2, 3}, aMap, aStruct, []byte{104, 101, 108, 108, 111}}
|
||||||
|
|
||||||
|
expected := []string{"0", "1", "-1", "123", "123", "123", "123", "123",
|
||||||
|
"123", "123", "12.3", "12.300000190734863", "true", "false",
|
||||||
|
"[1,2,3]", "{\"a\":1,\"b\":2,\"c\":3}", "{\"Name\":\"TestStruct\"}", "hello"}
|
||||||
|
|
||||||
|
for i := 0; i < len(cases); i++ {
|
||||||
|
res := ToString(cases[i])
|
||||||
|
if res != expected[i] {
|
||||||
|
utils.LogFailedTestInfo(t, "ToString", cases[i], expected[i], res)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestToJson(t *testing.T) {
|
func TestToJson(t *testing.T) {
|
||||||
// map
|
// map
|
||||||
aMap := make(map[string]int)
|
aMap := make(map[string]int)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
package fileutil
|
package fileutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@@ -17,7 +18,7 @@ func IsExist(path string) bool {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if errors.Is(err, os.ErrExist) {
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@@ -75,6 +76,53 @@ func CopyFile(srcFilePath string, dstFilePath string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ClearFile write empty string to path file
|
||||||
|
func ClearFile(path string) error {
|
||||||
|
f, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
_, err = f.WriteString("")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//ReadFileToString return string of file content
|
||||||
|
func ReadFileToString(path string) (string, error) {
|
||||||
|
bytes, err := ioutil.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(bytes), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadFileByLine read file line by line
|
||||||
|
func ReadFileByLine(path string) ([]string, error) {
|
||||||
|
f, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
res := make([]string, 0)
|
||||||
|
buf := bufio.NewReader(f)
|
||||||
|
|
||||||
|
for {
|
||||||
|
line, _, err := buf.ReadLine()
|
||||||
|
l := string(line)
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
res = append(res, l)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ListFileNames return all file names in the path
|
// ListFileNames return all file names in the path
|
||||||
func ListFileNames(path string) ([]string, error) {
|
func ListFileNames(path string) ([]string, error) {
|
||||||
if !IsExist(path) {
|
if !IsExist(path) {
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestIsExist(t *testing.T) {
|
func TestIsExist(t *testing.T) {
|
||||||
cases := []string{"./", "./a.txt"}
|
cases := []string{"./", "./file.go", "./a.txt"}
|
||||||
expected := []bool{true, false}
|
expected := []bool{true, true, false}
|
||||||
|
|
||||||
for i := 0; i < len(cases); i++ {
|
for i := 0; i < len(cases); i++ {
|
||||||
res := IsExist(cases[i])
|
res := IsExist(cases[i])
|
||||||
@@ -87,14 +87,52 @@ func TestCopyFile(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestListFileNames(t *testing.T) {
|
func TestListFileNames(t *testing.T) {
|
||||||
filesInCurrentPath, err := ListFileNames("./")
|
filesInCurrentPath, err := ListFileNames("../datetime/")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
expected := []string{"file.go", "file_test.go"}
|
expected := []string{"datetime.go", "datetime_test.go"}
|
||||||
if !reflect.DeepEqual(filesInCurrentPath, expected) {
|
if !reflect.DeepEqual(filesInCurrentPath, expected) {
|
||||||
utils.LogFailedTestInfo(t, "ToChar", "./", expected, filesInCurrentPath)
|
utils.LogFailedTestInfo(t, "ToChar", "./", expected, filesInCurrentPath)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReadFileToString(t *testing.T) {
|
||||||
|
path := "./text.txt"
|
||||||
|
CreateFile(path)
|
||||||
|
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||||
|
f.WriteString("hello world")
|
||||||
|
|
||||||
|
res, _ := ReadFileToString(path)
|
||||||
|
if res != "hello world" {
|
||||||
|
utils.LogFailedTestInfo(t, "ReadFileToString", path, "hello world", res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClearFile(t *testing.T) {
|
||||||
|
path := "./text.txt"
|
||||||
|
CreateFile(path)
|
||||||
|
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||||
|
f.WriteString("hello world")
|
||||||
|
|
||||||
|
CreateFile(path)
|
||||||
|
|
||||||
|
res, _ := ReadFileToString(path)
|
||||||
|
if res != "" {
|
||||||
|
utils.LogFailedTestInfo(t, "CreateFile", path, "", res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReadFileByLine(t *testing.T) {
|
||||||
|
path := "./text.txt"
|
||||||
|
CreateFile(path)
|
||||||
|
f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||||
|
f.WriteString("hello\nworld")
|
||||||
|
|
||||||
|
expected := []string{"hello", "world"}
|
||||||
|
res, _ := ReadFileByLine(path)
|
||||||
|
if !reflect.DeepEqual(res, expected) {
|
||||||
|
utils.LogFailedTestInfo(t, "ReadFileByLine", path, expected, res)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,8 @@ import (
|
|||||||
func TestComma(t *testing.T) {
|
func TestComma(t *testing.T) {
|
||||||
comma(t, "", "", "")
|
comma(t, "", "", "")
|
||||||
comma(t, "aa", "", "")
|
comma(t, "aa", "", "")
|
||||||
|
comma(t, "aa.a", "", "")
|
||||||
|
comma(t, []int{1}, "", "")
|
||||||
comma(t, "123", "", "123")
|
comma(t, "123", "", "123")
|
||||||
comma(t, "12345", "", "12,345")
|
comma(t, "12345", "", "12,345")
|
||||||
comma(t, 12345, "", "12,345")
|
comma(t, 12345, "", "12,345")
|
||||||
|
|||||||
87
function/function.go
Normal file
87
function/function.go
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||||
|
// Use of this source code is governed by MIT license
|
||||||
|
|
||||||
|
// Package function implements some functions for control the function execution and some is for functional programming.
|
||||||
|
|
||||||
|
package function
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// After creates a function that invokes func once it's called n or more times
|
||||||
|
func After(n int, fn interface{}) func(args ...interface{}) []reflect.Value {
|
||||||
|
return func(args ...interface{}) []reflect.Value {
|
||||||
|
n--
|
||||||
|
if n < 1 {
|
||||||
|
return invokeFunc(fn, args...)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Before creates a function that invokes func once it's called less than n times
|
||||||
|
func Before(n int, fn interface{}) func(args ...interface{}) []reflect.Value {
|
||||||
|
var res []reflect.Value
|
||||||
|
|
||||||
|
return func(args ...interface{}) []reflect.Value {
|
||||||
|
if n > 0 {
|
||||||
|
res = invokeFunc(fn, args...)
|
||||||
|
}
|
||||||
|
if n <= 0 {
|
||||||
|
fn = nil
|
||||||
|
}
|
||||||
|
n--
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Fn func(...interface{}) interface{}
|
||||||
|
|
||||||
|
// Curry make a curryed function
|
||||||
|
func (f Fn) Curry(i interface{}) func(...interface{}) interface{} {
|
||||||
|
return func(values ...interface{}) interface{} {
|
||||||
|
v := append([]interface{}{i}, values...)
|
||||||
|
return f(v...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compose compose the functions from right to left
|
||||||
|
func Compose(fnList ...func(...interface{}) interface{}) func(...interface{}) interface{} {
|
||||||
|
return func(s... interface{}) interface{} {
|
||||||
|
f := fnList[0]
|
||||||
|
restFn := fnList[1:]
|
||||||
|
|
||||||
|
if len(fnList) == 1 {
|
||||||
|
return f(s...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return f(Compose(restFn...)(s...))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Delay make the function execution after delayed time
|
||||||
|
func Delay(delay time.Duration, fn interface{}, args ...interface{}) {
|
||||||
|
time.Sleep(delay)
|
||||||
|
invokeFunc(fn, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Schedule invoke function every duration time, util close the returned bool chan
|
||||||
|
func Schedule(d time.Duration, fn interface{}, args ...interface{}) chan bool {
|
||||||
|
quit := make(chan bool)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
invokeFunc(fn, args...)
|
||||||
|
select {
|
||||||
|
case <-time.After(d):
|
||||||
|
case <-quit:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return quit
|
||||||
|
}
|
||||||
114
function/function_test.go
Normal file
114
function/function_test.go
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
package function
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAfter(t *testing.T) {
|
||||||
|
arr := []string{"a", "b"}
|
||||||
|
f := After(len(arr), func(i int) int {
|
||||||
|
fmt.Println("print done")
|
||||||
|
return i
|
||||||
|
})
|
||||||
|
type cb func(args ...interface{}) []reflect.Value
|
||||||
|
print := func(i int, s string, fn cb) {
|
||||||
|
fmt.Printf("print: arr[%d] is %s \n", i, s)
|
||||||
|
v := fn(i)
|
||||||
|
if v != nil {
|
||||||
|
vv := v[0].Int()
|
||||||
|
if vv != 1 {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println("print: arr is", arr)
|
||||||
|
for i := 0; i < len(arr); i++ {
|
||||||
|
print(i, arr[i], f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBefore(t *testing.T) {
|
||||||
|
arr := []string{"a", "b", "c", "d", "e"}
|
||||||
|
f := Before(3, func(i int) int {
|
||||||
|
return i
|
||||||
|
})
|
||||||
|
|
||||||
|
var res []int64
|
||||||
|
type cb func(args ...interface{}) []reflect.Value
|
||||||
|
appendStr := func(i int, s string, fn cb) {
|
||||||
|
fmt.Printf("appendStr: arr[%d] is %s \n", i, s)
|
||||||
|
v := fn(i)
|
||||||
|
res = append(res, v[0].Int())
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(arr); i++ {
|
||||||
|
appendStr(i, arr[i], f)
|
||||||
|
}
|
||||||
|
|
||||||
|
expect := []int64{0, 1, 2, 2, 2}
|
||||||
|
if !reflect.DeepEqual(expect, res) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCurry(t *testing.T) {
|
||||||
|
add := func(a, b int) int {
|
||||||
|
return a + b
|
||||||
|
}
|
||||||
|
var addCurry Fn = func(values ...interface{}) interface{} {
|
||||||
|
return add(values[0].(int), values[1].(int))
|
||||||
|
}
|
||||||
|
|
||||||
|
add1 := addCurry.Curry(1)
|
||||||
|
v := add1(2)
|
||||||
|
if v != 3 {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompose(t *testing.T) {
|
||||||
|
toUpper := func(a ...interface{}) interface{} {
|
||||||
|
return strings.ToUpper(a[0].(string))
|
||||||
|
}
|
||||||
|
toLower := func(a ...interface{}) interface{} {
|
||||||
|
return strings.ToLower(a[0].(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
expect := toUpper(toLower("aBCde"))
|
||||||
|
cf := Compose(toUpper, toLower)
|
||||||
|
res := cf("aBCde")
|
||||||
|
|
||||||
|
if res != expect {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDelay(t *testing.T) {
|
||||||
|
var print = func(s string) {
|
||||||
|
fmt.Println(s)
|
||||||
|
}
|
||||||
|
Delay(2*time.Second, print, "test delay")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSchedule(t *testing.T) {
|
||||||
|
var res []string
|
||||||
|
appendStr := func(s string) {
|
||||||
|
fmt.Println(s)
|
||||||
|
res = append(res, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
stop := Schedule(1*time.Second, appendStr, "*")
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
close(stop)
|
||||||
|
|
||||||
|
expect := []string{"*", "*", "*", "*", "*"}
|
||||||
|
if !reflect.DeepEqual(expect, res) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
fmt.Println("done")
|
||||||
|
}
|
||||||
23
function/function_util.go
Normal file
23
function/function_util.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package function
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
func invokeFunc(fn interface{}, args ...interface{}) []reflect.Value {
|
||||||
|
fv := functionValue(fn)
|
||||||
|
params := make([]reflect.Value, len(args))
|
||||||
|
for i, item := range args {
|
||||||
|
params[i] = reflect.ValueOf(item)
|
||||||
|
}
|
||||||
|
return fv.Call(params)
|
||||||
|
}
|
||||||
|
|
||||||
|
func functionValue(function interface{}) reflect.Value {
|
||||||
|
v := reflect.ValueOf(function)
|
||||||
|
if v.Kind() != reflect.Func {
|
||||||
|
panic(fmt.Sprintf("Invalid function type, value of type %T", function))
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
@@ -12,6 +12,8 @@
|
|||||||
package netutil
|
package netutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -43,6 +45,15 @@ func HttpPatch(url string, params ...interface{}) (*http.Response, error) {
|
|||||||
return request(http.MethodPatch, url, params...)
|
return request(http.MethodPatch, url, params...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseHttpResponse decode http response to specified interface
|
||||||
|
func ParseHttpResponse(resp *http.Response, obj interface{}) error {
|
||||||
|
if resp == nil {
|
||||||
|
return errors.New("InvalidResp")
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
return json.NewDecoder(resp.Body).Decode(obj)
|
||||||
|
}
|
||||||
|
|
||||||
// ConvertMapToQueryString convert map to sorted url query string
|
// ConvertMapToQueryString convert map to sorted url query string
|
||||||
func ConvertMapToQueryString(param map[string]interface{}) string {
|
func ConvertMapToQueryString(param map[string]interface{}) string {
|
||||||
if param == nil {
|
if param == nil {
|
||||||
|
|||||||
@@ -11,6 +11,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestHttpGet(t *testing.T) {
|
func TestHttpGet(t *testing.T) {
|
||||||
|
_, e := HttpGet("", nil)
|
||||||
|
if e == nil {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
url := "https://gutendex.com/books?"
|
url := "https://gutendex.com/books?"
|
||||||
queryParams := make(map[string]interface{})
|
queryParams := make(map[string]interface{})
|
||||||
queryParams["ids"] = "1"
|
queryParams["ids"] = "1"
|
||||||
@@ -97,3 +102,27 @@ func TestConvertMapToQueryString(t *testing.T) {
|
|||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseResponse(t *testing.T) {
|
||||||
|
url := "http://public-api-v1.aspirantzhang.com/users"
|
||||||
|
type User struct {
|
||||||
|
Id int `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
}
|
||||||
|
type UserResp struct {
|
||||||
|
Data []User `json:"data"`
|
||||||
|
}
|
||||||
|
resp, err := HttpGet(url)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
userResp := &UserResp{}
|
||||||
|
err = ParseHttpResponse(resp, userResp)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
fmt.Println(userResp.Data)
|
||||||
|
}
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ func setQueryParam(req *http.Request, reqUrl string, queryParam interface{}) err
|
|||||||
case map[string]interface{}:
|
case map[string]interface{}:
|
||||||
values = url.Values{}
|
values = url.Values{}
|
||||||
for k := range v {
|
for k := range v {
|
||||||
values.Set(k, fmt.Sprintf("%s", v[k]))
|
values.Set(k, fmt.Sprintf("%v", v[k]))
|
||||||
}
|
}
|
||||||
case url.Values:
|
case url.Values:
|
||||||
values = v
|
values = v
|
||||||
|
|||||||
@@ -1,11 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* @Descripttion:
|
||||||
|
* @version: v1.0.0
|
||||||
|
* @Author: dudaodong@kingsoft.com
|
||||||
|
* @Date: 2021-11-29 11:43:28
|
||||||
|
* @LastEditors: dudaodong@kingsoft.com
|
||||||
|
* @LastEditTime: 2021-12-01 18:05:29
|
||||||
|
*/
|
||||||
package random
|
package random
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/utils"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRandString(t *testing.T) {
|
func TestRandString(t *testing.T) {
|
||||||
@@ -21,26 +30,42 @@ func TestRandString(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRandInt(t *testing.T) {
|
func TestRandInt(t *testing.T) {
|
||||||
randInt := RandInt(1, 10)
|
res1 := RandInt(1, 10)
|
||||||
|
if res1 < 1 || res1 >= 10 {
|
||||||
|
utils.LogFailedTestInfo(t, "RandInt", "RandInt(1, 10)", "RandInt(1, 10) should between [1, 10) ", res1)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
if randInt < 1 || randInt >= 10 {
|
res2 := RandInt(1, 1)
|
||||||
utils.LogFailedTestInfo(t, "RandInt", "RandInt(1, 10)", "RandInt(1, 10) should between [1, 10) ", randInt)
|
if res2 != 1 {
|
||||||
|
utils.LogFailedTestInfo(t, "RandInt", "RandInt(1, 1)", "RandInt(1, 1) should be 1 ", res2)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
res3 := RandInt(10, 1)
|
||||||
|
if res3 < 1 || res3 >= 10 {
|
||||||
|
utils.LogFailedTestInfo(t, "RandInt", "RandInt(10, 1)", "RandInt(10, 1) should between [1, 10) ", res3)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRandBytes(t *testing.T) {
|
func TestRandBytes(t *testing.T) {
|
||||||
randBytes := RandBytes(4)
|
randBytes := RandBytes(4)
|
||||||
|
|
||||||
if len(randBytes) != 4 {
|
if len(randBytes) != 4 {
|
||||||
utils.LogFailedTestInfo(t, "RandBytes", "RandBytes(4)", "RandBytes(4) should return 4 element of []bytes", randBytes)
|
utils.LogFailedTestInfo(t, "RandBytes", "RandBytes(4)", "RandBytes(4) should return 4 element of []bytes", randBytes)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
v := reflect.ValueOf(randBytes)
|
v := reflect.ValueOf(randBytes)
|
||||||
et := v.Type().Elem()
|
et := v.Type().Elem()
|
||||||
if v.Kind() != reflect.Slice || et.Kind() != reflect.Uint8 {
|
if v.Kind() != reflect.Slice || et.Kind() != reflect.Uint8 {
|
||||||
utils.LogFailedTestInfo(t, "RandBytes", "RandBytes(4)", "RandBytes(4) should return 4 element of []bytes", randBytes)
|
utils.LogFailedTestInfo(t, "RandBytes", "RandBytes(4)", "RandBytes(4) should return 4 element of []bytes", randBytes)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
randErr := RandBytes(0)
|
||||||
|
if randErr != nil {
|
||||||
|
utils.LogFailedTestInfo(t, "RandBytes", "RandBytes(0)", "RandBytes(0) should return nil", randErr)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,6 +89,50 @@ func Difference(slice1, slice2 interface{}) interface{} {
|
|||||||
return res.Interface()
|
return res.Interface()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Every return true if all of the values in the slice pass the predicate function.
|
||||||
|
// The function signature should be func(index int, value interface{}) bool .
|
||||||
|
func Every(slice, function interface{}) bool {
|
||||||
|
sv := sliceValue(slice)
|
||||||
|
fn := functionValue(function)
|
||||||
|
|
||||||
|
elemType := sv.Type().Elem()
|
||||||
|
if checkSliceCallbackFuncSignature(fn, elemType, reflect.ValueOf(true).Type()) {
|
||||||
|
panic("Filter function must be of type func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
|
||||||
|
}
|
||||||
|
|
||||||
|
var indexes []int
|
||||||
|
for i := 0; i < sv.Len(); i++ {
|
||||||
|
flag := fn.Call([]reflect.Value{reflect.ValueOf(i), sv.Index(i)})[0]
|
||||||
|
if flag.Bool() {
|
||||||
|
indexes = append(indexes, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(indexes) == sv.Len()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some return true if any of the values in the list pass the predicate function.
|
||||||
|
// The function signature should be func(index int, value interface{}) bool .
|
||||||
|
func Some(slice, function interface{}) bool {
|
||||||
|
sv := sliceValue(slice)
|
||||||
|
fn := functionValue(function)
|
||||||
|
|
||||||
|
elemType := sv.Type().Elem()
|
||||||
|
if checkSliceCallbackFuncSignature(fn, elemType, reflect.ValueOf(true).Type()) {
|
||||||
|
panic("Filter function must be of type func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
|
||||||
|
}
|
||||||
|
|
||||||
|
has := false
|
||||||
|
for i := 0; i < sv.Len(); i++ {
|
||||||
|
flag := fn.Call([]reflect.Value{reflect.ValueOf(i), sv.Index(i)})[0]
|
||||||
|
if flag.Bool() {
|
||||||
|
has = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return has
|
||||||
|
}
|
||||||
|
|
||||||
// Filter iterates over elements of slice, returning an slice of all elements `signature` returns truthy for.
|
// Filter iterates over elements of slice, returning an slice of all elements `signature` returns truthy for.
|
||||||
// The function signature should be func(index int, value interface{}) bool .
|
// The function signature should be func(index int, value interface{}) bool .
|
||||||
func Filter(slice, function interface{}) interface{} {
|
func Filter(slice, function interface{}) interface{} {
|
||||||
@@ -115,6 +159,28 @@ func Filter(slice, function interface{}) interface{} {
|
|||||||
return res.Interface()
|
return res.Interface()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Find iterates over elements of slice, returning the first one that passes a truth test on function.
|
||||||
|
// The function signature should be func(index int, value interface{}) bool .
|
||||||
|
func Find(slice, function interface{}) interface{} {
|
||||||
|
sv := sliceValue(slice)
|
||||||
|
fn := functionValue(function)
|
||||||
|
|
||||||
|
elemType := sv.Type().Elem()
|
||||||
|
if checkSliceCallbackFuncSignature(fn, elemType, reflect.ValueOf(true).Type()) {
|
||||||
|
panic("Filter function must be of type func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
|
||||||
|
}
|
||||||
|
|
||||||
|
var index int
|
||||||
|
for i := 0; i < sv.Len(); i++ {
|
||||||
|
flag := fn.Call([]reflect.Value{reflect.ValueOf(i), sv.Index(i)})[0]
|
||||||
|
if flag.Bool() {
|
||||||
|
index = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sv.Index(index).Interface()
|
||||||
|
}
|
||||||
|
|
||||||
// Map creates an slice of values by running each element of `slice` thru `function`.
|
// Map creates an slice of values by running each element of `slice` thru `function`.
|
||||||
// The function signature should be func(index int, value interface{}) interface{}.
|
// The function signature should be func(index int, value interface{}) interface{}.
|
||||||
func Map(slice, function interface{}) interface{} {
|
func Map(slice, function interface{}) interface{} {
|
||||||
@@ -137,17 +203,16 @@ func Map(slice, function interface{}) interface{} {
|
|||||||
// The function signature should be func(index int, value1, value2 interface{}) interface{} .
|
// The function signature should be func(index int, value1, value2 interface{}) interface{} .
|
||||||
func Reduce(slice, function, zero interface{}) interface{} {
|
func Reduce(slice, function, zero interface{}) interface{} {
|
||||||
sv := sliceValue(slice)
|
sv := sliceValue(slice)
|
||||||
|
elementType := sv.Type().Elem()
|
||||||
|
|
||||||
len := sv.Len()
|
len := sv.Len()
|
||||||
if len == 0 {
|
if len == 0 {
|
||||||
return zero
|
return zero
|
||||||
} else if len == 1 {
|
} else if len == 1 {
|
||||||
return sv.Index(0)
|
return sv.Index(0).Interface()
|
||||||
}
|
}
|
||||||
|
|
||||||
elementType := sv.Type().Elem()
|
|
||||||
fn := functionValue(function)
|
fn := functionValue(function)
|
||||||
|
|
||||||
if checkSliceCallbackFuncSignature(fn, elementType, elementType, elementType) {
|
if checkSliceCallbackFuncSignature(fn, elementType, elementType, elementType) {
|
||||||
t := elementType.String()
|
t := elementType.String()
|
||||||
panic("Reduce function must be of type func(int, " + t + ", " + t + ")" + t)
|
panic("Reduce function must be of type func(int, " + t + ", " + t + ")" + t)
|
||||||
|
|||||||
@@ -14,6 +14,15 @@ func TestContain(t *testing.T) {
|
|||||||
|
|
||||||
var t2 []string
|
var t2 []string
|
||||||
contain(t, t2, "1", false)
|
contain(t, t2, "1", false)
|
||||||
|
|
||||||
|
m := make(map[string]int)
|
||||||
|
m["a"] = 1
|
||||||
|
contain(t, m, "a", true)
|
||||||
|
contain(t, m, "b", false)
|
||||||
|
|
||||||
|
s := "hello"
|
||||||
|
contain(t, s, "h", true)
|
||||||
|
contain(t, s, "s", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func contain(t *testing.T, test interface{}, value interface{}, expected bool) {
|
func contain(t *testing.T, test interface{}, value interface{}, expected bool) {
|
||||||
@@ -87,15 +96,39 @@ func TestConvertSlice(t *testing.T) {
|
|||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEvery(t *testing.T) {
|
||||||
|
nums := []int{1, 2, 3, 5}
|
||||||
|
isEven := func(i, num int) bool {
|
||||||
|
return num%2 == 0
|
||||||
|
}
|
||||||
|
res := Every(nums, isEven)
|
||||||
|
if res != false {
|
||||||
|
utils.LogFailedTestInfo(t, "Every", nums, false, res)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSome(t *testing.T) {
|
||||||
|
nums := []int{1, 2, 3, 5}
|
||||||
|
isEven := func(i, num int) bool {
|
||||||
|
return num%2 == 0
|
||||||
|
}
|
||||||
|
res := Some(nums, isEven)
|
||||||
|
if res != true {
|
||||||
|
utils.LogFailedTestInfo(t, "Some", nums, true, res)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestFilter(t *testing.T) {
|
func TestFilter(t *testing.T) {
|
||||||
s1 := []int{1, 2, 3, 4, 5}
|
nums := []int{1, 2, 3, 4, 5}
|
||||||
even := func(i, num int) bool {
|
even := func(i, num int) bool {
|
||||||
return num%2 == 0
|
return num%2 == 0
|
||||||
}
|
}
|
||||||
e1 := []int{2, 4}
|
e1 := []int{2, 4}
|
||||||
r1 := Filter(s1, even)
|
r1 := Filter(nums, even)
|
||||||
if !reflect.DeepEqual(r1, e1) {
|
if !reflect.DeepEqual(r1, e1) {
|
||||||
utils.LogFailedTestInfo(t, "Filter", s1, e1, r1)
|
utils.LogFailedTestInfo(t, "Filter", nums, e1, r1)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,6 +161,18 @@ func TestFilter(t *testing.T) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFind(t *testing.T) {
|
||||||
|
nums := []int{1, 2, 3, 4, 5}
|
||||||
|
even := func(i, num int) bool {
|
||||||
|
return num%2 == 0
|
||||||
|
}
|
||||||
|
res := Find(nums, even)
|
||||||
|
if res != 2 {
|
||||||
|
utils.LogFailedTestInfo(t, "Find", nums, 2, res)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestMap(t *testing.T) {
|
func TestMap(t *testing.T) {
|
||||||
s1 := []int{1, 2, 3, 4}
|
s1 := []int{1, 2, 3, 4}
|
||||||
multiplyTwo := func(i, num int) int {
|
multiplyTwo := func(i, num int) int {
|
||||||
@@ -167,28 +212,21 @@ func TestMap(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestReduce(t *testing.T) {
|
func TestReduce(t *testing.T) {
|
||||||
s1 := []int{1, 2, 3, 4}
|
cases := [][]int{
|
||||||
f1 := func(i, v1, v2 int) int {
|
{},
|
||||||
|
{1},
|
||||||
|
{1, 2, 3, 4}}
|
||||||
|
expected := []int{0, 1, 10}
|
||||||
|
f := func(i, v1, v2 int) int {
|
||||||
return v1 + v2
|
return v1 + v2
|
||||||
}
|
}
|
||||||
e1 := 10
|
for i := 0; i < len(cases); i++ {
|
||||||
r1 := Reduce(s1, f1, 0)
|
res := Reduce(cases[i], f, 0)
|
||||||
if e1 != r1 {
|
if res != expected[i] {
|
||||||
utils.LogFailedTestInfo(t, "Reduce", s1, e1, r1)
|
utils.LogFailedTestInfo(t, "Reduce", cases[i], expected[i], res)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// failed Reduce function should be func(i int, v1, v2 int) int
|
|
||||||
//s1 := []int{1, 2, 3, 4}
|
|
||||||
//f1 := func(i string, v1, v2 int) int { //i should be int
|
|
||||||
// return v1+v2
|
|
||||||
//}
|
|
||||||
//e1 := 10
|
|
||||||
//r1 := Reduce(s1, f1, 0)
|
|
||||||
//if e1 != r1 {
|
|
||||||
// utils.LogFailedTestInfo(t, "Reduce", s1, e1, r1)
|
|
||||||
// t.FailNow()
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIntSlice(t *testing.T) {
|
func TestIntSlice(t *testing.T) {
|
||||||
@@ -340,11 +378,6 @@ func TestUpdateByIndex(t *testing.T) {
|
|||||||
r3 := []string{"a", "b", "1"}
|
r3 := []string{"a", "b", "1"}
|
||||||
updateByIndex(t, t1, 2, "1", r3)
|
updateByIndex(t, t1, 2, "1", r3)
|
||||||
|
|
||||||
//failed
|
|
||||||
//t1 = []string{"a","b","c"}
|
|
||||||
//r4 := []string{"a", "b", "1"}
|
|
||||||
//updateByIndex(t, t1, 3, "1", r4)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateByIndex(t *testing.T, test interface{}, index int, value, expected interface{}) {
|
func updateByIndex(t *testing.T, test interface{}, index int, value, expected interface{}) {
|
||||||
|
|||||||
@@ -26,11 +26,7 @@ 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(s string) bool {
|
||||||
_, e := strconv.ParseFloat(s, 64)
|
_, e := strconv.ParseFloat(s, 64)
|
||||||
|
return e == nil
|
||||||
if e != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsIntStr check if the string can convert to a integer.
|
// IsIntStr check if the string can convert to a integer.
|
||||||
@@ -42,10 +38,7 @@ func IsIntStr(s string) bool {
|
|||||||
// IsIp check if the string is a ip address.
|
// IsIp check if the string is a ip address.
|
||||||
func IsIp(ipstr string) bool {
|
func IsIp(ipstr string) bool {
|
||||||
ip := net.ParseIP(ipstr)
|
ip := net.ParseIP(ipstr)
|
||||||
if ip == nil {
|
return ip != nil
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsIpV4 check if the string is a ipv4 address.
|
// IsIpV4 check if the string is a ipv4 address.
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ func isCreditCard(t *testing.T, source string, expected bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestIsBase64(t *testing.T) {
|
func TestIsBase64(t *testing.T) {
|
||||||
isBase64(t, "aGVsbG8", true)
|
isBase64(t, "aGVsbG8=", true)
|
||||||
isBase64(t, "123456", false)
|
isBase64(t, "123456", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user