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

Compare commits

...

62 Commits

Author SHA1 Message Date
dudaodong
b6815224fd release v1.3.1 2022-08-02 17:52:18 +08:00
dudaodong
5931b882ee doc: update document for system package 2022-07-29 13:33:23 +08:00
dudaodong
f8096e3585 doc: update slice document 2022-07-29 13:31:04 +08:00
dudaodong
979381bfb7 doc: update convertor document 2022-07-29 13:28:25 +08:00
dudaodong
3e2c25f827 doc: update netutil document 2022-07-29 13:23:30 +08:00
dudaodong
2c7bcc9fbb doc: update slice document 2022-07-29 13:17:05 +08:00
dudaodong
3a944ab12f test: update slice unit test 2022-07-27 15:31:12 +08:00
dudaodong
387079d034 feat: os.go, add GetOsBits 2022-07-27 15:27:39 +08:00
dudaodong
33e3631b72 fix: fix aes/des cbc crypto iv bug 2022-07-27 15:26:45 +08:00
dudaodong
b3149ea619 feat: convertor.go, add ToChannel 2022-07-27 15:22:43 +08:00
dudaodong
116ff284c3 feat: net.go, add IsInternalIP, GetRequestPublicIp, EncodeUrl 2022-07-27 15:18:20 +08:00
dudaodong
0cb251f7b8 feat: add ToSlice and ToSlicePointer and AppendIfAbsent 2022-07-27 15:12:14 +08:00
dudaodong
683def2242 docs: update go version badge 2022-06-24 09:41:46 +08:00
dudaodong
d4a90f2869 release v1.3.0 2022-06-22 16:30:45 +08:00
dudaodong
be67de3b40 release v1.3.0 2022-06-22 15:58:41 +08:00
dudaodong
6898ed413e docs: add doc for UniqueBy function 2022-06-22 15:47:48 +08:00
dudaodong
5dbdbcd651 docs: add doc for UniqueBy function 2022-06-22 15:45:29 +08:00
dudaodong
ae0facd32d refactor: clean code for slice/slice.go 2022-06-22 14:21:45 +08:00
dudaodong
2d7e19fb87 feat: add UniqueBy function in slice.go 2022-06-22 12:00:01 +08:00
dudaodong
24d4a03227 update .gitignore file 2022-06-22 11:27:31 +08:00
dudaodong
93fb089f6e docs: add CreateDir function for fileutil 2022-06-17 17:25:16 +08:00
dudaodong
2fe272f2ef docs: add CreateDir function for fileutil 2022-06-17 17:22:08 +08:00
dudaodong
77859ffa15 docs: add doc for SplitEx function 2022-06-17 17:19:59 +08:00
dudaodong
f83f47df3a feat: add SplitEx function 2022-06-17 17:13:58 +08:00
dudaodong
885c08847d docs: add doc for function IndexOf and LastIndexOf 2022-06-17 17:11:09 +08:00
dudaodong
cc4a20751f test: add unit test for funcation IndexOf and LastIndexOf 2022-06-17 17:02:44 +08:00
dudaodong
b0d1d39452 feat: add IndexOf and LastIndexOf function in slice.go 2022-06-17 17:01:37 +08:00
dudaodong
02fa7bc8be docs: add doc for function Equal and EqualWithFunc 2022-06-17 16:57:42 +08:00
dudaodong
433eb63b86 feat: add EqualWith function for slice 2022-06-17 15:47:36 +08:00
dudaodong
a2541dac03 feat: add Equal function for slice 2022-06-17 15:37:36 +08:00
dudaodong
690e746811 update readme file 2022-04-29 14:50:29 +08:00
dudaodong
7cb97a26c5 release v1.2.9 2022-04-14 11:41:46 +08:00
dudaodong
39d373d37b fix: fix http post to support multipart/form-data header 2022-04-14 11:39:21 +08:00
dudaodong
1aefd6aa12 release v1.2.8 2022-04-13 11:46:14 +08:00
dudaodong
c7aa44b8a4 fix: fix http post fucntion 2022-04-13 11:38:45 +08:00
dudaodong
0e3dc68de5 release v1.2.7 2022-03-29 10:52:55 +08:00
dudaodong
4083e75ed4 fix: fix ToBytes bug 2022-03-26 21:09:28 +08:00
dudaodong
1327eff62f docs: add doc for unix time 2022-03-24 16:09:19 +08:00
dudaodong
eb24c37143 docs: add doc for unix time 2022-03-24 16:07:17 +08:00
dudaodong
b7a6c91064 feat: add unix date conversion 2022-03-24 16:03:57 +08:00
dudaodong
555e185871 feat: add unix date conversion 2022-03-24 16:01:41 +08:00
dudaodong
cb0efc5cc7 docs: replace path '/main' with '/v1' 2022-03-16 16:18:28 +08:00
dudaodong
7ac6816532 docs: add Factorial 2022-03-04 17:37:49 +08:00
dudaodong
81c4216699 release v1.2.6 2022-03-04 17:31:38 +08:00
dudaodong
2e30389703 test: add TestTruncRound 2022-03-04 17:30:47 +08:00
dudaodong
0e1d5cf04b docs: add doc for mathutil package 2022-03-04 17:28:53 +08:00
dudaodong
4e2d84e4fc feat: add mathutil package 2022-03-03 15:55:36 +08:00
dudaodong
13ee045b99 docs: add section 'How to Contribute' 2022-03-01 14:55:42 +08:00
dudaodong
f1fd4c876b fmt: gofmt function.go 2022-02-28 10:11:07 +08:00
dudaodong
cd63b2b18f docs: add func UUIdV4 in readme file 2022-02-28 10:09:23 +08:00
dudaodong
bab9b4a6b3 release v1.2.5 2022-02-25 16:39:03 +08:00
dudaodong
b3c34578bf fix: set request body content-length 2022-02-25 16:38:32 +08:00
dudaodong
f26477904e refactor: set body byte for http post request 2022-02-25 15:31:39 +08:00
dudaodong
85886cf618 docs: add func UUIdV4 2022-02-20 11:09:51 +08:00
dudaodong
a19a861552 feat: add func UUIdV4 2022-02-20 10:16:15 +08:00
dudaodong
96d57a6d24 docs: remove duplicated 2022-02-19 21:53:27 +08:00
dudaodong
b48155c249 refactor: rename files *_util.go to *_internal.go 2022-02-19 21:52:10 +08:00
dudaodong
41685022c0 refactor: rename files *_util.go to *_internal.go 2022-02-19 21:51:58 +08:00
dudaodong
4e7274ce05 fix: check fn param must be function 2022-02-17 19:51:52 +08:00
dudaodong
2384b0e51f docs: fix func link mistake 2022-02-16 14:26:03 +08:00
dudaodong
6b6b938d1e docs: fix func link mistake 2022-02-16 14:24:18 +08:00
dudaodong
29d8987909 docs: update readme file 2022-02-16 14:12:42 +08:00
59 changed files with 2966 additions and 198 deletions

1
.gitignore vendored
View File

@@ -6,4 +6,5 @@ fileutil/*.txt
fileutil/*.zip
fileutil/*.link
fileutil/unzip/*
slice/testdata/*
cryptor/*.pem

View File

@@ -3,8 +3,8 @@
<br/>
![Go version](https://img.shields.io/badge/go-%3E%3D1.16<recommend>-9cf)
[![Release](https://img.shields.io/badge/release-1.2.4-green.svg)](https://github.com/duke-git/lancet/releases)
![Go version](https://img.shields.io/badge/go-v1.16-9cf)
[![Release](https://img.shields.io/badge/release-1.3.1-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)
[![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)
@@ -24,7 +24,7 @@ English | [简体中文](./README_zh-CN.md)
## Feature
- 👏 Comprehensive, efficient and reusable.
- 💪 170+ common go util functions, support string, slice, datetime, net, crypt...
- 💪 200+ go util functions, support string, slice, datetime, net, crypt...
- 💅 Only depend on the go standard library.
- 🌍 Unit test for every exported function.
@@ -62,7 +62,7 @@ func main() {
```
## API Documentation
### Convertor package contains some functions for data convertion.
### 1. Convertor package contains some functions for data convertion.
```go
import "github.com/duke-git/lancet/convertor"
@@ -73,12 +73,13 @@ import "github.com/duke-git/lancet/convertor"
- [ToBool](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToBool)
- [ToBytes](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToBytes)
- [ToChar](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToChar)
- [ToChannel](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToChannel)
- [ToInt](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToInt)
- [ToJson](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToJson)
- [ToString](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToString)
- [StructToMap](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#StructToMap)
### Cryptor package is for data encryption and decryption.
### 2. Cryptor package is for data encryption and decryption.
```go
import "github.com/duke-git/lancet/cryptor"
@@ -118,7 +119,7 @@ import "github.com/duke-git/lancet/cryptor"
- [RsaEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#RsaEncrypt)
- [RsaDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#RsaDecrypt)
### Datetime package supports date and time format and compare.
### 3. Datetime package supports date and time format and compare.
```go
@@ -137,9 +138,9 @@ import "github.com/duke-git/lancet/datetime"
- [EndOfMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfMinute)
- [EndOfHour](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfHour)
- [EndOfDay](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfDay)
- [EndOfWeek](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfWeek)
- [EndOfMonth](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMonth)
- [EndOfYear](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfYear)
- [EndOfWeek](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfWeek)
- [EndOfMonth](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfMonth)
- [EndOfYear](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfYear)
- [GetNowDate](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNowDate)
- [GetNowTime](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNowTime)
- [GetNowDateTime](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNowDateTime)
@@ -147,8 +148,16 @@ import "github.com/duke-git/lancet/datetime"
- [GetNightTimestamp](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNightTimestamp)
- [FormatTimeToStr](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#FormatTimeToStr)
- [FormatStrToTime](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#FormatStrToTime)
- [NewUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewUnix)
- [NewUnixNow](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewUnixNow)
- [NewFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewFormat)
- [NewISO8601](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewISO8601)
- [ToUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToUnix)
- [ToFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToFormat)
- [ToFormatForTpl](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToFormatForTpl)
- [ToIso8601](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToIso8601)
### Fileutil package implements some basic functions for file operations.
### 4. Fileutil package implements some basic functions for file operations.
```go
import "github.com/duke-git/lancet/fileutil"
@@ -158,6 +167,7 @@ import "github.com/duke-git/lancet/fileutil"
- [ClearFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ClearFile)
- [CreateFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#CreateFile)
- [CreateDir](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#CreateDir)
- [CopyFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#CopyFile)
- [FileMode](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#FileMode)
- [MiMeType](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#MiMeType)
@@ -171,7 +181,7 @@ import "github.com/duke-git/lancet/fileutil"
- [Zip](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#Zip)
- [UnZip](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#UnZip)
### Formatter contains some functions for data formatting.
### 5. Formatter contains some functions for data formatting.
```go
import "github.com/duke-git/lancet/formatter"
@@ -192,10 +202,26 @@ import "github.com/duke-git/lancet/function"
- [Compose](https://github.com/duke-git/lancet/blob/main/docs/function.md#Compose)
- [Debounced](https://github.com/duke-git/lancet/blob/main/docs/function.md#Debounced)
- [Delay](https://github.com/duke-git/lancet/blob/main/docs/function.md#Delay)
- [Delay](https://github.com/duke-git/lancet/blob/main/docs/function.md#Delay)
- [Watcher](https://github.com/duke-git/lancet/blob/main/docs/function.md#Watcher)
### Netutil package contains functions to get net information and send http request.
### 6. Mathutil package implements some functions for math calculation.
```go
import "github.com/duke-git/lancet/mathutil"
```
#### Function list:
- [Exponent](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Exponent)
- [Fibonacci](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Fibonacci)
- [Factorial](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Factorial)
- [Percent](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Percent)
- [RoundToFloat](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#RoundToFloat)
- [RoundToString](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#RoundToString)
- [TruncRound](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#TruncRound)
### 7. Netutil package contains functions to get net information and send http request.
```go
import "github.com/duke-git/lancet/netutil"
@@ -203,11 +229,14 @@ import "github.com/duke-git/lancet/netutil"
#### Function list:
- [ConvertMapToQueryString](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#ConvertMapToQueryString)
- [EncodeUrl](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#EncodeUrl)
- [GetInternalIp](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetInternalIp)
- [GetIps](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetIps)
- [GetMacAddrs](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetMacAddrs)
- [GetPublicIpInfo](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetPublicIpInfo)
- [GetRequestPublicIp](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetRequestPublicIp)
- [IsPublicIP](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#IsPublicIP)
- [IsInternalIP](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#IsInternalIP)
- [HttpGet](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpGet)
- [HttpDelete](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpDelete)
- [HttpPost](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPost)
@@ -215,7 +244,7 @@ import "github.com/duke-git/lancet/netutil"
- [HttpPatch](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPatch)
- [ParseHttpResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#ParseHttpResponse)
### Random package implements some basic functions to generate random int and string.
### 8. Random package implements some basic functions to generate random int and string.
```go
import "github.com/duke-git/lancet/random"
@@ -225,8 +254,9 @@ import "github.com/duke-git/lancet/random"
- [RandBytes](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandBytes)
- [RandInt](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandInt)
- [RandString](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandString)
- [UUIdV4](https://github.com/duke-git/lancet/blob/main/docs/random.md#UUIdV4)
### Retry package is for executing a function repeatedly until it was successful or canceled by the context.
### 9. Retry package is for executing a function repeatedly until it was successful or canceled by the context.
```go
import "github.com/duke-git/lancet/retry"
@@ -239,13 +269,14 @@ import "github.com/duke-git/lancet/retry"
- [RetryDuration](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryDuration)
- [RetryTimes](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryTimes)
### Slice contains some functions to manipulate slice.
### 10. Slice contains some functions to manipulate slice.
```go
import "github.com/duke-git/lancet/slice"
```
#### Function list:
- [AppendIfAbsent](https://github.com/duke-git/lancet/blob/main/docs/slice.md#AppendIfAbsent)
- [Contain](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Contain)
- [ContainSubSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ContainSubSlice)
- [Chunk](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Chunk)
@@ -257,13 +288,17 @@ import "github.com/duke-git/lancet/slice"
- [DeleteByIndex](https://github.com/duke-git/lancet/blob/main/docs/slice.md#DeleteByIndex)
- [Drop](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Drop)
- [Every](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Every)
- [Equal](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Equal)
- [EqualWith](https://github.com/duke-git/lancet/blob/main/docs/slice.md#EqualWith)
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Filter)
- [Find](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Find)
- [FindLast](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FindLast)
- [FlattenDeep](#FlattenDeep)
- [FlattenDeep](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FlattenDeep)
- [ForEach](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ForEach)
- [GroupBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#GroupBy)
- [IntSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IntSlice)
- [IndexOf](https://github.com/duke-git/lancet/blob/main/docs/slice.md#IndexOf)
- [LastIndexOf](https://github.com/duke-git/lancet/blob/main/docs/slice.md#LastIndexOf)
- [InterfaceSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#InterfaceSlice)
- [Intersection](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Intersection)
- [InsertByIndex](https://github.com/duke-git/lancet/blob/main/docs/slice.md#InsertByIndex)
@@ -274,12 +309,15 @@ import "github.com/duke-git/lancet/slice"
- [SortByField](https://github.com/duke-git/lancet/blob/main/docs/slice.md#SortByField)
- [Some](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Some)
- [StringSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#StringSlice)
- [ToSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ToSlice)
- [ToSlicePointer](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ToSlice)
- [Unique](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Unique)
- [UniqueBy](https://github.com/duke-git/lancet/blob/main/docs/slice.md#UniqueBy)
- [Union](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Union)
- [UpdateByIndex](https://github.com/duke-git/lancet/blob/main/docs/slice.md#UpdateByIndex)
- [Without](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Without)
### Strutil package contains some functions to manipulate string.
### 11. Strutil package contains some functions to manipulate string.
```go
import "github.com/duke-git/lancet/strutil"
@@ -301,10 +339,11 @@ import "github.com/duke-git/lancet/strutil"
- [PadStart](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#PadStart)
- [ReverseStr](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#ReverseStr)
- [SnakeCase](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SnakeCase)
- [SplitEx](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SplitEx)
- [Wrap](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Wrap)
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Unwrap)
### System package contain some functions about os, runtime, shell command.
### 12. System package contain some functions about os, runtime, shell command.
```go
import "github.com/duke-git/lancet/system"
@@ -319,8 +358,9 @@ import "github.com/duke-git/lancet/system"
- [RemoveOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#RemoveOsEnv)
- [CompareOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system.md#CompareOsEnv)
- [ExecCommand](https://github.com/duke-git/lancet/blob/main/docs/system.md#ExecCommand)
- [GetOsBits](https://github.com/duke-git/lancet/blob/main/docs/system.md#GetOsBits)
### Validator package contains some functions for data validation.
### 13. Validator package contains some functions for data validation.
```go
import "github.com/duke-git/lancet/validator"
@@ -352,4 +392,15 @@ import "github.com/duke-git/lancet/validator"
- [IsIpV6](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsIpV6)
- [IsStrongPassword](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsStrongPassword)
- [IsUrl](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsUrl)
- [IsWeakPassword](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsWeakPassword)
- [IsWeakPassword](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsWeakPassword)
## How to Contribute
I really appreciate any code commits which make lancet lib powerful. Please follow the rules below to create your pull request.
1. Fork the repository.
2. Create your feature branch.
3. Commit your changes.
4. Push to the branch
5. Create new pull request.

View File

@@ -3,8 +3,8 @@
<br/>
![Go version](https://img.shields.io/badge/go-%3E%3D1.16<recommend>-9cf)
[![Release](https://img.shields.io/badge/release-1.2.4-green.svg)](https://github.com/duke-git/lancet/releases)
![Go version](https://img.shields.io/badge/go-v1.16-9cf)
[![Release](https://img.shields.io/badge/release-1.3.1-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)
[![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)
@@ -24,7 +24,7 @@
## 特性
- 👏 全面、高效、可复用
- 💪 170+常用go工具函数支持string、slice、datetime、net、crypt...
- 💪 200+常用go工具函数支持string、slice、datetime、net、crypt...
- 💅 只依赖go标准库
- 🌍 所有导出函数单元测试覆盖率100%
@@ -62,7 +62,7 @@ func main() {
```
## API文档
### convertor转换器包支持一些常见的数据类型转换。
### 1. convertor转换器包支持一些常见的数据类型转换。
```go
import "github.com/duke-git/lancet/convertor"
@@ -73,12 +73,13 @@ import "github.com/duke-git/lancet/convertor"
- [ToBool](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToBool)
- [ToBytes](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToBytes)
- [ToChar](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToChar)
- [ToChannel](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToChannel)
- [ToInt](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToInt)
- [ToJson](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToJson)
- [ToString](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToString)
- [StructToMap](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#StructToMap)
### cryptor加密包支持数据加密和解密获取md5hash值。支持base64, md5, hmac, aes, des, rsa。
### 2. cryptor加密包支持数据加密和解密获取md5hash值。支持base64, md5, hmac, aes, des, rsa。
```go
import "github.com/duke-git/lancet/cryptor"
@@ -118,7 +119,7 @@ import "github.com/duke-git/lancet/cryptor"
- [RsaEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#RsaEncrypt)
- [RsaDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#RsaDecrypt)
### datetime日期时间处理包格式化日期比较日期。
### 3. datetime日期时间处理包格式化日期比较日期。
```go
@@ -137,9 +138,9 @@ import "github.com/duke-git/lancet/datetime"
- [EndOfMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfMinute)
- [EndOfHour](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfHour)
- [EndOfDay](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfDay)
- [EndOfWeek](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfWeek)
- [EndOfMonth](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMonth)
- [EndOfYear](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfYear)
- [EndOfWeek](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfWeek)
- [EndOfMonth](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfMonth)
- [EndOfYear](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfYear)
- [GetNowDate](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNowDate)
- [GetNowTime](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNowTime)
- [GetNowDateTime](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNowDateTime)
@@ -147,8 +148,15 @@ import "github.com/duke-git/lancet/datetime"
- [GetNightTimestamp](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNightTimestamp)
- [FormatTimeToStr](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#FormatTimeToStr)
- [FormatStrToTime](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#FormatStrToTime)
### fileutil包支持文件基本操作。
- [NewUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewUnix)
- [NewUnixNow](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewUnixNow)
- [NewFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewFormat)
- [NewISO8601](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewISO8601)
- [ToUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToUnix)
- [ToFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToFormat)
- [ToFormatForTpl](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToFormatForTpl)
- [ToIso8601](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToIso8601)
### 4. fileutil包支持文件基本操作。
```go
import "github.com/duke-git/lancet/fileutil"
@@ -158,6 +166,7 @@ import "github.com/duke-git/lancet/fileutil"
- [ClearFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ClearFile)
- [CreateFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#CreateFile)
- [CreateDir](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#CreateDir)
- [CopyFile](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#CopyFile)
- [FileMode](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#FileMode)
- [MiMeType](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#MiMeType)
@@ -171,7 +180,7 @@ import "github.com/duke-git/lancet/fileutil"
- [Zip](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#Zip)
- [UnZip](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#UnZip)
### formatter格式化器包含一些数据格式化处理方法。
### 5. formatter格式化器包含一些数据格式化处理方法。
```go
import "github.com/duke-git/lancet/formatter"
@@ -193,11 +202,24 @@ import "github.com/duke-git/lancet/function"
- [Compose](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Compose)
- [Debounced](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Debounced)
- [Delay](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Delay)
- [Delay](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Delay)
- [Watcher](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Watcher)
### 6. mathutil包实现了一些数学计算的函数。
### netutil网络包支持获取ip地址发送http请求。
```go
import "github.com/duke-git/lancet/mathutil"
```
#### Function list:
- [Exponent](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Exponent)
- [Fibonacci](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Fibonacci)
- [Factorial](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Factorial)
- [Percent](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Percent)
- [RoundToFloat](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RoundToFloat)
- [RoundToString](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RoundToString)
- [TruncRound](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#TruncRound)
### 7. netutil网络包支持获取ip地址发送http请求。
```go
import "github.com/duke-git/lancet/netutil"
@@ -205,11 +227,14 @@ import "github.com/duke-git/lancet/netutil"
#### 函数列表:
- [ConvertMapToQueryString](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#ConvertMapToQueryString)
- [EncodeUrl](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#EncodeUrl)
- [GetInternalIp](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetInternalIp)
- [GetIps](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetIps)
- [GetMacAddrs](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetMacAddrs)
- [GetPublicIpInfo](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetPublicIpInfo)
- [GetRequestPublicIp](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetRequestPublicIp)
- [IsPublicIP](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#IsPublicIP)
- [IsInternalIP](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#IsInternalIP)
- [HttpGet](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpGet)
- [HttpDelete](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpDelete)
- [HttpPost](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPost)
@@ -217,7 +242,7 @@ import "github.com/duke-git/lancet/netutil"
- [HttpPatch](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPatch)
- [ParseHttpResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#ParseHttpResponse)
### random随机数生成器包可以生成随机[]bytes, int, string。
### 8. random随机数生成器包可以生成随机[]bytes, int, string。
```go
import "github.com/duke-git/lancet/random"
@@ -227,8 +252,8 @@ import "github.com/duke-git/lancet/random"
- [RandBytes](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandBytes)
- [RandInt](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandInt)
- [RandString](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandString)
### retry重试执行函数直到函数运行成功或被context cancel。
- [UUIdV4](https://github.com/duke-git/lancet/blob/main/docs/random.md#UUIdV4)
### 9. retry重试执行函数直到函数运行成功或被context cancel。
```go
import "github.com/duke-git/lancet/retry"
@@ -242,13 +267,14 @@ import "github.com/duke-git/lancet/retry"
- [RetryTimes](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryTimes)
### slice包包含操作切片的方法集合。
### 10. slice包包含操作切片的方法集合。
```go
import "github.com/duke-git/lancet/slice"
```
#### 函数列表:
- [AppendIfAbsent](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#AppendIfAbsent)
- [Contain](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Contain)
- [ContainSubSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ContainSubSlice)
- [Chunk](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Chunk)
@@ -260,13 +286,17 @@ import "github.com/duke-git/lancet/slice"
- [DeleteByIndex](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#DeleteByIndex)
- [Drop](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Drop)
- [Every](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Every)
- [Equal](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Equal)
- [EqualWith](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#EqualWith)
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Filter)
- [Find](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Find)
- [FindLast](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#FindLast)
- [FlattenDeep](#FlattenDeep)
- [FlattenDeep](https://github.com/duke-git/lancet/blob/main/docs/slice.md#FlattenDeep)
- [ForEach](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ForEach)
- [GroupBy](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#GroupBy)
- [IntSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IntSlice)
- [IndexOf](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#IndexOf)
- [LastIndexOf](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#LastIndexOf)
- [InterfaceSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#InterfaceSlice)
- [Intersection](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Intersection)
- [InsertByIndex](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#InsertByIndex)
@@ -277,13 +307,16 @@ import "github.com/duke-git/lancet/slice"
- [SortByField](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#SortByField)
- [Some](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Some)
- [StringSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#StringSlice)
- [ToSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ToSlice)
- [ToSlicePointer](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ToSlice)
- [Unique](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Unique)
- [UniqueBy](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#UniqueBy)
- [Union](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Union)
- [UpdateByIndex](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#UpdateByIndex)
- [Without](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Without)
### strutil包含处理字符串的相关函数。
### 12. strutil包含处理字符串的相关函数。
```go
import "github.com/duke-git/lancet/strutil"
@@ -305,11 +338,12 @@ import "github.com/duke-git/lancet/strutil"
- [PadStart](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#PadStart)
- [ReverseStr](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#ReverseStr)
- [SnakeCase](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#SnakeCase)
- [SplitEx](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#SplitEx)
- [Wrap](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Wrap)
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Unwrap)
### system包含os, runtime, shell command相关函数。
### 13. system包含os, runtime, shell command相关函数。
```go
import "github.com/duke-git/lancet/system"
@@ -324,8 +358,9 @@ import "github.com/duke-git/lancet/system"
- [RemoveOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#RemoveOsEnv)
- [CompareOsEnv](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#CompareOsEnv)
- [ExecCommand](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#ExecCommand)
- [GetOsBits](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN.md#GetOsBits)
### validator验证器包包含常用字符串格式验证函数。
### 14. validator验证器包包含常用字符串格式验证函数。
```go
import "github.com/duke-git/lancet/validator"
@@ -357,4 +392,15 @@ import "github.com/duke-git/lancet/validator"
- [IsIpV6](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIpV6)
- [IsStrongPassword](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsStrongPassword)
- [IsUrl](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsUrl)
- [IsWeakPassword](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsWeakPassword)
- [IsWeakPassword](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsWeakPassword)
## 如何贡献代码
非常感激任何的代码提交以使lancet的功能越来越强大。创建pull request时请遵守以下规则。
1. Fork lancet仓库。
2. 创建自己的特性分支。
3. 提交变更。
4. Push分支。
5. 创建新的pull request。

View File

@@ -6,9 +6,10 @@ package convertor
import (
"bytes"
"encoding/gob"
"encoding/binary"
"encoding/json"
"fmt"
"math"
"reflect"
"regexp"
"strconv"
@@ -21,14 +22,44 @@ func ToBool(s string) (bool, error) {
}
// ToBytes convert interface to bytes
func ToBytes(data interface{}) ([]byte, error) {
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
err := enc.Encode(data)
if err != nil {
return nil, err
func ToBytes(value interface{}) ([]byte, error) {
v := reflect.ValueOf(value)
switch value.(type) {
case int, int8, int16, int32, int64:
number := v.Int()
buf := bytes.NewBuffer([]byte{})
buf.Reset()
err := binary.Write(buf, binary.BigEndian, number)
return buf.Bytes(), err
case uint, uint8, uint16, uint32, uint64:
number := v.Uint()
buf := bytes.NewBuffer([]byte{})
buf.Reset()
err := binary.Write(buf, binary.BigEndian, number)
return buf.Bytes(), err
case float32:
number := float32(v.Float())
bits := math.Float32bits(number)
bytes := make([]byte, 4)
binary.BigEndian.PutUint32(bytes, bits)
return bytes, nil
case float64:
number := v.Float()
bits := math.Float64bits(number)
bytes := make([]byte, 8)
binary.BigEndian.PutUint64(bytes, bits)
return bytes, nil
case bool:
return strconv.AppendBool([]byte{}, v.Bool()), nil
case string:
return []byte(v.String()), nil
case []byte:
return v.Bytes(), nil
default:
newValue, err := json.Marshal(value)
return newValue, err
}
return buf.Bytes(), nil
}
// ToChar convert string to char slice
@@ -198,3 +229,17 @@ func ColorRGBToHex(red, green, blue int) string {
return "#" + r + g + b
}
// ToChannel convert a array of elements to a read-only channels
func ToChannel(array []interface{}) <-chan interface{} {
ch := make(chan interface{})
go func() {
for _, item := range array {
ch <- item
}
close(ch)
}()
return ch
}

View File

@@ -42,14 +42,21 @@ func TestToBytes(t *testing.T) {
"1",
}
expected := [][]byte{
{3, 4, 0, 0},
{3, 2, 0, 0},
{4, 12, 0, 1, 49},
{0, 0, 0, 0, 0, 0, 0, 0},
{102, 97, 108, 115, 101},
{49},
}
for i := 0; i < len(cases); i++ {
actual, _ := ToBytes(cases[i])
assert.Equal(expected[i], actual)
}
bytesData, err := ToBytes("abc")
if err != nil {
t.Error(err)
t.Fail()
}
assert.Equal("abc", ToString(bytesData))
}
func TestToInt(t *testing.T) {
@@ -171,3 +178,20 @@ func TestColorRGBToHex(t *testing.T) {
assert := internal.NewAssert(t, "TestColorRGBToHex")
assert.Equal(expected, colorHex)
}
func TestToChannel(t *testing.T) {
assert := internal.NewAssert(t, "TestToChannel")
ch := ToChannel([]interface{}{1, 2, 3})
val1, _ := <-ch
assert.Equal(1, val1)
val2, _ := <-ch
assert.Equal(2, val2)
val3, _ := <-ch
assert.Equal(3, val3)
_, ok := <-ch
assert.Equal(false, ok)
}

View File

@@ -54,14 +54,18 @@ func AesEcbDecrypt(encrypted, key []byte) []byte {
// AesCbcEncrypt encrypt data with key use AES CBC algorithm
// len(key) should be 16, 24 or 32
func AesCbcEncrypt(data, key []byte) []byte {
// len(key) should be 16, 24 or 32
block, _ := aes.NewCipher(key)
blockSize := block.BlockSize()
data = pkcs7Padding(data, blockSize)
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
data = pkcs7Padding(data, block.BlockSize())
encrypted := make([]byte, aes.BlockSize+len(data))
iv := encrypted[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(encrypted[aes.BlockSize:], data)
encrypted := make([]byte, len(data))
blockMode.CryptBlocks(encrypted, data)
return encrypted
}
@@ -69,12 +73,14 @@ func AesCbcEncrypt(data, key []byte) []byte {
// len(key) should be 16, 24 or 32
func AesCbcDecrypt(encrypted, key []byte) []byte {
block, _ := aes.NewCipher(key)
blockSize := block.BlockSize()
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
decrypted := make([]byte, len(encrypted))
blockMode.CryptBlocks(decrypted, encrypted)
decrypted = pkcs7UnPadding(decrypted)
iv := encrypted[:aes.BlockSize]
encrypted = encrypted[aes.BlockSize:]
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(encrypted, encrypted)
decrypted := pkcs7UnPadding(encrypted)
return decrypted
}

View File

@@ -55,12 +55,16 @@ func DesEcbDecrypt(encrypted, key []byte) []byte {
// len(key) should be 8
func DesCbcEncrypt(data, key []byte) []byte {
block, _ := des.NewCipher(key)
blockSize := block.BlockSize()
data = pkcs7Padding(data, blockSize)
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
data = pkcs7Padding(data, block.BlockSize())
encrypted := make([]byte, len(data))
blockMode.CryptBlocks(encrypted, data)
encrypted := make([]byte, des.BlockSize+len(data))
iv := encrypted[:des.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(encrypted[des.BlockSize:], data)
return encrypted
}
@@ -69,13 +73,14 @@ func DesCbcEncrypt(data, key []byte) []byte {
// len(key) should be 8
func DesCbcDecrypt(encrypted, key []byte) []byte {
block, _ := des.NewCipher(key)
blockSize := block.BlockSize()
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
decrypted := make([]byte, len(encrypted))
blockMode.CryptBlocks(decrypted, encrypted)
decrypted = pkcs7UnPadding(decrypted)
iv := encrypted[:des.BlockSize]
encrypted = encrypted[des.BlockSize:]
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(encrypted, encrypted)
decrypted := pkcs7UnPadding(encrypted)
return decrypted
}

60
datetime/conversion.go Normal file
View File

@@ -0,0 +1,60 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license.
package datetime
import "time"
type theTime struct {
unix int64
}
// NewUnixNow return unix timestamp of current time
func NewUnixNow() *theTime {
return &theTime{unix: time.Now().Unix()}
}
// NewUnix return unix timestamp of specified time
func NewUnix(unix int64) *theTime {
return &theTime{unix: unix}
}
// NewFormat return unix timestamp of specified time string, t should be "yyyy-mm-dd hh:mm:ss"
func NewFormat(t string) (*theTime, error) {
timeLayout := "2006-01-02 15:04:05"
loc := time.FixedZone("CST", 8*3600)
tt, err := time.ParseInLocation(timeLayout, t, loc)
if err != nil {
return nil, err
}
return &theTime{unix: tt.Unix()}, nil
}
// NewISO8601 return unix timestamp of specified iso8601 time string
func NewISO8601(iso8601 string) (*theTime, error) {
t, err := time.ParseInLocation(time.RFC3339, iso8601, time.UTC)
if err != nil {
return nil, err
}
return &theTime{unix: t.Unix()}, nil
}
// ToUnix return unix timestamp
func (t *theTime) ToUnix() int64 {
return t.unix
}
// ToFormat return the time string 'yyyy-mm-dd hh:mm:ss' of unix time
func (t *theTime) ToFormat() string {
return time.Unix(t.unix, 0).Format("2006-01-02 15:04:05")
}
// ToFormatForTpl return the time string which format is specified tpl
func (t *theTime) ToFormatForTpl(tpl string) string {
return time.Unix(t.unix, 0).Format(tpl)
}
// ToFormatForTpl return iso8601 time string
func (t *theTime) ToIso8601() string {
return time.Unix(t.unix, 0).Format(time.RFC3339)
}

View File

@@ -0,0 +1,54 @@
package datetime
import (
"testing"
"github.com/duke-git/lancet/internal"
)
func TestToUnix(t *testing.T) {
assert := internal.NewAssert(t, "TestToUnix")
tm1 := NewUnixNow()
unixTimestamp := tm1.ToUnix()
tm2 := NewUnix(unixTimestamp)
assert.Equal(tm1, tm2)
}
func TestToFormat(t *testing.T) {
assert := internal.NewAssert(t, "TestToFormat")
tm, err := NewFormat("2022/03/18 17:04:05")
assert.IsNotNil(err)
tm, err = NewFormat("2022-03-18 17:04:05")
assert.IsNil(err)
t.Log("ToFormat -> ", tm.ToFormat())
}
func TestToFormatForTpl(t *testing.T) {
assert := internal.NewAssert(t, "TestToFormatForTpl")
tm, err := NewFormat("2022/03/18 17:04:05")
assert.IsNotNil(err)
tm, err = NewFormat("2022-03-18 17:04:05")
assert.IsNil(err)
t.Log("ToFormatForTpl -> ", tm.ToFormatForTpl("2006/01/02 15:04:05"))
}
func TestToIso8601(t *testing.T) {
assert := internal.NewAssert(t, "TestToIso8601")
tm, err := NewISO8601("2022-03-18 17:04:05")
assert.IsNotNil(err)
tm, err = NewISO8601("2006-01-02T15:04:05.999Z")
assert.IsNil(err)
t.Log("ToIso8601 -> ", tm.ToIso8601())
}

View File

@@ -5,7 +5,7 @@ Package convertor contains some functions for data type convertion.
## Source:
[https://github.com/duke-git/lancet/blob/main/convertor/convertor.go](https://github.com/duke-git/lancet/blob/main/convertor/convertor.go)
[https://github.com/duke-git/lancet/blob/v1/convertor/convertor.go](https://github.com/duke-git/lancet/blob/v1/convertor/convertor.go)
<div STYLE="page-break-after: always;"></div>
@@ -24,6 +24,7 @@ import (
- [ToBool](#ToBool)
- [ToBytes](#ToBytes)
- [ToChar](#ToChar)
- [ToChannel](#ToChannel)
- [ToInt](#ToInt)
- [ToJson](#ToJson)
- [ToString](#ToString)
@@ -191,6 +192,43 @@ func main() {
```
### <span id="ToChannel">ToChannel</span>
<p>Convert a collection of elements to a read-only channels.</p>
<b>Signature:</b>
```go
func ToChannel(array []interface{}) <-chan interface{}
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/convertor"
)
func main() {
ch := convertor.ToChannel([]int{1, 2, 3})
val1, _ := <-ch
fmt.Println(val1) //1
val2, _ := <-ch
fmt.Println(val2) //2
val3, _ := <-ch
fmt.Println(val3) //3
_, ok := <-ch
fmt.Println(ok) //false
}
```
### <span id="ToFloat">ToFloat</span>

View File

@@ -5,7 +5,7 @@ convertor转换器包支持一些常见的数据类型转换
## 源码:
[https://github.com/duke-git/lancet/blob/main/convertor/convertor.go](https://github.com/duke-git/lancet/blob/main/convertor/convertor.go)
[https://github.com/duke-git/lancet/blob/v1/convertor/convertor.go](https://github.com/duke-git/lancet/blob/v1/convertor/convertor.go)
<div STYLE="page-break-after: always;"></div>
@@ -26,6 +26,7 @@ import (
- [ToBool](#ToBool)
- [ToBytes](#ToBytes)
- [ToChar](#ToChar)
- [ToChannel](#ToChannel)
- [ToInt](#ToInt)
- [ToJson](#ToJson)
- [ToString](#ToString)
@@ -194,6 +195,44 @@ func main() {
### <span id="ToChannel">ToChannel</span>
<p>将切片转为只读channel</p>
<b>函数签名:</b>
```go
func ToChannel(array []interface{}) <-chan interface{}
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
ch := convertor.ToChannel([]int{1, 2, 3})
val1, _ := <-ch
fmt.Println(val1) //1
val2, _ := <-ch
fmt.Println(val2) //2
val3, _ := <-ch
fmt.Println(val3) //3
_, ok := <-ch
fmt.Println(ok) //false
}
```
### <span id="ToFloat">ToFloat</span>
<p>将interface转成float64类型如果参数无法转换会返回0和error</p>

View File

@@ -5,10 +5,10 @@ Package cryptor contains some functions for data encryption and decryption. Supp
## Source:
- [https://github.com/duke-git/lancet/blob/main/cryptor/aes.go](https://github.com/duke-git/lancet/blob/main/cryptor/aes.go)
- [https://github.com/duke-git/lancet/blob/main/cryptor/des.go](https://github.com/duke-git/lancet/blob/main/cryptor/des.go)
- [https://github.com/duke-git/lancet/blob/main/cryptor/basic.go](https://github.com/duke-git/lancet/blob/main/cryptor/basic.go)
- [https://github.com/duke-git/lancet/blob/main/cryptor/rsa.go](https://github.com/duke-git/lancet/blob/main/cryptor/rsa.go)
- [https://github.com/duke-git/lancet/blob/v1/cryptor/aes.go](https://github.com/duke-git/lancet/blob/v1/cryptor/aes.go)
- [https://github.com/duke-git/lancet/blob/v1/cryptor/des.go](https://github.com/duke-git/lancet/blob/v1/cryptor/des.go)
- [https://github.com/duke-git/lancet/blob/v1/cryptor/basic.go](https://github.com/duke-git/lancet/blob/v1/cryptor/basic.go)
- [https://github.com/duke-git/lancet/blob/v1/cryptor/rsa.go](https://github.com/duke-git/lancet/blob/v1/cryptor/rsa.go)
<div STYLE="page-break-after: always;"></div>

View File

@@ -5,10 +5,10 @@ cryptor加密包支持数据加密和解密获取md5hash值。支持base64
## 源码:
- [https://github.com/duke-git/lancet/blob/main/cryptor/aes.go](https://github.com/duke-git/lancet/blob/main/cryptor/aes.go)
- [https://github.com/duke-git/lancet/blob/main/cryptor/des.go](https://github.com/duke-git/lancet/blob/main/cryptor/des.go)
- [https://github.com/duke-git/lancet/blob/main/cryptor/basic.go](https://github.com/duke-git/lancet/blob/main/cryptor/basic.go)
- [https://github.com/duke-git/lancet/blob/main/cryptor/rsa.go](https://github.com/duke-git/lancet/blob/main/cryptor/rsa.go)
- [https://github.com/duke-git/lancet/blob/v1/cryptor/aes.go](https://github.com/duke-git/lancet/blob/v1/cryptor/aes.go)
- [https://github.com/duke-git/lancet/blob/v1/cryptor/des.go](https://github.com/duke-git/lancet/blob/v1/cryptor/des.go)
- [https://github.com/duke-git/lancet/blob/v1/cryptor/basic.go](https://github.com/duke-git/lancet/blob/v1/cryptor/basic.go)
- [https://github.com/duke-git/lancet/blob/v1/cryptor/rsa.go](https://github.com/duke-git/lancet/blob/v1/cryptor/rsa.go)
<div STYLE="page-break-after: always;"></div>

View File

@@ -5,7 +5,7 @@ Package datetime supports date and time format and compare.
## Source:
[https://github.com/duke-git/lancet/blob/main/datetime/datetime.go](https://github.com/duke-git/lancet/blob/main/datetime/datetime.go)
[https://github.com/duke-git/lancet/blob/v1/datetime/datetime.go](https://github.com/duke-git/lancet/blob/v1/datetime/datetime.go)
<div STYLE="page-break-after: always;"></div>
@@ -32,9 +32,9 @@ import (
- [EndOfMinute](#EndOfMinute)
- [EndOfHour](#EndOfHour)
- [EndOfDay](#EndOfDay)
- [EndOfWeek](#BeginOfWeek)
- [EndOfMonth](#BeginOfMonth)
- [EndOfYear](#BeginOfYear)
- [EndOfWeek](#EndOfWeek)
- [EndOfMonth](#EndOfMonth)
- [EndOfYear](#EndOfYear)
- [GetNowDate](#GetNowDate)
- [GetNowTime](#GetNowTime)
- [GetNowDateTime](#GetNowDateTime)
@@ -43,6 +43,14 @@ import (
- [FormatTimeToStr](#FormatTimeToStr)
- [FormatStrToTime](#FormatStrToTime)
- [NewUnixNow](#NewUnixNow)
- [NewUnix](#NewUnix)
- [NewFormat](#NewFormat)
- [NewISO8601](#NewISO8601)
- [ToUnix](#ToUnix)
- [ToFormat](#ToFormat)
- [ToFormatForTpl](#ToFormatForTpl)
- [ToIso8601](#ToIso8601)
<div STYLE="page-break-after: always;"></div>
@@ -263,7 +271,7 @@ func main() {
### <span id="BeginOfMonth">BeginOfWeek</span>
### <span id="BeginOfMonth">BeginOfMonth</span>
<p>Return beginning time of month</p>
<b>Signature:</b>
@@ -667,3 +675,221 @@ func main() {
### <span id="NewUnixNow">NewUnixNow</span>
<p>Return unix timestamp of current time</p>
<b>Signature:</b>
```go
type theTime struct {
unix int64
}
func NewUnixNow() *theTime
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm := datetime.NewUnixNow()
fmt.Println(tm) //&{1647597438}
}
```
### <span id="NewUnix">NewUnix</span>
<p>Return unix timestamp of specified int64 value.</p>
<b>Signature:</b>
```go
type theTime struct {
unix int64
}
func NewUnix(unix int64) *theTime
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm := datetime.NewUnix(1647597438)
fmt.Println(tm) //&{1647597438}
}
```
### <span id="NewFormat">NewFormat</span>
<p>Return unix timestamp of specified time string, t should be "yyyy-mm-dd hh:mm:ss".</p>
<b>Signature:</b>
```go
type theTime struct {
unix int64
}
func NewFormat(t string) (*theTime, error)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, err := datetime.NewFormat("2022-03-18 17:04:05")
fmt.Println(tm) //&{1647594245}
}
```
### <span id="NewISO8601">NewISO8601</span>
<p>Return unix timestamp of specified iso8601 time string.</p>
<b>Signature:</b>
```go
type theTime struct {
unix int64
}
func NewISO8601(iso8601 string) (*theTime, error)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, err := datetime.NewISO8601("2006-01-02T15:04:05.999Z")
fmt.Println(tm) //&{1136214245}
}
```
### <span id="ToUnix">ToUnix</span>
<p>Return unix timestamp.</p>
<b>Signature:</b>
```go
func (t *theTime) ToUnix() int64
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm := datetime.NewUnixNow()
fmt.Println(tm.ToUnix()) //1647597438
}
```
### <span id="ToFormat">ToFormat</span>
<p>Return time string 'yyyy-mm-dd hh:mm:ss'.</p>
<b>Signature:</b>
```go
func (t *theTime) ToFormat() string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, _ := datetime.NewFormat("2022-03-18 17:04:05")
fmt.Println(tm.ToFormat()) //"2022-03-18 17:04:05"
}
```
### <span id="ToFormatForTpl">ToFormatForTpl</span>
<p>Return the time string which format is specified tpl.</p>
<b>Signature:</b>
```go
func (t *theTime) ToFormatForTpl(tpl string) string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, _ := datetime.NewFormat("2022-03-18 17:04:05")
ts := tm.ToFormatForTpl("2006/01/02 15:04:05")
fmt.Println(ts) //"2022/03/18 17:04:05"
}
```
### <span id="ToIso8601">ToIso8601</span>
<p>Return iso8601 time string.</p>
<b>Signature:</b>
```go
func (t *theTime) ToIso8601() string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, _ := datetime.NewISO8601("2006-01-02T15:04:05.999Z")
ts := tm.ToIso8601()
fmt.Println(ts) //"2006-01-02T23:04:05+08:00"
}
```

View File

@@ -5,7 +5,7 @@ datetime日期时间处理包格式化日期比较日期。
## 源码:
[https://github.com/duke-git/lancet/blob/main/datetime/datetime.go](https://github.com/duke-git/lancet/blob/main/datetime/datetime.go)
[https://github.com/duke-git/lancet/blob/v1/datetime/datetime.go](https://github.com/duke-git/lancet/blob/v1/datetime/datetime.go)
<div STYLE="page-break-after: always;"></div>
@@ -22,14 +22,34 @@ import (
- [AddDay](#AddDay)
- [AddHour](#AddHour)
- [AddMinute](#AddMinute)
- [BeginOfMinute](#BeginOfMinute)
- [BeginOfHour](#BeginOfHour)
- [BeginOfDay](#BeginOfDay)
- [BeginOfWeek](#BeginOfWeek)
- [BeginOfMonth](#BeginOfMonth)
- [BeginOfYear](#BeginOfYear)
- [EndOfMinute](#EndOfMinute)
- [EndOfHour](#EndOfHour)
- [EndOfDay](#EndOfDay)
- [EndOfWeek](#EndOfWeek)
- [EndOfMonth](#EndOfMonth)
- [EndOfYear](#EndOfYear)
- [GetNowDate](#GetNowDate)
- [GetNowTime](#GetNowTime)
- [GetNowDateTime](#GetNowDateTime)
- [GetZeroHourTimestamp](#GetZeroHourTimestamp)
- [GetNightTimestamp](#GetNightTimestamp)
- [FormatTimeToStr](#FormatTimeToStr)
- [FormatStrToTime](#FormatStrToTime)
- [NewUnixNow](#NewUnixNow)
- [NewUnix](#NewUnix)
- [NewFormat](#NewFormat)
- [NewISO8601](#NewISO8601)
- [ToUnix](#ToUnix)
- [ToFormat](#ToFormat)
- [ToFormatForTpl](#ToFormatForTpl)
- [ToIso8601](#ToIso8601)
<div STYLE="page-break-after: always;"></div>
@@ -250,7 +270,7 @@ func main() {
### <span id="BeginOfMonth">BeginOfWeek</span>
### <span id="BeginOfMonth">BeginOfMonth</span>
<p>返回指定时间的当月开始时间</p>
<b>函数签名:</b>
@@ -654,3 +674,222 @@ func main() {
### <span id="NewUnixNow">NewUnixNow</span>
<p>创建一个当前时间的unix时间戳</p>
<b>函数签名:</b>
```go
type theTime struct {
unix int64
}
func NewUnixNow() *theTime
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm := datetime.NewUnixNow()
fmt.Println(tm) //&{1647597438}
}
```
### <span id="NewUnix">NewUnix</span>
<p>创建一个unix时间戳</p>
<b>函数签名:</b>
```go
type theTime struct {
unix int64
}
func NewUnix(unix int64) *theTime
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm := datetime.NewUnix(1647597438)
fmt.Println(tm) //&{1647597438}
}
```
### <span id="NewFormat">NewFormat</span>
<p>创建一个yyyy-mm-dd hh:mm:ss格式时间字符串的unix时间戳</p>
<b>函数签名:</b>
```go
type theTime struct {
unix int64
}
func NewFormat(t string) (*theTime, error)
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, err := datetime.NewFormat("2022-03-18 17:04:05")
fmt.Println(tm) //&{1647594245}
}
```
### <span id="NewISO8601">NewISO8601</span>
<p>创建一个iso8601格式时间字符串的unix时间戳</p>
<b>函数签名:</b>
```go
type theTime struct {
unix int64
}
func NewISO8601(iso8601 string) (*theTime, error)
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, err := datetime.NewISO8601("2006-01-02T15:04:05.999Z")
fmt.Println(tm) //&{1136214245}
}
```
### <span id="ToUnix">ToUnix</span>
<p>返回unix时间戳</p>
<b>函数签名:</b>
```go
func (t *theTime) ToUnix() int64
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm := datetime.NewUnixNow()
fmt.Println(tm.ToUnix()) //1647597438
}
```
### <span id="ToFormat">ToFormat</span>
<p>返回格式'yyyy-mm-dd hh:mm:ss'的日期字符串</p>
<b>函数签名:</b>
```go
func (t *theTime) ToFormat() string
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, _ := datetime.NewFormat("2022-03-18 17:04:05")
fmt.Println(tm.ToFormat()) //"2022-03-18 17:04:05"
}
```
### <span id="ToFormatForTpl">ToFormatForTpl</span>
<p>返回tpl格式指定的日期字符串</p>
<b>函数签名:</b>
```go
func (t *theTime) ToFormatForTpl(tpl string) string
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, _ := datetime.NewFormat("2022-03-18 17:04:05")
ts := tm.ToFormatForTpl("2006/01/02 15:04:05")
fmt.Println(ts) //"2022/03/18 17:04:05"
}
```
### <span id="ToIso8601">ToIso8601</span>
<p>返回iso8601日期字符串</p>
<b>函数签名:</b>
```go
func (t *theTime) ToIso8601() string
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
tm, _ := datetime.NewISO8601("2006-01-02T15:04:05.999Z")
ts := tm.ToIso8601()
fmt.Println(ts) //"2006-01-02T23:04:05+08:00"
}
```

View File

@@ -5,7 +5,7 @@ Package fileutil implements some basic functions for file operations.
## Source:
[https://github.com/duke-git/lancet/blob/main/fileutil/file.go](https://github.com/duke-git/lancet/blob/main/fileutil/file.go)
[https://github.com/duke-git/lancet/blob/v1/fileutil/file.go](https://github.com/duke-git/lancet/blob/v1/fileutil/file.go)
<div STYLE="page-break-after: always;"></div>
@@ -21,6 +21,8 @@ import (
## Index
- [ClearFile](#ClearFile)
- [CreateFile](#CreateFile)
- [CreateDir](#CreateDir)
- [CopyFile](#CopyFile)
- [FileMode](#FileMode)
- [MiMeType](#MiMeType)
@@ -32,7 +34,6 @@ import (
- [ReadFileToString](#ReadFileToString)
- [ReadFileByLine](#ReadFileByLine)
- [Zip](#Zip)
- [UnZip](#UnZip)
<div STYLE="page-break-after: always;"></div>
@@ -67,6 +68,34 @@ func main() {
}
```
### <span id="CreateDir">CreateDir</span>
<p>Create directory in absolute path. param `absPath` like /a/, /a/b/.</p>
<b>Signature:</b>
```go
func CreateDir(absPath string) error
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
)
func main() {
err := fileutil.CreateDir("/a/")
fmt.Println(err)
}
```
### <span id="CreateFile">CreateFile</span>
<p>Create file in path. return true if create succeed.</p>

View File

@@ -5,7 +5,7 @@ fileutil包支持文件基本操作。
## 源码:
[https://github.com/duke-git/lancet/blob/main/fileutil/file.go](https://github.com/duke-git/lancet/blob/main/fileutil/file.go)
[https://github.com/duke-git/lancet/blob/v1/fileutil/file.go](https://github.com/duke-git/lancet/blob/v1/fileutil/file.go)
<div STYLE="page-break-after: always;"></div>
@@ -21,6 +21,7 @@ import (
## 目录
- [ClearFile](#ClearFile)
- [CreateFile](#CreateFile)
- [CreateDir](#CreateDir)
- [CopyFile](#CopyFile)
- [FileMode](#FileMode)
- [MiMeType](#MiMeType)
@@ -67,6 +68,33 @@ func main() {
}
```
### <span id="CreateDir">CreateDir</span>
<p>使用绝对路径创建嵌套目录,例如/a/, /a/b/</p>
<b>函数签名:</b>
```go
func CreateDir(absPath string) error
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/fileutil"
)
func main() {
err := fileutil.CreateDir("/a/")
fmt.Println(err)
}
```
### <span id="CreateFile">CreateFile</span>
<p>创建文件创建成功返回true, 否则返回false</p>

View File

@@ -5,7 +5,7 @@ formatter contains some functions for data formatting.
## Source:
[https://github.com/duke-git/lancet/blob/main/formatter/formatter.go](https://github.com/duke-git/lancet/blob/main/formatter/formatter.go)
[https://github.com/duke-git/lancet/blob/v1/formatter/formatter.go](https://github.com/duke-git/lancet/blob/v1/formatter/formatter.go)
<div STYLE="page-break-after: always;"></div>

View File

@@ -5,7 +5,7 @@ formatter格式化器包含一些数据格式化处理方法。
## 源码:
[https://github.com/duke-git/lancet/blob/main/formatter/formatter.go](https://github.com/duke-git/lancet/blob/main/formatter/formatter.go)
[https://github.com/duke-git/lancet/blob/v1/formatter/formatter.go](https://github.com/duke-git/lancet/blob/v1/formatter/formatter.go)
<div STYLE="page-break-after: always;"></div>

View File

@@ -5,8 +5,8 @@ Package function can control the flow of function execution and support part of
## Source:
[https://github.com/duke-git/lancet/blob/main/function/function.go](https://github.com/duke-git/lancet/blob/main/function/function.go)
[https://github.com/duke-git/lancet/blob/main/function/watcher.go](https://github.com/duke-git/lancet/blob/main/function/watcher.go)
[https://github.com/duke-git/lancet/blob/v1/function/function.go](https://github.com/duke-git/lancet/blob/v1/function/function.go)
[https://github.com/duke-git/lancet/blob/v1/function/watcher.go](https://github.com/duke-git/lancet/blob/v1/function/watcher.go)
<div STYLE="page-break-after: always;"></div>
@@ -26,7 +26,6 @@ import (
- [Compose](#Compose)
- [Debounced](#Debounced)
- [Delay](#Delay)
- [Delay](#Delay)
- [Watcher](#Watcher)
<div STYLE="page-break-after: always;"></div>

View File

@@ -5,8 +5,8 @@ function函数包控制函数执行流程包含部分函数式编程。
## 源码:
[https://github.com/duke-git/lancet/blob/main/function/function.go](https://github.com/duke-git/lancet/blob/main/function/function.go)
[https://github.com/duke-git/lancet/blob/main/function/watcher.go](https://github.com/duke-git/lancet/blob/main/function/watcher.go)
[https://github.com/duke-git/lancet/blob/v1/function/function.go](https://github.com/duke-git/lancet/blob/v1/function/function.go)
[https://github.com/duke-git/lancet/blob/v1/function/watcher.go](https://github.com/duke-git/lancet/blob/v1/function/watcher.go)
<div STYLE="page-break-after: always;"></div>
@@ -26,7 +26,6 @@ import (
- [Compose](#Compose)
- [Debounced](#Debounced)
- [Delay](#Delay)
- [Delay](#Delay)
- [Watcher](#Watcher)
<div STYLE="page-break-after: always;"></div>

233
docs/mathutil.md Normal file
View File

@@ -0,0 +1,233 @@
# Mathutil
Package mathutil implements some functions for math calculation.
<div STYLE="page-break-after: always;"></div>
## Source:
[https://github.com/duke-git/lancet/blob/v1/mathutil/mathutil.go](https://github.com/duke-git/lancet/blob/v1/mathutil/mathutil.go)
<div STYLE="page-break-after: always;"></div>
## Example:
```go
import (
"github.com/duke-git/lancet/mathutil"
)
```
<div STYLE="page-break-after: always;"></div>
## Index
- [Exponent](#Exponent)
- [Fibonacci](#Fibonacci)
- [Factorial](#Factorial)
- [Percent](#Percent)
- [RoundToFloat](#RoundToFloat)
- [RoundToString](#RoundToString)
- [TruncRound](#TruncRound)
<div STYLE="page-break-after: always;"></div>
## Documentation
### <span id="Exponent">Exponent</span>
<p>Calculate x to the nth power.</p>
<b>Signature:</b>
```go
func Exponent(x, n int64) int64
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
)
func main() {
fmt.Println(mathutil.Exponent(10, 0)) //1
fmt.Println(mathutil.Exponent(10, 1)) //10
fmt.Println(mathutil.Exponent(10, 2)) //100
}
```
### <span id="Fibonacci">Fibonacci</span>
<p>Calculate the nth number of fibonacci sequence.</p>
<b>Signature:</b>
```go
func Fibonacci(first, second, n int) int
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
)
func main() {
fmt.Println(mathutil.Fibonacci(1, 1, 1)) //1
fmt.Println(mathutil.Fibonacci(1, 1, 2)) //1
fmt.Println(mathutil.Fibonacci(1, 1, 3)) //2
fmt.Println(mathutil.Fibonacci(1, 1, 4)) //3
fmt.Println(mathutil.Fibonacci(1, 1, 5)) //5
}
```
### <span id="Factorial">Factorial</span>
<p>Calculate the factorial of x.</p>
<b>Signature:</b>
```go
func Factorial(x uint) uint
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
)
func main() {
fmt.Println(mathutil.Factorial(0)) //1
fmt.Println(mathutil.Factorial(1)) //1
fmt.Println(mathutil.Factorial(2)) //2
fmt.Println(mathutil.Factorial(3)) //6
}
```
### <span id="Percent">Percent</span>
<p>calculate the percentage of val to total, retain n decimal places.</p>
<b>Signature:</b>
```go
func Percent(val, total float64, n int) float64
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
)
func main() {
fmt.Println(mathutil.Percent(1, 2, 2)) //1
fmt.Println(mathutil.Percent(0.1, 0.3, 2)) //33.33
}
```
### <span id="RoundToFloat">RoundToFloat</span>
<p>Round float up to n decimal places.</p>
<b>Signature:</b>
```go
func RoundToFloat(x float64, n int) float64
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
)
func main() {
fmt.Println(mathutil.RoundToFloat(0, 0)) //0
fmt.Println(mathutil.RoundToFloat(0, 1)) //0
fmt.Println(mathutil.RoundToFloat(0.124, 2)) //0.12
fmt.Println(mathutil.RoundToFloat(0.125, 2)) //0.13
fmt.Println(mathutil.RoundToFloat(0.125, 3)) //0.125
}
```
### <span id="RoundToString">RoundToString</span>
<p>Round float up to n decimal places. will return string.</p>
<b>Signature:</b>
```go
func RoundToString(x float64, n int) string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
)
func main() {
fmt.Println(mathutil.RoundToString(0, 0)) //"0"
fmt.Println(mathutil.RoundToString(0, 1)) //"0.0:
fmt.Println(mathutil.RoundToString(0.124, 2)) //"0.12"
fmt.Println(mathutil.RoundToString(0.125, 2)) //"0.13"
fmt.Println(mathutil.RoundToString(0.125, 3)) //"0.125"
}
```
### <span id="TruncRound">TruncRound</span>
<p>Round float off n decimal places.</p>
<b>Signature:</b>
```go
func TruncRound(x float64, n int) float64
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
)
func main() {
fmt.Println(mathutil.TruncRound(0, 0)) //0
fmt.Println(mathutil.TruncRound(0, 1)) //0
fmt.Println(mathutil.TruncRound(0.124, 2)) //0.12
fmt.Println(mathutil.TruncRound(0.125, 2)) //0.12
fmt.Println(mathutil.TruncRound(0.125, 3)) //0.125
}
```

234
docs/mathutil_zh-CN.md Normal file
View File

@@ -0,0 +1,234 @@
# Mathutil
mathutil包实现了一些数学计算的函数.
<div STYLE="page-break-after: always;"></div>
## 源码:
[https://github.com/duke-git/lancet/blob/v1/mathutil/mathutil.go](https://github.com/duke-git/lancet/blob/v1/mathutil/mathutil.go)
<div STYLE="page-break-after: always;"></div>
## 用法:
```go
import (
"github.com/duke-git/lancet/mathutil"
)
```
<div STYLE="page-break-after: always;"></div>
## 目录
- [Exponent](#Exponent)
- [Fibonacci](#Fibonacci)
- [Factorial](#Factorial)
- [Percent](#Percent)
- [RoundToFloat](#RoundToFloat)
- [RoundToString](#RoundToString)
- [TruncRound](#TruncRound)
<div STYLE="page-break-after: always;"></div>
## Documentation
### <span id="Exponent">Exponent</span>
<p>指数计算x的n次方</p>
<b>函数签名:</b>
```go
func Exponent(x, n int64) int64
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
)
func main() {
fmt.Println(mathutil.Exponent(10, 0)) //1
fmt.Println(mathutil.Exponent(10, 1)) //10
fmt.Println(mathutil.Exponent(10, 2)) //100
}
```
### <span id="Fibonacci">Fibonacci</span>
<p>计算斐波那契数列的第n个数</p>
<b>函数签名:</b>
```go
func Fibonacci(first, second, n int) int
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
)
func main() {
fmt.Println(mathutil.Fibonacci(1, 1, 1)) //1
fmt.Println(mathutil.Fibonacci(1, 1, 2)) //1
fmt.Println(mathutil.Fibonacci(1, 1, 3)) //2
fmt.Println(mathutil.Fibonacci(1, 1, 4)) //3
fmt.Println(mathutil.Fibonacci(1, 1, 5)) //5
}
```
### <span id="Factorial">Factorial</span>
<p>计算阶乘</p>
<b>函数签名:</b>
```go
func Factorial(x uint) uint
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
)
func main() {
fmt.Println(mathutil.Factorial(0)) //1
fmt.Println(mathutil.Factorial(1)) //1
fmt.Println(mathutil.Factorial(2)) //2
fmt.Println(mathutil.Factorial(3)) //6
}
```
### <span id="Percent">Percent</span>
<p>计算百分比保留n位小数</p>
<b>函数签名:</b>
```go
func Percent(val, total float64, n int) float64
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
)
func main() {
fmt.Println(mathutil.Percent(1, 2, 2)) //1
fmt.Println(mathutil.Percent(0.1, 0.3, 2)) //33.33
}
```
### <span id="RoundToFloat">RoundToFloat</span>
<p>四舍五入保留n位小数</p>
<b>函数签名:</b>
```go
func RoundToFloat(x float64, n int) float64
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
)
func main() {
fmt.Println(mathutil.RoundToFloat(0, 0)) //0
fmt.Println(mathutil.RoundToFloat(0, 1)) //0
fmt.Println(mathutil.RoundToFloat(0.124, 2)) //0.12
fmt.Println(mathutil.RoundToFloat(0.125, 2)) //0.13
fmt.Println(mathutil.RoundToFloat(0.125, 3)) //0.125
}
```
### <span id="RoundToString">RoundToString</span>
<p>四舍五入保留n位小数返回字符串</p>
<b>函数签名:</b>
```go
func RoundToString(x float64, n int) string
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
)
func main() {
fmt.Println(mathutil.RoundToString(0, 0)) //"0"
fmt.Println(mathutil.RoundToString(0, 1)) //"0.0:
fmt.Println(mathutil.RoundToString(0.124, 2)) //"0.12"
fmt.Println(mathutil.RoundToString(0.125, 2)) //"0.13"
fmt.Println(mathutil.RoundToString(0.125, 3)) //"0.125"
}
```
### <span id="TruncRound">TruncRound</span>
<p>截短n位小数不进行四舍五入</p>
<b>函数签名:</b>
```go
func TruncRound(x float64, n int) float64
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/mathutil"
)
func main() {
fmt.Println(mathutil.TruncRound(0, 0)) //0
fmt.Println(mathutil.TruncRound(0, 1)) //0
fmt.Println(mathutil.TruncRound(0.124, 2)) //0.12
fmt.Println(mathutil.TruncRound(0.125, 2)) //0.12
fmt.Println(mathutil.TruncRound(0.125, 3)) //0.125
}
```

View File

@@ -5,9 +5,9 @@ Package netutil contains functions to get net information and send http request.
## Source:
[https://github.com/duke-git/lancet/blob/main/netutil/net.go](https://github.com/duke-git/lancet/blob/main/netutil/net.go)
[https://github.com/duke-git/lancet/blob/v1/netutil/net.go](https://github.com/duke-git/lancet/blob/v1/netutil/net.go)
[https://github.com/duke-git/lancet/blob/main/netutil/http.go](https://github.com/duke-git/lancet/blob/main/netutil/http.go)
[https://github.com/duke-git/lancet/blob/v1/netutil/http.go](https://github.com/duke-git/lancet/blob/v1/netutil/http.go)
<div STYLE="page-break-after: always;"></div>
@@ -22,16 +22,19 @@ import (
## Index
- [ConvertMapToQueryString](#ConvertMapToQueryString)
- [EncodeUrl](#EncodeUrl)
- [GetInternalIp](#GetInternalIp)
- [GetIps](#GetIps)
- [GetMacAddrs](#GetMacAddrs)
- [GetPublicIpInfo](#GetPublicIpInfo)
- [GetRequestPublicIp](#GetRequestPublicIp)
- [IsPublicIP](#IsPublicIP)
- [IsInternalIP](#IsInternalIP)
- [HttpGet](#HttpGet)
- [HttpDelete](#HttpDelete)
- [HttpPost](#HttpPost)
- [HttpPut](#HttpPut)
- [HttpPatch](#HttpPatch)
- [ParseHttpResponse](#ParseHttpResponse)
@@ -72,6 +75,35 @@ func main() {
### <span id="EncodeUrl">EncodeUrl</span>
<p>Encode url query string values.</p>
<b>Signature:</b>
```go
func EncodeUrl(urlStr string) (string, error)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/netutil"
)
func main() {
urlAddr := "http://www.lancet.com?a=1&b=[2]"
encodedUrl, err := netutil.EncodeUrl(urlAddr)
if err != nil {
fmt.Println(err)
}
fmt.Println(encodedUrl) //http://www.lancet.com?a=1&b=%5B2%5D
}
```
### <span id="GetInternalIp">GetInternalIp</span>
<p>Get internal ip information.</p>
@@ -198,6 +230,48 @@ func main() {
```
### <span id="GetRequestPublicIp">GetRequestPublicIp</span>
<p>Get http request public ip.</p>
<b>Signature:</b>
```go
func GetRequestPublicIp(req *http.Request) string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/netutil"
)
func main() {
ip := "36.112.24.10"
request1 := http.Request{
Method: "GET",
Header: http.Header{
"X-Forwarded-For": {ip},
},
}
publicIp1 := netutil.GetRequestPublicIp(&request1)
fmt.Println(publicIp1) //36.112.24.10
request2 := http.Request{
Method: "GET",
Header: http.Header{
"X-Real-Ip": {ip},
},
}
publicIp2 := netutil.GetRequestPublicIp(&request2)
fmt.Println(publicIp2) //36.112.24.10
}
```
### <span id="IsPublicIP">IsPublicIP</span>
<p>Checks if a ip is public or not.</p>
@@ -229,6 +303,36 @@ func main() {
### <span id="IsInternalIP">IsInternalIP</span>
<p>Checks if an ip is intranet or not.</p>
<b>Signature:</b>
```go
func IsInternalIP(IP net.IP) bool
```
<b>Example:</b>
```go
package main
import (
"fmt"
"net"
"github.com/duke-git/lancet/v2/netutil"
)
func main() {
ip1 := net.ParseIP("127.0.0.1")
ip2 := net.ParseIP("36.112.24.10")
fmt.Println(netutil.IsInternalIP(ip1)) //true
fmt.Println(netutil.IsInternalIP(ip2)) //false
}
```
### <span id="HttpGet">HttpGet</span>
<p>Send http get request.</p>

View File

@@ -5,9 +5,9 @@ netutil网络包支持获取ip地址发送http请求。
## 源码:
[https://github.com/duke-git/lancet/blob/main/netutil/net.go](https://github.com/duke-git/lancet/blob/main/netutil/net.go)
[https://github.com/duke-git/lancet/blob/v1/netutil/net.go](https://github.com/duke-git/lancet/blob/v1/netutil/net.go)
[https://github.com/duke-git/lancet/blob/main/netutil/http.go](https://github.com/duke-git/lancet/blob/main/netutil/http.go)
[https://github.com/duke-git/lancet/blob/v1/netutil/http.go](https://github.com/duke-git/lancet/blob/v1/netutil/http.go)
<div STYLE="page-break-after: always;"></div>
@@ -22,16 +22,19 @@ import (
## 目录
- [ConvertMapToQueryString](#ConvertMapToQueryString)
- [EncodeUrl](#EncodeUrl)
- [GetInternalIp](#GetInternalIp)
- [GetIps](#GetIps)
- [GetMacAddrs](#GetMacAddrs)
- [GetPublicIpInfo](#GetPublicIpInfo)
- [GetRequestPublicIp](#GetRequestPublicIp)
- [IsPublicIP](#IsPublicIP)
- [IsInternalIP](#IsInternalIP)
- [HttpGet](#HttpGet)
- [HttpDelete](#HttpDelete)
- [HttpPost](#HttpPost)
- [HttpPut](#HttpPut)
- [HttpPatch](#HttpPatch)
- [ParseHttpResponse](#ParseHttpResponse)
@@ -72,6 +75,36 @@ func main() {
### <span id="EncodeUrl">EncodeUrl</span>
<p>编码url query string的值</p>
<b>函数签名:</b>
```go
func EncodeUrl(urlStr string) (string, error)
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/netutil"
)
func main() {
urlAddr := "http://www.lancet.com?a=1&b=[2]"
encodedUrl, err := netutil.EncodeUrl(urlAddr)
if err != nil {
fmt.Println(err)
}
fmt.Println(encodedUrl) //http://www.lancet.com?a=1&b=%5B2%5D
}
```
### <span id="GetInternalIp">GetInternalIp</span>
<p>获取内部ip</p>
@@ -198,6 +231,49 @@ func main() {
### <span id="GetRequestPublicIp">GetRequestPublicIp</span>
<p>获取http请求ip</p>
<b>函数签名:</b>
```go
func GetRequestPublicIp(req *http.Request) string
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/netutil"
)
func main() {
ip := "36.112.24.10"
request1 := http.Request{
Method: "GET",
Header: http.Header{
"X-Forwarded-For": {ip},
},
}
publicIp1 := netutil.GetRequestPublicIp(&request1)
fmt.Println(publicIp1) //36.112.24.10
request2 := http.Request{
Method: "GET",
Header: http.Header{
"X-Real-Ip": {ip},
},
}
publicIp2 := netutil.GetRequestPublicIp(&request2)
fmt.Println(publicIp2) //36.112.24.10
}
```
### <span id="IsPublicIP">IsPublicIP</span>
<p>判断ip是否是公共ip</p>
@@ -228,6 +304,35 @@ func main() {
### <span id="IsInternalIP">IsInternalIP</span>
<p>判断ip是否是局域网ip.</p>
<b>函数签名:</b>
```go
func IsInternalIP(IP net.IP) bool
```
<b>例子:</b>
```go
package main
import (
"fmt"
"net"
"github.com/duke-git/lancet/netutil"
)
func main() {
ip1 := net.ParseIP("127.0.0.1")
ip2 := net.ParseIP("36.112.24.10")
fmt.Println(netutil.IsInternalIP(ip1)) //true
fmt.Println(netutil.IsInternalIP(ip2)) //false
}
```
### <span id="HttpGet">HttpGet</span>
<p>发送http get请求</p>

View File

@@ -5,7 +5,7 @@ Package random implements some basic functions to generate random int and string
## Source:
[https://github.com/duke-git/lancet/blob/main/random/random.go](https://github.com/duke-git/lancet/blob/main/random/random.go)
[https://github.com/duke-git/lancet/blob/v1/random/random.go](https://github.com/duke-git/lancet/blob/v1/random/random.go)
<div STYLE="page-break-after: always;"></div>
@@ -23,6 +23,7 @@ import (
- [RandBytes](#RandBytes)
- [RandInt](#RandInt)
- [RandString](#RandString)
- [UUIdV4](#UUIdV4)
<div STYLE="page-break-after: always;"></div>
@@ -105,3 +106,33 @@ func main() {
```
### <span id="UUIdV4">UUIdV4</span>
<p>Generate a random UUID of version 4 according to RFC 4122.</p>
<b>Signature:</b>
```go
func UUIdV4() (string, error)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/random"
)
func main() {
uuid, err := random.UUIdV4()
if err != nil {
return
}
fmt.Println(uuid)
}
```

View File

@@ -5,7 +5,7 @@ random随机数生成器包可以生成随机[]bytes, int, string。
## 源码:
[https://github.com/duke-git/lancet/blob/main/random/random.go](https://github.com/duke-git/lancet/blob/main/random/random.go)
[https://github.com/duke-git/lancet/blob/v1/random/random.go](https://github.com/duke-git/lancet/blob/v1/random/random.go)
<div STYLE="page-break-after: always;"></div>
@@ -23,6 +23,8 @@ import (
- [RandBytes](#RandBytes)
- [RandInt](#RandInt)
- [RandString](#RandString)
- [UUIdV4](#UUIdV4)
<div STYLE="page-break-after: always;"></div>
@@ -105,3 +107,32 @@ func main() {
```
### <span id="UUIdV4">UUIdV4</span>
<p>生成UUID v4字符串</p>
<b>函数签名:</b>
```go
func UUIdV4() (string, error)
```
<b>例子:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/random"
)
func main() {
uuid, err := random.UUIdV4()
if err != nil {
return
}
fmt.Println(uuid)
}
```

View File

@@ -5,7 +5,7 @@ Package retry is for executing a function repeatedly until it was successful or
## Source:
[https://github.com/duke-git/lancet/blob/main/retry/retry.go](https://github.com/duke-git/lancet/blob/main/retry/retry.go)
[https://github.com/duke-git/lancet/blob/v1/retry/retry.go](https://github.com/duke-git/lancet/blob/v1/retry/retry.go)
<div STYLE="page-break-after: always;"></div>

View File

@@ -5,7 +5,7 @@ retry重试执行函数直到函数运行成功或被context cancel。
## 源码:
[https://github.com/duke-git/lancet/blob/main/retry/retry.go](https://github.com/duke-git/lancet/blob/main/retry/retry.go)
[https://github.com/duke-git/lancet/blob/v1/retry/retry.go](https://github.com/duke-git/lancet/blob/v1/retry/retry.go)
<div STYLE="page-break-after: always;"></div>

View File

@@ -5,7 +5,7 @@ Package slice implements some functions to manipulate slice.
## Source:
[https://github.com/duke-git/lancet/blob/main/slice/slice.go](https://github.com/duke-git/lancet/blob/main/slice/slice.go)
[https://github.com/duke-git/lancet/blob/v1/slice/slice.go](https://github.com/duke-git/lancet/blob/v1/slice/slice.go)
<div STYLE="page-break-after: always;"></div>
@@ -20,6 +20,7 @@ import (
<div STYLE="page-break-after: always;"></div>
## Index
- [AppendIfAbsent](#AppendIfAbsent)
- [Contain](#Contain)
- [ContainSubSlice](#ContainSubSlice)
- [Chunk](#Chunk)
@@ -30,6 +31,8 @@ import (
- [DifferenceBy](#DifferenceBy)
- [DeleteByIndex](#DeleteByIndex)
- [Drop](#Drop)
- [Equal](#Equal)
- [EqualWith](#EqualWith)
- [Every](#Every)
- [Filter](#Filter)
- [Find](#Find)
@@ -42,6 +45,8 @@ import (
- [InterfaceSlice](#InterfaceSlice)
- [Intersection](#Intersection)
- [InsertByIndex](#InsertByIndex)
- [IndexOf](#IndexOf)
- [LastIndexOf](#LastIndexOf)
- [Map](#Map)
- [ReverseSlice](#ReverseSlice)
- [Reduce](#Reduce)
@@ -49,7 +54,10 @@ import (
- [SortByField](#SortByField)
- [Some](#Some)
- [StringSlice](#StringSlice)
- [ToSlice](#ToSlice)
- [ToSlicePointer](#ToSlicePointer)
- [Unique](#Unique)
- [UniqueBy](#UniqueBy)
- [Union](#Union)
- [UpdateByIndex](#UpdateByIndex)
- [Without](#Without)
@@ -61,6 +69,35 @@ import (
## Note:
1. param which type is interface{} in below functions should be slice.
### <span id="AppendIfAbsent">AppendIfAbsent</span>
<p>If slice doesn't contain the value, append it to the slice.</p>
<b>Signature:</b>
```go
func AppendIfAbsent(slice interface{}, value interface{}) interface{}
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
)
func main() {
strs := []string{"a", "b"}
res1 := slice.AppendIfAbsent(strs, "a")
fmt.Println(res1) //[]string{"a", "b"}
res2 := slice.AppendIfAbsent(strs, "cannot")
fmt.Println(res2"}
}
```
### <span id="Contain">Contain</span>
<p>Check if the value is in the slice or not. iterableType param can be string, map or slice.</p>
@@ -332,6 +369,68 @@ func main() {
### <span id="Equal">Equal</span>
<p>Check if two slices are equal: the same length and all elements' order and value are equal.</p>
<b>Signature:</b>
```go
func Equal(slice1, slice2 interface{}) bool
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
)
func main() {
slice1 := []int{1, 2, 3}
slice2 := []int{1, 2, 3}
slice3 := []int{3, 2, 1}
res1 := slice.Equal(slice1, slice2)
res2 := slice.Equal(slice1, slice3)
fmt.Println(res1) //true
fmt.Println(res2) //false
}
```
### <span id="EqualWith">EqualWith</span>
<p>Check if two slices are equal with comparator funcation.comparator signature: func(a interface{}, b interface{}) bool</p>
<b>Signature:</b>
```go
func EqualWith(slice1, slice2 interface{}, comparator interface{}) bool
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
)
func main() {
slice1 := []int{1, 2, 3}
slice2 := []int{2, 4, 6}
isDouble := func(a, b int) bool {
return b == a*2
}
res := slice.EqualWith(slice1, slice2, isDouble)
fmt.Println(res) //true
}
```
### <span id="Every">Every</span>
<p>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.</p>
@@ -478,8 +577,6 @@ func main() {
### <span id="ForEach">ForEach</span>
<p>Iterates over elements of slice and invokes function for each element, function signature should be func(index int, value interface{}).</p>
@@ -619,6 +716,60 @@ func main() {
### <span id="IndexOf">IndexOf</span>
<p>Returns the index at which the first occurrence of a value is found in a slice or return -1 if the value cannot be found.</p>
<b>Signature:</b>
```go
func IndexOf(slice, value interface{}) int
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
)
func main() {
arr := []string{"a", "a", "b", "c"}
res1 := slice.IndexOf(arr, "a")
fmt.Println(res1) //0
res2 := slice.IndexOf(arr, "d")
fmt.Println(res2) //-1
}
```
### <span id="LastIndexOf">LastIndexOf</span>
<p>Returns the index at which the last occurrence of a value is found in a slice or return -1 if the value cannot be found.</p>
<b>Signature:</b>
```go
func LastIndexOf(slice, value interface{}) int
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
)
func main() {
arr := []string{"a", "a", "b", "c"}
res1 := slice.LastIndexOf(arr, "a")
fmt.Println(res1) //1
res2 := slice.LastIndexOf(arr, "d")
fmt.Println(res2) //-1
}
```
### <span id="InsertByIndex">InsertByIndex</span>
<p>insert the element into slice at index.</p>
@@ -855,6 +1006,55 @@ func main() {
### <span id="ToSlice">ToSlice</span>
<p>Returns a slices of a variable parameter transformation</p>
<b>Signature:</b>
```go
func ToSlice(value ...interface{}) interface{}
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
)
func main() {
res := slice.ToSlice("a", "b")
fmt.Println(res) //{"a", "b"}
}
```
### <span id="ToSlicePointer">ToSlicePointer</span>
<p>Returns a pointer to the slices of a variable parameter transformation</p>
<b>Signature:</b>
```go
func ToSlicePointer(value ...interface{}) []*interface{}
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
)
func main() {
str1 := "a"
str2 := "b"
res := slice.ToSlicePointer(str1, str2)
fmt.Println(res) // res -> []*string{&str1, &str2}
}
```
### <span id="Unique">Unique</span>
<p>Remove duplicate elements in slice.</p>
@@ -880,7 +1080,33 @@ func main() {
### <span id="Union">Unique</span>
### <span id="UniqueBy">UniqueBy</span>
<p>Call iteratee func with every item of slice, then remove duplicated.</p>
<b>Signature:</b>
```go
func UniqueBy(slice, iteratee interface{}) interface{}
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
)
func main() {
res := slice.UniqueBy([]int{1, 2, 3, 4, 5, 6}, func(val int) int {
return val % 4
})
fmt.Println(res) //[]int{1, 2, 3, 0}
}
```
### <span id="Union">Union</span>
<p>Creates a slice of unique values, in order, from all given slices. using == for equality comparisons.</p>
<b>Signature:</b>

View File

@@ -5,7 +5,7 @@ slice包包含操作切片的方法集合。
## 源码:
[https://github.com/duke-git/lancet/blob/main/slice/slice.go](https://github.com/duke-git/lancet/blob/main/slice/slice.go)
[https://github.com/duke-git/lancet/blob/v1/slice/slice.go](https://github.com/duke-git/lancet/blob/v1/slice/slice.go)
<div STYLE="page-break-after: always;"></div>
@@ -20,6 +20,7 @@ import (
<div STYLE="page-break-after: always;"></div>
## 目录
- [AppendIfAbsent](#AppendIfAbsent)
- [Contain](#Contain)
- [ContainSubSlice](#ContainSubSlice)
- [Chunk](#Chunk)
@@ -30,6 +31,8 @@ import (
- [DifferenceBy](#DifferenceBy)
- [DeleteByIndex](#DeleteByIndex)
- [Drop](#Drop)
- [Equal](#Equal)
- [EqualWith](#EqualWith)
- [Every](#Every)
- [Filter](#Filter)
- [Find](#Find)
@@ -42,6 +45,8 @@ import (
- [InterfaceSlice](#InterfaceSlice)
- [Intersection](#Intersection)
- [InsertByIndex](#InsertByIndex)
- [IndexOf](#IndexOf)
- [LastIndexOf](#LastIndexOf)
- [Map](#Map)
- [ReverseSlice](#ReverseSlice)
- [Reduce](#Reduce)
@@ -49,7 +54,10 @@ import (
- [SortByField](#SortByField)
- [Some](#Some)
- [StringSlice](#StringSlice)
- [ToSlice](#ToSlice)
- [ToSlicePointer](#ToSlicePointer)
- [Unique](#Unique)
- [UniqueBy](#UniqueBy)
- [Union](#Union)
- [UpdateByIndex](#UpdateByIndex)
- [Without](#Without)
@@ -58,6 +66,34 @@ import (
## 文档
### <span id="AppendIfAbsent">AppendIfAbsent</span>
<p>当前切片中不包含值时,将该值追加到切片中</p>
<b>函数签名:</b>
```go
func AppendIfAbsent(slice interface{}, value interface{}) interface{}
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
)
func main() {
strs := []string{"a", "b"}
res1 := slice.AppendIfAbsent(strs, "a")
fmt.Println(res1) //[]string{"a", "b"}
res2 := slice.AppendIfAbsent(strs, "cannot")
fmt.Println(res2"}
}
```
### <span id="Contain">Contain</span>
<p>判断slice是否包含value</p>
@@ -329,6 +365,68 @@ func main() {
### <span id="Equal">Equal</span>
<p>检查两个切片是否相等,相等条件:切片长度相同,元素顺序和值都相同</p>
<b>函数签名:</b>
```go
func Equal(slice1, slice2 interface{}) bool
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
)
func main() {
slice1 := []int{1, 2, 3}
slice2 := []int{1, 2, 3}
slice3 := []int{3, 2, 1}
res1 := slice.Equal(slice1, slice2)
res2 := slice.Equal(slice1, slice3)
fmt.Println(res1) //true
fmt.Println(res2) //false
}
```
### <span id="EqualWith">EqualWith</span>
<p>检查两个切片是否相等相等条件对两个切片的元素调用比较函数comparator返回true。 comparator函数签名: func(a interface{}, b interface{}) bool</p>
<b>函数签名:</b>
```go
func EqualWith(slice1, slice2 interface{}, comparator interface{}) bool
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
)
func main() {
slice1 := []int{1, 2, 3}
slice2 := []int{2, 4, 6}
isDouble := func(a, b int) bool {
return b == a*2
}
res := slice.EqualWith(slice1, slice2, isDouble)
fmt.Println(res) //true
}
```
### <span id="Every">Every</span>
<p>如果切片中的所有值都通过谓词函数则返回true。 函数签名应该是func(index int, value interface{}) bool</p>
@@ -616,6 +714,61 @@ func main() {
### <span id="IndexOf">IndexOf</span>
<p>返回在切片中找到值的第一个匹配项的索引,如果找不到值,则返回-1</p>
<b>函数签名:</b>
```go
func IndexOf(slice, value interface{}) int
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
)
func main() {
arr := []string{"a", "a", "b", "c"}
res1 := slice.IndexOf(arr, "a")
fmt.Println(res1) //0
res2 := slice.IndexOf(arr, "d")
fmt.Println(res2) //-1
}
```
### <span id="LastIndexOf">LastIndexOf</span>
<p>返回在切片中找到最后一个值的索引,如果找不到该值,则返回-1</p>
<b>函数签名:</b>
```go
func LastIndexOf(slice, value interface{}) int
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
)
func main() {
arr := []string{"a", "a", "b", "c"}
res1 := slice.LastIndexOf(arr, "a")
fmt.Println(res1) //1
res2 := slice.LastIndexOf(arr, "d")
fmt.Println(res2) //-1
}
```
### <span id="InsertByIndex">InsertByIndex</span>
<p>将元素插入到索引处的切片中</p>
@@ -852,6 +1005,55 @@ func main() {
### <span id="ToSlice">ToSlice</span>
<p>将可变参数转为切片</p>
<b>函数签名:</b>
```go
func ToSlice(value ...interface{}) interface{}
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
res := slice.ToSlice("a", "b")
fmt.Println(res) //{"a", "b"}
}
```
### <span id="ToSlicePointer">ToSlicePointer</span>
<p>将可变参数转为指针切片</p>
<b>函数签名:</b>
```go
func ToSlicePointer(value ...interface{}) []*interface{}
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/slice"
)
func main() {
str1 := "a"
str2 := "b"
res := slice.ToSlicePointer(str1, str2)
fmt.Println(res) // res -> []*string{&str1, &str2}
}
```
### <span id="Unique">Unique</span>
<p>删除切片中的重复元素</p>
@@ -877,7 +1079,32 @@ func main() {
### <span id="Union">Unique</span>
### <span id="UniqueBy">UniqueBy</span>
<p>对切片的每个项目调用iteratee函数然后删除重复的</p>
<b>函数签名:</b>
```go
func UniqueBy(slice, iteratee interface{}) interface{}
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/slice"
)
func main() {
res := slice.UniqueBy([]int{1, 2, 3, 4, 5, 6}, func(val int) int {
return val % 4
})
fmt.Println(res) //[]int{1, 2, 3, 0}
}
```
### <span id="Union">Union</span>
<p>从所有给定的切片按顺序创建一个唯一值切片。 使用 == 进行相等比较。</p>
<b>函数签名:</b>

View File

@@ -5,7 +5,7 @@ Package strutil contains some functions to manipulate string.
## Source:
[https://github.com/duke-git/lancet/blob/main/strutil/string.go](https://github.com/duke-git/lancet/blob/main/strutil/string.go)
[https://github.com/duke-git/lancet/blob/v1/strutil/string.go](https://github.com/duke-git/lancet/blob/v1/strutil/string.go)
<div STYLE="page-break-after: always;"></div>
@@ -35,8 +35,9 @@ import (
- [ReverseStr](#ReverseStr)
- [SnakeCase](#SnakeCase)
- [Wrap](#Wrap)
- [Unwrap](#Unwrap)
- [SplitEx](#SplitEx)
<div STYLE="page-break-after: always;"></div>
@@ -566,7 +567,39 @@ func main() {
### <span id="SplitEx">SplitEx</span>
<p>Split a given string whether the result contains empty string.</p>
<b>Signature:</b>
```go
func SplitEx(s, sep string, removeEmptyString bool) []string
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
)
func main() {
arr1 := strutil.SplitEx(" a b c ", "", true)
fmt.Println(arr1) //[]string{}
arr2 := strutil.SplitEx(" a b c ", " ", false)
fmt.Println(arr2) //[]string{"", "a", "b", "c", ""}
arr3 := strutil.SplitEx(" a b c ", " ", true)
fmt.Println(arr3) //[]string{"a", "b", "c"}
arr4 := strutil.SplitEx(" a = b = c = ", " = ", false)
fmt.Println(arr4) //[]string{" a", "b", "c", ""}
arr5 := strutil.SplitEx(" a = b = c = ", " = ", true)
fmt.Println(arr5) //[]string{" a", "b", "c"}
}
```

View File

@@ -5,7 +5,7 @@ strutil包含处理字符串的相关函数。
## 源码:
[https://github.com/duke-git/lancet/blob/main/strutil/string.go](https://github.com/duke-git/lancet/blob/main/strutil/string.go)
[https://github.com/duke-git/lancet/blob/v1/strutil/string.go](https://github.com/duke-git/lancet/blob/v1/strutil/string.go)
<div STYLE="page-break-after: always;"></div>
@@ -37,6 +37,7 @@ import (
- [Wrap](#Wrap)
- [Unwrap](#Unwrap)
- [SplitEx](#SplitEx)
<div STYLE="page-break-after: always;"></div>
@@ -567,6 +568,39 @@ func main() {
### <span id="SplitEx">SplitEx</span>
<p>分割字符串为切片removeEmptyString参数指定是否去除空字符串</p>
<b>函数签名:</b>
```go
func SplitEx(s, sep string, removeEmptyString bool) []string
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/strutil"
)
func main() {
arr1 := strutil.SplitEx(" a b c ", "", true)
fmt.Println(arr1) //[]string{}
arr2 := strutil.SplitEx(" a b c ", " ", false)
fmt.Println(arr2) //[]string{"", "a", "b", "c", ""}
arr3 := strutil.SplitEx(" a b c ", " ", true)
fmt.Println(arr3) //[]string{"a", "b", "c"}
arr4 := strutil.SplitEx(" a = b = c = ", " = ", false)
fmt.Println(arr4) //[]string{" a", "b", "c", ""}
arr5 := strutil.SplitEx(" a = b = c = ", " = ", true)
fmt.Println(arr5) //[]string{" a", "b", "c"}
}
```

View File

@@ -5,7 +5,7 @@ Package system contains some functions about os, runtime, shell command.
## Source:
[https://github.com/duke-git/lancet/blob/main/system/os.go](https://github.com/duke-git/lancet/blob/main/system/os.go)
[https://github.com/duke-git/lancet/blob/v1/system/os.go](https://github.com/duke-git/lancet/blob/v1/system/os.go)
<div STYLE="page-break-after: always;"></div>
@@ -28,6 +28,7 @@ import (
- [RemoveOsEnv](#RemoveOsEnv)
- [CompareOsEnv](#CompareOsEnv)
- [ExecCommand](#ExecCommand)
- [GetOsBits](#GetOsBits)
<div STYLE="page-break-after: always;"></div>
@@ -235,7 +236,27 @@ func main() {
### <span id="GetOsBits">GetOsBits</span>
<p>获取当前操作系统位数返回32或64</p>
<b>函数签名:</b>
```go
func GetOsBits() int
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/system"
)
func main() {
osBit := system.GetOsBits()
fmt.Println(osBit)
}
```

View File

@@ -5,7 +5,7 @@ system包含os, runtime, shell command相关函数。
## 源码:
[https://github.com/duke-git/lancet/blob/main/system/os.go](https://github.com/duke-git/lancet/blob/main/system/os.go)
[https://github.com/duke-git/lancet/blob/v1/system/os.go](https://github.com/duke-git/lancet/blob/v1/system/os.go)
<div STYLE="page-break-after: always;"></div>
@@ -28,6 +28,7 @@ import (
- [RemoveOsEnv](#RemoveOsEnv)
- [CompareOsEnv](#CompareOsEnv)
- [ExecCommand](#ExecCommand)
- [GetOsBits](#GetOsBits)
<div STYLE="page-break-after: always;"></div>
@@ -235,7 +236,27 @@ func main() {
### <span id="GetOsBits">GetOsBits</span>
<p>Get current os bits, 32bit or 64bit. return 32 or 64</p>
<b>Signature:</b>
```go
func GetOsBits() int
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/system"
)
func main() {
osBit := system.GetOsBits()
fmt.Println(osBit)
}
```

View File

@@ -5,7 +5,7 @@ Package validator contains some functions for data validation.
## Source:
[https://github.com/duke-git/lancet/blob/main/validator/validator.go](https://github.com/duke-git/lancet/blob/main/validator/validator.go)
[https://github.com/duke-git/lancet/blob/v1/validator/validator.go](https://github.com/duke-git/lancet/blob/v1/validator/validator.go)
<div STYLE="page-break-after: always;"></div>

View File

@@ -5,7 +5,7 @@ validator验证器包包含常用字符串格式验证函数。
## 源码:
[https://github.com/duke-git/lancet/blob/main/validator/validator.go](https://github.com/duke-git/lancet/blob/main/validator/validator.go)
[https://github.com/duke-git/lancet/blob/v1/validator/validator.go](https://github.com/duke-git/lancet/blob/v1/validator/validator.go)
<div STYLE="page-break-after: always;"></div>

View File

@@ -13,6 +13,7 @@ import (
"io/ioutil"
"net/http"
"os"
"path"
"path/filepath"
"strings"
)
@@ -40,6 +41,11 @@ func CreateFile(path string) bool {
return true
}
// CreateDir create directory in absolute path. param `absPath` like /a/, /a/b/
func CreateDir(absPath string) error {
return os.MkdirAll(path.Dir(absPath), os.ModePerm)
}
// IsDir checks if the path is directory or not
func IsDir(path string) bool {
file, err := os.Stat(path)

View File

@@ -33,6 +33,27 @@ func TestCreateFile(t *testing.T) {
os.Remove(f)
}
func TestCreateDir(t *testing.T) {
assert := internal.NewAssert(t, "TestCreateDir")
pwd, err := os.Getwd()
if err != nil {
t.Error(err)
t.FailNow()
}
dirPath := pwd + "/a/"
err = CreateDir(dirPath)
if err != nil {
t.Error(err)
t.FailNow()
}
assert.Equal(true, IsExist(dirPath))
os.Remove(dirPath)
assert.Equal(false, IsExist(dirPath))
}
func TestIsDir(t *testing.T) {
assert := internal.NewAssert(t, "TestIsDir")
@@ -79,7 +100,7 @@ func TestListFileNames(t *testing.T) {
filesInPath, err := ListFileNames("../datetime/")
assert.IsNil(err)
expected := []string{"datetime.go", "datetime_test.go"}
expected := []string{"conversion.go", "conversion_test.go", "datetime.go", "datetime_test.go"}
assert.Equal(expected, filesInPath)
}

View File

@@ -13,6 +13,7 @@ import (
func After(n int, fn interface{}) func(args ...interface{}) []reflect.Value {
// Catch programming error while constructing the closure
mustBeFunction(fn)
return func(args ...interface{}) []reflect.Value {
n--
if n < 1 {
@@ -66,12 +67,18 @@ func Compose(fnList ...func(...interface{}) interface{}) func(...interface{}) in
// Delay make the function execution after delayed time
func Delay(delay time.Duration, fn interface{}, args ...interface{}) {
// Catch programming error while constructing the closure
mustBeFunction(fn)
time.Sleep(delay)
invokeFunc(fn, args...)
}
// Debounced creates a debounced function that delays invoking fn until after wait duration have elapsed since the last time the debounced function was invoked.
func Debounced(fn func(), duration time.Duration) func() {
// Catch programming error while constructing the closure
mustBeFunction(fn)
timer := time.NewTimer(duration)
timer.Stop()
@@ -91,6 +98,7 @@ func Debounced(fn func(), duration time.Duration) func() {
func Schedule(d time.Duration, fn interface{}, args ...interface{}) chan bool {
// Catch programming error while constructing the closure
mustBeFunction(fn)
quit := make(chan bool)
go func() {
for {

92
mathutil/mathutil.go Normal file
View File

@@ -0,0 +1,92 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package mathutil implements some functions for math calculation.
package mathutil
import (
"fmt"
"math"
"strconv"
"strings"
)
// Exponent calculate x^n
func Exponent(x, n int64) int64 {
if n == 0 {
return 1
}
t := Exponent(x, n/2)
if n%2 == 1 {
return t * t * x
}
return t * t
}
// Fibonacci calculate fibonacci number before n
func Fibonacci(first, second, n int) int {
if n <= 0 {
return 0
}
if n < 3 {
return 1
} else if n == 3 {
return first + second
} else {
return Fibonacci(second, first+second, n-1)
}
}
// Factorial calculate x!
func Factorial(x uint) uint {
var f uint = 1
for ; x > 1; x-- {
f *= x
}
return f
}
// Percent calculate the percentage of val to total
func Percent(val, total float64, n int) float64 {
if total == 0 {
return float64(0)
}
tmp := val / total * 100
res := RoundToFloat(tmp, n)
return res
}
// RoundToString round up to n decimal places
func RoundToString(x float64, n int) string {
tmp := math.Pow(10.0, float64(n))
x *= tmp
x = math.Round(x)
res := strconv.FormatFloat(x/tmp, 'f', n, 64)
return res
}
// RoundToFloat round up to n decimal places
func RoundToFloat(x float64, n int) float64 {
tmp := math.Pow(10.0, float64(n))
x *= tmp
x = math.Round(x)
return x / tmp
}
// TruncRound round off n decimal places
func TruncRound(x float64, n int) float64 {
floatStr := fmt.Sprintf("%."+strconv.Itoa(n+1)+"f", x)
temp := strings.Split(floatStr, ".")
var newFloat string
if len(temp) < 2 || n >= len(temp[1]) {
newFloat = floatStr
} else {
newFloat = temp[0] + "." + temp[1][:n]
}
res, _ := strconv.ParseFloat(newFloat, 64)
return res
}

72
mathutil/mathutil_test.go Normal file
View File

@@ -0,0 +1,72 @@
package mathutil
import (
"testing"
"github.com/duke-git/lancet/internal"
)
func TestExponent(t *testing.T) {
assert := internal.NewAssert(t, "TestExponent")
assert.Equal(int64(1), Exponent(10, 0))
assert.Equal(int64(10), Exponent(10, 1))
assert.Equal(int64(100), Exponent(10, 2))
}
func TestFibonacci(t *testing.T) {
assert := internal.NewAssert(t, "TestFibonacci")
assert.Equal(0, Fibonacci(1, 1, 0))
assert.Equal(1, Fibonacci(1, 1, 1))
assert.Equal(1, Fibonacci(1, 1, 2))
assert.Equal(5, Fibonacci(1, 1, 5))
}
func TestFactorial(t *testing.T) {
assert := internal.NewAssert(t, "TestFactorial")
assert.Equal(uint(1), Factorial(0))
assert.Equal(uint(1), Factorial(1))
assert.Equal(uint(2), Factorial(2))
assert.Equal(uint(6), Factorial(3))
}
func TestPercent(t *testing.T) {
assert := internal.NewAssert(t, "TestPercent")
assert.Equal(float64(50), Percent(1, 2, 2))
assert.Equal(float64(33.33), Percent(0.1, 0.3, 2))
}
func TestRoundToFloat(t *testing.T) {
assert := internal.NewAssert(t, "TestRoundToFloat")
assert.Equal(RoundToFloat(0, 0), float64(0))
assert.Equal(RoundToFloat(0, 1), float64(0))
assert.Equal(RoundToFloat(0.124, 2), float64(0.12))
assert.Equal(RoundToFloat(0.125, 2), float64(0.13))
assert.Equal(RoundToFloat(0.125, 3), float64(0.125))
assert.Equal(RoundToFloat(33.33333, 2), float64(33.33))
}
func TestRoundToString(t *testing.T) {
assert := internal.NewAssert(t, "TestRoundToString")
assert.Equal(RoundToString(0, 0), "0")
assert.Equal(RoundToString(0, 1), "0.0")
assert.Equal(RoundToString(0.124, 2), "0.12")
assert.Equal(RoundToString(0.125, 2), "0.13")
assert.Equal(RoundToString(0.125, 3), "0.125")
}
func TestTruncRound(t *testing.T) {
assert := internal.NewAssert(t, "TestTruncRound")
assert.Equal(TruncRound(0, 0), float64(0))
assert.Equal(TruncRound(0, 1), float64(0))
assert.Equal(TruncRound(0.124, 2), float64(0.12))
assert.Equal(TruncRound(0.125, 2), float64(0.12))
assert.Equal(TruncRound(0.125, 3), float64(0.125))
assert.Equal(TruncRound(33.33333, 2), float64(33.33))
}

View File

@@ -6,7 +6,8 @@
// HttpGet, HttpPost, HttpDelete, HttpPut, HttpPatch, function param `url` is required.
// HttpGet, HttpPost, HttpDelete, HttpPut, HttpPatch, function param `params` is variable, the order is:
// params[0] is header which type should be http.Header or map[string]string,
// params[1] is query param which type should be url.Values or map[string]interface{},
// params[1] is query string param which type should be url.Values or map[string]string, when content-type header is
// multipart/form-data or application/x-www-form-urlencoded
// params[2] is post body which type should be []byte.
// params[3] is http client which type should be http.Client.
package netutil

View File

@@ -4,6 +4,7 @@ import (
"encoding/json"
"io/ioutil"
"log"
"net/url"
"testing"
"github.com/duke-git/lancet/internal"
@@ -46,6 +47,29 @@ func TestHttpPost(t *testing.T) {
t.Log("response: ", resp.StatusCode, string(body))
}
func TestHttpPostFormData(t *testing.T) {
apiUrl := "https://jsonplaceholder.typicode.com/todos"
header := map[string]string{
// "Content-Type": "application/x-www-form-urlencoded",
"Content-Type": "multipart/form-data",
}
type Todo struct {
UserId int `json:"userId"`
Title string `json:"title"`
}
postData := url.Values{}
postData.Add("userId", "1")
postData.Add("title", "TestAddToDo")
resp, err := HttpPost(apiUrl, header, postData, nil)
if err != nil {
log.Fatal(err)
t.FailNow()
}
body, _ := ioutil.ReadAll(resp.Body)
t.Log("response: ", resp.StatusCode, string(body))
}
func TestHttpPut(t *testing.T) {
url := "https://jsonplaceholder.typicode.com/todos/1"
header := map[string]string{

View File

@@ -5,6 +5,8 @@ import (
"io/ioutil"
"net"
"net/http"
"net/url"
"strings"
)
// GetInternalIp return internal ipv4
@@ -47,6 +49,26 @@ func GetPublicIpInfo() (*PublicIpInfo, error) {
return &ip, nil
}
// GetRequestPublicIp return the requested public ip
func GetRequestPublicIp(req *http.Request) string {
var ip string
for _, ip = range strings.Split(req.Header.Get("X-Forwarded-For"), ",") {
if ip = strings.TrimSpace(ip); ip != "" && !IsInternalIP(net.ParseIP(ip)) {
return ip
}
}
if ip = strings.TrimSpace(req.Header.Get("X-Real-Ip")); ip != "" && !IsInternalIP(net.ParseIP(ip)) {
return ip
}
if ip, _, _ = net.SplitHostPort(req.RemoteAddr); !IsInternalIP(net.ParseIP(ip)) {
return ip
}
return ip
}
// GetIps return all ipv4 of system
func GetIps() []string {
var ips []string
@@ -122,3 +144,29 @@ func IsPublicIP(IP net.IP) bool {
}
return false
}
// IsInternalIP verify an ip is intranet or not
func IsInternalIP(IP net.IP) bool {
if IP.IsLoopback() {
return true
}
if ip4 := IP.To4(); ip4 != nil {
return ip4[0] == 10 ||
(ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31) ||
(ip4[0] == 169 && ip4[1] == 254) ||
(ip4[0] == 192 && ip4[1] == 168)
}
return false
}
// EncodeUrl encode url
func EncodeUrl(urlStr string) (string, error) {
URL, err := url.Parse(urlStr)
if err != nil {
return "", err
}
URL.RawQuery = URL.Query().Encode()
return URL.String(), nil
}

View File

@@ -41,6 +41,7 @@ func doHttpRequest(method, reqUrl string, params ...interface{}) (*http.Response
return nil, err
}
case 3:
err := setHeaderAndQueryAndBody(req, reqUrl, params[0], params[1], params[2])
if err != nil {
return nil, err
@@ -81,7 +82,21 @@ func setHeaderAndQueryAndBody(req *http.Request, reqUrl string, header, queryPar
if err != nil {
return err
}
err = setBodyByte(req, body)
if strings.Contains(req.Header.Get("Content-Type"), "multipart/form-data") || req.Header.Get("Content-Type") == "application/x-www-form-urlencoded" {
if formData, ok := queryParam.(url.Values); ok {
err = setBodyByte(req, []byte(formData.Encode()))
}
if formData, ok := queryParam.(map[string]string); ok {
postData := url.Values{}
for k, v := range formData {
postData.Set(k, v)
}
err = setBodyByte(req, []byte(postData.Encode()))
}
} else {
err = setBodyByte(req, body)
}
if err != nil {
return err
}
@@ -157,16 +172,13 @@ func setQueryParam(req *http.Request, reqUrl string, queryParam interface{}) err
func setBodyByte(req *http.Request, body interface{}) error {
if body != nil {
var bodyByte []byte
if body != nil {
switch v := body.(type) {
case []byte:
bodyByte = v
default:
return errors.New("body type should be []byte")
}
switch b := body.(type) {
case []byte:
req.Body = ioutil.NopCloser(bytes.NewReader(b))
req.ContentLength = int64(len(b))
default:
return errors.New("body type should be []byte")
}
req.Body = ioutil.NopCloser(bytes.NewReader(bodyByte))
}
return nil
}

View File

@@ -6,6 +6,7 @@ package random
import (
crand "crypto/rand"
"fmt"
"io"
"math/rand"
"time"
@@ -48,3 +49,18 @@ func RandBytes(length int) []byte {
}
return b
}
// UUIdV4 generate a random UUID of version 4 according to RFC 4122
func UUIdV4() (string, error) {
uuid := make([]byte, 16)
n, err := io.ReadFull(crand.Reader, uuid)
if n != len(uuid) || err != nil {
return "", err
}
uuid[8] = uuid[8]&^0xc0 | 0x80
uuid[6] = uuid[6]&^0xf0 | 0x40
return fmt.Sprintf("%x-%x-%x-%x-%x", uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:]), nil
}

View File

@@ -47,3 +47,16 @@ func TestRandBytes(t *testing.T) {
assert.Equal([]byte{}, RandBytes(0))
}
func TestUUIdV4(t *testing.T) {
assert := internal.NewAssert(t, "TestUUIdV4")
uuid, err := UUIdV4()
if err != nil {
t.Log(err)
t.Fail()
}
isUUiDV4 := regexp.MustCompile(`^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$`)
assert.Equal(true, isUUiDV4.MatchString(uuid))
}

View File

@@ -167,15 +167,15 @@ func Difference(slice1, slice2 interface{}) interface{} {
// DifferenceBy it accepts iteratee which is invoked for each element of slice
// and values to generate the criterion by which they're compared.
// like lodash.js differenceBy: https://lodash.com/docs/4.17.15#differenceBy,
// the iterateeFn function signature should be func(index int, value interface{}) interface{}.
func DifferenceBy(slice interface{}, comparedSlice interface{}, iterateeFn interface{}) interface{} {
// the iteratee function signature should be func(index int, value interface{}) interface{}.
func DifferenceBy(slice interface{}, comparedSlice interface{}, iteratee interface{}) interface{} {
sv := sliceValue(slice)
smv := sliceValue(comparedSlice)
fn := functionValue(iterateeFn)
fn := functionValue(iteratee)
elemType := sv.Type().Elem()
if checkSliceCallbackFuncSignature(fn, elemType, nil) {
panic("function param should be of type func(" + elemType.String() + ")" + elemType.String())
panic("iteratee function signature should be func(" + elemType.String() + ")" + elemType.String())
}
slice1 := reflect.MakeSlice(sv.Type(), sv.Len(), sv.Len())
@@ -203,15 +203,57 @@ func DifferenceBy(slice interface{}, comparedSlice interface{}, iterateeFn inter
return res.Interface()
}
// Equal checks if two slices are equal: the same length and all elements' order and value are equal
func Equal(slice1, slice2 interface{}) bool {
sv1 := sliceValue(slice1)
sv2 := sliceValue(slice2)
if sv1.Type().Elem() != sv2.Type().Elem() {
return false
}
if sv1.Len() != sv2.Len() {
return false
}
for i := 0; i < sv1.Len(); i++ {
if sv1.Index(i).Interface() != sv2.Index(i).Interface() {
return false
}
}
return true
}
// EqualWith checks if two slices are equal with comparator func
func EqualWith(slice1, slice2 interface{}, comparator interface{}) bool {
sv1 := sliceValue(slice1)
sv2 := sliceValue(slice2)
fn := functionValue(comparator)
// elemType1 := sv1.Type().Elem()
// elemType2 := sv2.Type().Elem()
// todo: check fn signature: func(a elemType1.Kind(), b elemType2.Kind()) bool
for i := 0; i < sv1.Len(); i++ {
flag := fn.Call([]reflect.Value{sv1.Index(i), sv2.Index(i)})[0]
if !flag.Bool() {
return false
}
}
return true
}
// 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 .
// The iteratee 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("function param should be of type func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
panic("iteratee function signature should be func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
}
var currentLength int
@@ -226,14 +268,14 @@ func Every(slice, function interface{}) bool {
}
// None return true if all the values in the slice mismatch the criteria
// The function signature should be func(index int, value interface{}) bool .
func None(slice, function interface{}) bool {
// The iteratee function signature should be func(index int, value interface{}) bool .
func None(slice, iteratee interface{}) bool {
sv := sliceValue(slice)
fn := functionValue(function)
fn := functionValue(iteratee)
elemType := sv.Type().Elem()
if checkSliceCallbackFuncSignature(fn, elemType, reflect.ValueOf(true).Type()) {
panic("function param should be of type func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
panic("iteratee function signature should be func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
}
var currentLength int
@@ -248,14 +290,14 @@ func None(slice, function interface{}) bool {
}
// 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 {
// The iteratee function signature should be func(index int, value interface{}) bool .
func Some(slice, iteratee interface{}) bool {
sv := sliceValue(slice)
fn := functionValue(function)
fn := functionValue(iteratee)
elemType := sv.Type().Elem()
if checkSliceCallbackFuncSignature(fn, elemType, reflect.ValueOf(true).Type()) {
panic("function param should be of type func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
panic("iteratee function signature should be func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
}
has := false
@@ -270,14 +312,14 @@ func Some(slice, function interface{}) bool {
}
// 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 .
func Filter(slice, function interface{}) interface{} {
// The iteratee function signature should be func(index int, value interface{}) bool .
func Filter(slice, iteratee interface{}) interface{} {
sv := sliceValue(slice)
fn := functionValue(function)
fn := functionValue(iteratee)
elemType := sv.Type().Elem()
if checkSliceCallbackFuncSignature(fn, elemType, reflect.ValueOf(true).Type()) {
panic("function param should be of type func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
panic("iteratee function signature should be func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
}
res := reflect.MakeSlice(sv.Type(), 0, 0)
@@ -292,14 +334,14 @@ func Filter(slice, function interface{}) interface{} {
}
// Count iterates over elements of slice, returns a count of all matched elements
// The function signature should be func(index int, value interface{}) bool .
func Count(slice, function interface{}) int {
// The iteratee function signature should be func(index int, value interface{}) bool .
func Count(slice, iteratee interface{}) int {
sv := sliceValue(slice)
fn := functionValue(function)
fn := functionValue(iteratee)
elemType := sv.Type().Elem()
if checkSliceCallbackFuncSignature(fn, elemType, reflect.ValueOf(true).Type()) {
panic("function param should be of type func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
panic("iteratee function signature should be func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
}
var counter int
@@ -314,14 +356,14 @@ func Count(slice, function interface{}) int {
}
// GroupBy iterate over elements of the slice, each element will be group by criteria, returns two slices
// The function signature should be func(index int, value interface{}) bool .
func GroupBy(slice, function interface{}) (interface{}, interface{}) {
// The iteratee function signature should be func(index int, value interface{}) bool .
func GroupBy(slice, iteratee interface{}) (interface{}, interface{}) {
sv := sliceValue(slice)
fn := functionValue(function)
fn := functionValue(iteratee)
elemType := sv.Type().Elem()
if checkSliceCallbackFuncSignature(fn, elemType, reflect.ValueOf(true).Type()) {
panic("function param should be of type func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
panic("iteratee function signature should be func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
}
groupB := reflect.MakeSlice(sv.Type(), 0, 0)
@@ -340,14 +382,14 @@ func GroupBy(slice, function interface{}) (interface{}, 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{}, bool) {
// The predicate function signature should be func(index int, value interface{}) bool .
func Find(slice, predicate interface{}) (interface{}, bool) {
sv := sliceValue(slice)
fn := functionValue(function)
fn := functionValue(predicate)
elemType := sv.Type().Elem()
if checkSliceCallbackFuncSignature(fn, elemType, reflect.ValueOf(true).Type()) {
panic("function param should be of type func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
panic("predicate function signature should be func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
}
index := -1
@@ -369,13 +411,13 @@ func Find(slice, function interface{}) (interface{}, bool) {
// FindLast iterates over elements of slice from end to begin, returning the first one that passes a truth test on function.
// The function signature should be func(index int, value interface{}) bool .
func FindLast(slice, function interface{}) (interface{}, bool) {
func FindLast(slice, predicate interface{}) (interface{}, bool) {
sv := sliceValue(slice)
fn := functionValue(function)
fn := functionValue(predicate)
elemType := sv.Type().Elem()
if checkSliceCallbackFuncSignature(fn, elemType, reflect.ValueOf(true).Type()) {
panic("function param should be of type func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
panic("predicate function signature should be func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
}
index := -1
@@ -420,14 +462,14 @@ func flattenRecursive(value reflect.Value, result reflect.Value) reflect.Value {
}
// ForEach iterates over elements of slice and invokes function for each element
// The function signature should be func(index int, value interface{}).
func ForEach(slice, function interface{}) {
// The iteratee function signature should be func(index int, value interface{}).
func ForEach(slice, iteratee interface{}) {
sv := sliceValue(slice)
fn := functionValue(function)
fn := functionValue(iteratee)
elemType := sv.Type().Elem()
if checkSliceCallbackFuncSignature(fn, elemType, nil) {
panic("function param should be of type func(int, " + elemType.String() + ")" + elemType.String())
panic("iteratee function signature should be func(int, " + elemType.String() + ")" + elemType.String())
}
for i := 0; i < sv.Len(); i++ {
@@ -436,14 +478,14 @@ func ForEach(slice, function interface{}) {
}
// 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{}.
func Map(slice, function interface{}) interface{} {
// The iteratee function signature should be func(index int, value interface{}) interface{}.
func Map(slice, iteratee interface{}) interface{} {
sv := sliceValue(slice)
fn := functionValue(function)
fn := functionValue(iteratee)
elemType := sv.Type().Elem()
if checkSliceCallbackFuncSignature(fn, elemType, nil) {
panic("function param should be of type func(int, " + elemType.String() + ")" + elemType.String())
panic("iteratee function signature should be func(int, " + elemType.String() + ")" + elemType.String())
}
res := reflect.MakeSlice(sv.Type(), sv.Len(), sv.Len())
@@ -599,7 +641,6 @@ func InsertByIndex(slice interface{}, index int, value interface{}) (interface{}
return slice, errors.New("InvalidSliceIndex")
}
// value is slice
vv := reflect.ValueOf(value)
if vv.Kind() == reflect.Slice {
if reflect.TypeOf(slice).Elem() != reflect.TypeOf(value).Elem() {
@@ -609,7 +650,6 @@ func InsertByIndex(slice interface{}, index int, value interface{}) (interface{}
return v.Interface(), nil
}
// value is not slice
if reflect.TypeOf(slice).Elem() != reflect.TypeOf(value) {
return slice, errors.New("InvalidValueType")
}
@@ -667,21 +707,28 @@ func Unique(slice interface{}) interface{} {
for i := 0; i < len(temp); i++ {
res.Index(i).Set(reflect.ValueOf(temp[i]))
}
return res.Interface()
}
// if use map filter, the result slice element order is random, not same as origin slice
//mp := make(map[interface{}]bool)
//for i := 0; i < sv.Len(); i++ {
// v := sv.Index(i).Interface()
// mp[v] = true
//}
//
//var res []interface{}
//for k := range mp {
// res = append(res, mp[k])
//}
//return res
// UniqueBy call iteratee func with every item of slice, then remove duplicated.
// The iteratee function signature should be func(value interface{}) interface{}.
func UniqueBy(slice, iteratee interface{}) interface{} {
sv := sliceValue(slice)
fn := functionValue(iteratee)
if sv.Len() == 0 {
return slice
}
res := reflect.MakeSlice(sv.Type(), sv.Len(), sv.Len())
for i := 0; i < sv.Len(); i++ {
val := fn.Call([]reflect.Value{sv.Index(i)})[0]
res.Index(i).Set(val)
}
return Unique(res.Interface())
}
// Union creates a slice of unique values, in order, from all given slices. using == for equality comparisons.
@@ -860,3 +907,64 @@ func Without(slice interface{}, values ...interface{}) interface{} {
return res.Interface()
}
// IndexOf returns the index at which the first occurrence of a value is found in a slice or return -1
// if the value cannot be found.
func IndexOf(slice, value interface{}) int {
sv := sliceValue(slice)
for i := 0; i < sv.Len(); i++ {
if reflect.DeepEqual(sv.Index(i).Interface(), value) {
return i
}
}
return -1
}
// LastIndexOf returns the index at which the last occurrence of a value is found in a slice or return -1
// if the value cannot be found.
func LastIndexOf(slice, value interface{}) int {
sv := sliceValue(slice)
for i := sv.Len() - 1; i > 0; i-- {
if reflect.DeepEqual(sv.Index(i).Interface(), value) {
return i
}
}
return -1
}
// ToSlicePointer returns a pointer to the slices of a variable parameter transformation
func ToSlicePointer(value ...interface{}) []*interface{} {
out := make([]*interface{}, len(value))
for i := range value {
out[i] = &value[i]
}
return out
}
// ToSlice returns a slices of a variable parameter transformation
func ToSlice(value ...interface{}) interface{} {
rv := reflect.ValueOf(value)
out := reflect.MakeSlice(rv.Type(), len(value), len(value))
for i := range value {
out.Index(i).Set(reflect.ValueOf(value[i]))
}
return out.Interface()
}
// AppendIfAbsent only absent append the value
func AppendIfAbsent(slice interface{}, value interface{}) interface{} {
sv := sliceValue(slice)
out := reflect.MakeSlice(sv.Type(), sv.Len(), sv.Len())
for i := 0; i < sv.Len(); i++ {
out.Index(i).Set(sv.Index(i))
}
if !Contain(slice, value) {
out = reflect.Append(out, reflect.ValueOf(value))
}
return out.Interface()
}

View File

@@ -73,6 +73,30 @@ func TestConcat(t *testing.T) {
assert.Equal([]int{1, 2, 3, 4, 5}, Concat([]int{1, 2, 3}, []int{4}, 5))
}
func TestEqual(t *testing.T) {
assert := internal.NewAssert(t, "TestEqual")
slice1 := []int{1, 2, 3}
slice2 := []int{1, 2, 3}
slice3 := []int{3, 2, 1}
assert.Equal(true, Equal(slice1, slice2))
assert.Equal(false, Equal(slice1, slice3))
}
func TestEqualWith(t *testing.T) {
assert := internal.NewAssert(t, "TestEqualWith")
slice1 := []int{1, 2, 3}
slice2 := []int{2, 4, 6}
isDouble := func(a, b int) bool {
return b == a*2
}
assert.Equal(true, EqualWith(slice1, slice2, isDouble))
}
func TestEvery(t *testing.T) {
nums := []int{1, 2, 3, 5}
isEven := func(i, num int) bool {
@@ -394,6 +418,15 @@ func TestUnique(t *testing.T) {
assert.Equal([]string{"a", "b", "c"}, Unique([]string{"a", "a", "b", "c"}))
}
func TestUniqueBy(t *testing.T) {
assert := internal.NewAssert(t, "TestUniqueBy")
actual := UniqueBy([]int{1, 2, 3, 4, 5, 6}, func(val int) int {
return val % 4
})
assert.Equal([]int{1, 2, 3, 0}, actual)
}
func TestUnion(t *testing.T) {
assert := internal.NewAssert(t, "TestUnion")
@@ -543,3 +576,51 @@ func TestShuffle(t *testing.T) {
assert.Equal(true, Contain(res, 4))
assert.Equal(true, Contain(res, 5))
}
func TestIndexOf(t *testing.T) {
assert := internal.NewAssert(t, "TestIndexOf")
arr := []string{"a", "a", "b", "c"}
assert.Equal(0, IndexOf(arr, "a"))
assert.Equal(-1, IndexOf(arr, "d"))
}
func TestLastIndexOf(t *testing.T) {
assert := internal.NewAssert(t, "TestLastIndexOf")
arr := []string{"a", "a", "b", "c"}
assert.Equal(1, LastIndexOf(arr, "a"))
assert.Equal(-1, LastIndexOf(arr, "d"))
}
func TestToSlice(t *testing.T) {
assert := internal.NewAssert(t, "TestToSlice")
str1 := "a"
str2 := "b"
out1 := ToSlice(str1)
out2 := ToSlice(str1, str2)
assert.Equal([]string{"a"}, StringSlice(out1))
assert.Equal([]string{"a", "b"}, StringSlice(out2))
}
func TestToSlicePointer(t *testing.T) {
assert := internal.NewAssert(t, "TestToSlicePointer")
var str1 interface{}
str1 = "a"
var str2 interface{}
str2 = "b"
assert.Equal([]*interface{}{&str1}, ToSlicePointer(str1))
assert.Equal([]*interface{}{&str1, &str2}, ToSlicePointer(str1, str2))
}
func TestAppendIfAbsent(t *testing.T) {
assert := internal.NewAssert(t, "TestToAppendIfAbsent")
str1 := []string{"a", "b"}
assert.Equal([]string{"a", "b"}, AppendIfAbsent(str1, "a"))
assert.Equal([]string{"a", "b", "c"}, AppendIfAbsent(str1, "c"))
}

View File

@@ -248,3 +248,52 @@ func Unwrap(str string, wrapToken string) string {
return str
}
// SplitEx split a given string whether the result contains empty string
func SplitEx(s, sep string, removeEmptyString bool) []string {
if sep == "" {
return []string{}
}
n := strings.Count(s, sep) + 1
a := make([]string, n)
n--
i := 0
sepSave := 0
ignore := false
for i < n {
m := strings.Index(s, sep)
if m < 0 {
break
}
ignore = false
if removeEmptyString {
if s[:m+sepSave] == "" {
ignore = true
}
}
if !ignore {
a[i] = s[:m+sepSave]
s = s[m+len(sep):]
i++
} else {
s = s[m+len(sep):]
}
}
var ret []string
if removeEmptyString {
if s != "" {
a[i] = s
ret = a[:i+1]
} else {
ret = a[:i]
}
} else {
a[i] = s
ret = a[:i+1]
}
return ret
}

View File

@@ -177,3 +177,15 @@ func TestUnwrap(t *testing.T) {
assert.Equal("***", Unwrap("***", "**"))
assert.Equal("**", Unwrap("**", "**"))
}
func TestSplitEx(t *testing.T) {
assert := internal.NewAssert(t, "TestSplitEx")
assert.Equal([]string{}, SplitEx(" a b c ", "", true))
assert.Equal([]string{"", "a", "b", "c", ""}, SplitEx(" a b c ", " ", false))
assert.Equal([]string{"a", "b", "c"}, SplitEx(" a b c ", " ", true))
assert.Equal([]string{" a", "b", "c", ""}, SplitEx(" a = b = c = ", " = ", false))
assert.Equal([]string{" a", "b", "c"}, SplitEx(" a = b = c = ", " = ", true))
}

View File

@@ -70,3 +70,9 @@ func ExecCommand(command string) (stdout, stderr string, err error) {
return
}
// GetOsBits get this system bits 32bit or 64bit
// return bit int (32/64)
func GetOsBits() int {
return 32 << (^uint(0) >> 63)
}

View File

@@ -60,3 +60,13 @@ func TestExecCommand(t *testing.T) {
assert.IsNotNil(err)
}
}
func TestGetOsBits(t *testing.T) {
osBits := GetOsBits()
switch osBits {
case 32, 64:
t.Logf("os is %d", osBits)
default:
t.Error("os is not 32 or 64 bits")
}
}