1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-15 10:12:29 +08:00

Compare commits

...

17 Commits

Author SHA1 Message Date
dudaodong
d95a7c6101 fix: fix example function bug in function package 2023-01-08 21:09:41 +08:00
dudaodong
bce3641ec6 fix: fix example function bug in datetime package 2023-01-08 21:04:39 +08:00
dudaodong
ceb134b2fd fix: fix example function bug in datetime package 2023-01-08 21:01:05 +08:00
dudaodong
4b9b1d32c5 release v2.1.13 2023-01-08 20:45:43 +08:00
dudaodong
395e0883c7 fix: fix example test failed of CreateFile 2023-01-08 20:44:23 +08:00
dudaodong
a930511054 test&doc: add example and update doc for xerror package 2023-01-08 20:36:32 +08:00
dudaodong
7380721ccc test&doc: add example and update doc for xerror package 2023-01-08 20:36:17 +08:00
dudaodong
936011dc3b fix: fix bug in file test 2023-01-08 20:25:11 +08:00
dudaodong
bc0ee08f38 test&doc: add example and update doc for datetime package 2023-01-08 20:16:04 +08:00
dudaodong
f1afd753d4 test&doc: add example and update doc for netutil package 2023-01-08 16:57:03 +08:00
dudaodong
b05a0a91c3 test&doc: add example and update doc for netutil package 2023-01-08 16:54:29 +08:00
dudaodong
da2eb66657 doc: update doc for datastructure package 2023-01-08 15:42:34 +08:00
dudaodong
ad20159de2 doc: update doc for datastructure package 2023-01-08 15:41:59 +08:00
dudaodong
278733d3d1 Todo: add todo for playground demo of function 2023-01-07 18:27:07 +08:00
dudaodong
2f184907ff doc: update document for cryptor package 2023-01-07 18:18:23 +08:00
dudaodong
50fcc718ee test: add example for cryptor package 2023-01-07 17:34:42 +08:00
dudaodong
cc68feb52d doc&test: add example and update doc for retry package 2023-01-07 14:22:07 +08:00
43 changed files with 2455 additions and 995 deletions

397
README.md
View File

@@ -4,7 +4,7 @@
<br/> <br/>
![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf) ![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf)
[![Release](https://img.shields.io/badge/release-2.1.12-green.svg)](https://github.com/duke-git/lancet/releases) [![Release](https://img.shields.io/badge/release-2.1.13-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2) [![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2) [![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
[![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml) [![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
@@ -162,7 +162,7 @@ import "github.com/duke-git/lancet/v2/condition"
[[play](https://go.dev/play/p/W1SSUmt6pvr)] [[play](https://go.dev/play/p/W1SSUmt6pvr)]
- **<big>Or</big>** : returns false if neither a nor b is truthy. - **<big>Or</big>** : returns false if neither a nor b is truthy.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Or)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Or)]
[[play](https://go.dev/play/p/UlQTxHaeEkq)] [[play](https://go.dev/play/p/UlQTxHaeEkq)]]
- **<big>Xor</big>** : returns true if a or b but not both is truthy. - **<big>Xor</big>** : returns true if a or b but not both is truthy.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Xor)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Xor)]
[[play](https://go.dev/play/p/gObZrW7ZbG8)] [[play](https://go.dev/play/p/gObZrW7ZbG8)]
@@ -244,38 +244,101 @@ import "github.com/duke-git/lancet/v2/cryptor"
#### Function list: #### Function list:
- [AesEcbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesEcbEncrypt) - **<big>AesEcbEncrypt</big>** : encrypt byte slice data with key use AES ECB algorithm.
- [AesEcbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesEcbDecrypt) [[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesEcbEncrypt)]
- [AesCbcEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCbcEncrypt) [[play](https://go.dev/play/p/zI6xsmuQRbn)]
- [AesCbcDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCbcDecrypt) - **<big>AesEcbDecrypt</big>** : decrypt byte slice data with key use AES ECB algorithm.
- [AesCtrCrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCtrCrypt) [[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesEcbDecrypt)]
- [AesCfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCfbEncrypt) [[play](https://go.dev/play/p/zI6xsmuQRbn)]
- [AesCfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCfbDecrypt) - **<big>AesCbcEncrypt</big>** : encrypt byte slice data with key use AES CBC algorithm.
- [AesOfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesOfbEncrypt) [[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCbcEncrypt)]
- [AesOfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesOfbDecrypt) [[play](https://go.dev/play/p/IOq_g8_lKZD)]
- [Base64StdEncode](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Base64StdEncode) - **<big>AesCbcDecrypt</big>** : decrypt byte slice data with key use AES CBC algorithm.
- [Base64StdDecode](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Base64StdDecode) [[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCbcDecrypt)]
- [DesEcbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesEcbEncrypt) [[play](https://go.dev/play/p/IOq_g8_lKZD)]
- [DesEcbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesEcbDecrypt) - **<big>AesCtrCrypt</big>** : encrypt/ decrypt byte slice data with key use AES CRC algorithm.
- [DesCbcEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCbcEncrypt) [[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCtrCrypt)]
- [DesCbcDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCbcDecrypt) [[play](https://go.dev/play/p/SpaZO0-5Nsp)]
- [DesCtrCrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCtrCrypt) - **<big>AesCfbEncrypt</big>** : encrypt byte slice data with key use AES CFB algorithm.
- [DesCfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCfbEncrypt) [[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCfbEncrypt)]
- [DesCfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCfbDecrypt) [[play](https://go.dev/play/p/tfkF10B13kH)]
- [DesOfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesOfbEncrypt) - **<big>AesCfbDecrypt</big>** : decrypt byte slice data with key use AES CFB algorithm.
- [DesOfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesOfbDecrypt) [[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesCfbDecrypt)]
- [HmacMd5](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacMd5) [[play](https://go.dev/play/p/tfkF10B13kH)]
- [HmacSha1](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha1) - **<big>AesOfbEncrypt</big>** : encrypt byte slice data with key use AES OFB algorithm.
- [HmacSha256](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha256) [[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesOfbEncrypt)]
- [HmacSha512](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha512) [[play](https://go.dev/play/p/VtHxtkUj-3F)]
- [Md5String](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Md5String) - **<big>AesOfbDecrypt</big>** : decrypt byte slice data with key use AES OFB algorithm.
- [Md5File](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Md5File) [[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#AesOfbDecrypt)]
- [Sha1](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha1) [[play](https://go.dev/play/p/VtHxtkUj-3F)]
- [Sha256](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha256) - **<big>Base64StdEncode</big>** : encode string with base64 encoding.
- [Sha512](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha512) [[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Base64StdEncode)]
- [GenerateRsaKey](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#GenerateRsaKey) [[play](https://go.dev/play/p/VOaUyQUreoK)]
- [RsaEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#RsaEncrypt) - **<big>Base64StdDecode</big>** : decode string with base64 encoding.
- [RsaDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#RsaDecrypt) [[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Base64StdDecode)]
[[play](https://go.dev/play/p/RWQylnJVgIe)]
- **<big>DesEcbEncrypt</big>** : encrypt byte slice data with key use DES ECB algorithm.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesEcbEncrypt)]
[[play](https://go.dev/play/p/8qivmPeZy4P)]
- **<big>DesEcbDecrypt</big>** : decrypt byte slice data with key use DES ECB algorithm.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesEcbDecrypt)]
[[play](https://go.dev/play/p/8qivmPeZy4P)]
- **<big>DesCbcEncrypt</big>** : encrypt byte slice data with key use DES CBC algorithm.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCbcEncrypt)]
[[play](https://go.dev/play/p/4cC4QvWfe3_1)]
- **<big>DesCbcDecrypt</big>** : decrypt byte slice data with key use DES CBC algorithm.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCbcDecrypt)]
[[play](https://go.dev/play/p/4cC4QvWfe3_1)]
- **<big>DesCtrCrypt</big>** : encrypt/decrypt byte slice data with key use DES CRY algorithm.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCtrCrypt)]
[[play](https://go.dev/play/p/9-T6OjKpcdw)]
- **<big>DesCfbEncrypt</big>** : encrypt byte slice data with key use DES CFB algorithm.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCfbEncrypt)]
[[play](https://go.dev/play/p/y-eNxcFBlxL)]
- **<big>DesCfbDecrypt</big>** : decrypt byte slice data with key use DES CFB algorithm.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesCfbDecrypt)]
[[play](https://go.dev/play/p/y-eNxcFBlxL)]
- **<big>DesOfbEncrypt</big>** : encrypt byte slice data with key use DES OFB algorithm.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesOfbEncrypt)]
[[play](https://go.dev/play/p/74KmNadjN1J)]
- **<big>DesOfbDecrypt</big>** : decrypt byte slice data with key use DES OFB algorithm.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#DesOfbDecrypt)]
[[play](https://go.dev/play/p/74KmNadjN1J)]
- **<big>HmacMd5</big>** : return the md5 hmac hash of string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacMd5)]
[[play](https://go.dev/play/p/uef0q1fz53I)]
- **<big>HmacSha1</big>** : return the hmac hash of string use sha1.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha1)]
[[play](https://go.dev/play/p/1UI4oQ4WXKM)]
- **<big>HmacSha256</big>** : return the hmac hash of string use sha256.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha256)]
[[play](https://go.dev/play/p/HhpwXxFhhC0)]
- **<big>HmacSha512</big>** : return the hmac hash of string use sha512.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#HmacSha512)]
[[play](https://go.dev/play/p/59Od6m4A0Ud)]
- **<big>Md5String</big>** : return the md5 value of string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Md5String)]
[[play](https://go.dev/play/p/1bLcVetbTOI)]
- **<big>Md5File</big>** : return the md5 value of file.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Md5File)]
- **<big>Sha1</big>** : return the sha1 value (SHA-1 hash algorithm) of string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha1)]
[[play](https://go.dev/play/p/_m_uoD1deMT)]
- **<big>Sha256</big>** : return the sha256 value (SHA-256 hash algorithm) of string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha256)]
[[play](https://go.dev/play/p/tU9tfBMIAr1)]
- **<big>Sha512</big>** : return the sha512 value (SHA-512 hash algorithm) of string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#Sha512)]
[[play](https://go.dev/play/p/3WsvLYZxsHa)]
- **<big>GenerateRsaKey</big>** : create rsa private and public pemo file.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#GenerateRsaKey)]
[[play](https://go.dev/play/p/zutRHrDqs0X)]
- **<big>RsaEncrypt</big>** : encrypt data with ras algorithm.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#RsaEncrypt)]
[[play](https://go.dev/play/p/uef0q1fz53I)]
- **<big>RsaDecrypt</big>** : decrypt data with ras algorithm.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#RsaDecrypt)]
[[play](https://go.dev/play/p/uef0q1fz53I)]
### 6. Datetime package supports date and time format and compare. ### 6. Datetime package supports date and time format and compare.
@@ -285,36 +348,99 @@ import "github.com/duke-git/lancet/v2/datetime"
#### Function list: #### Function list:
- [AddDay](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddDay) - **<big>AddDay</big>** : add or sub day to the time.
- [AddHour](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddHour) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddDay)]
- [AddMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddMinute) [[play](https://go.dev/play/p/dIGbs_uTdFa)]
- [BeginOfMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMinute) - **<big>AddHour</big>** : add or sub day to the time.
- [BeginOfHour](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfHour) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddHour)]
- [BeginOfDay](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfDay) [[play](https://go.dev/play/p/rcMjd7OCsi5)]
- [BeginOfWeek](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfWeek) - **<big>AddMinute</big>** : add or sub day to the time.
- [BeginOfMonth](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMonth) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddMinute)]
- [BeginOfYear](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfYear) [[play](https://go.dev/play/p/nT1heB1KUUK)]
- [EndOfMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfMinute) - **<big>BeginOfMinute</big>** : return the date time at the begin of minute of specific date.
- [EndOfHour](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfHour) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMinute)]
- [EndOfDay](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfDay) [[play](https://go.dev/play/p/ieOLVJ9CiFT)]
- [EndOfWeek](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfWeek) - **<big>BeginOfHour</big>** : return the date time at the begin of hour of specific date.
- [EndOfMonth](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfMonth) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfHour)]
- [EndOfYear](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfYear) [[play](https://go.dev/play/p/GhdGFnDWpYs)]
- [GetNowDate](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNowDate) - **<big>BeginOfDay</big>** : return the date time at the begin of day of specific date.
- [GetNowTime](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNowTime) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfDay)]
- [GetNowDateTime](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNowDateTime) [[play](https://go.dev/play/p/94m_UT6cWs9)]
- [GetZeroHourTimestamp](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetZeroHourTimestamp) - **<big>BeginOfWeek</big>** : return the date time at the begin of week of specific date.
- [GetNightTimestamp](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNightTimestamp) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfWeek)]
- [FormatTimeToStr](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#FormatTimeToStr) [[play](https://go.dev/play/p/ynjoJPz7VNV)]
- [FormatStrToTime](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#FormatStrToTime) - **<big>BeginOfMonth</big>** : return the date time at the begin of month of specific date.
- [NewUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewUnix) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMonth)]
- [NewUnixNow](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewUnixNow) [[play](https://go.dev/play/p/bWXVFsmmzwL)]
- [NewFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewFormat) - **<big>BeginOfYear</big>** : return the date time at the begin of year of specific date.
- [NewISO8601](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewISO8601) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfYear)]
- [ToUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToUnix) [[play](https://go.dev/play/p/i326DSwLnV8)]
- [ToFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToFormat) - **<big>EndOfMinute</big>** : return the date time at the end of minute of specific date.
- [ToFormatForTpl](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToFormatForTpl) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfMinute)]
- [ToIso8601](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToIso8601) [[play](https://go.dev/play/p/yrL5wGzPj4z)]
- **<big>EndOfHour</big>** : return the date time at the end of hour of specific date.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfHour)]
[[play](https://go.dev/play/p/6ce3j_6cVqN)]
- **<big>EndOfDay</big>** : return the date time at the end of day of specific date.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfDay)]
[[play](https://go.dev/play/p/eMBOvmq5Ih1)]
- **<big>EndOfWeek</big>** : return the date time at the end of week of specific date.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfWeek)]
[[play](https://go.dev/play/p/i08qKXD9flf)]
- **<big>EndOfMonth</big>** : return the date time at the end of month of specific date.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfMonth)]
[[play](https://go.dev/play/p/_GWh10B3Nqi)]
- **<big>EndOfYear</big>** : return the date time at the end of year of specific date.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfYear)]
[[play](https://go.dev/play/p/G01cKlMCvNm)]
- **<big>GetNowDate</big>** : return format yyyy-mm-dd of current date.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNowDate)]
[[play](https://go.dev/play/p/PvfkPpcpBBf)]
- **<big>GetNowTime</big>** : return format hh-mm-ss of current time.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNowTime)]
[[play](https://go.dev/play/p/l7BNxCkTmJS)]
- **<big>GetNowDateTime</big>** : return format yyyy-mm-dd hh-mm-ss of current datetime.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNowDateTime)]
[[play](https://go.dev/play/p/pI4AqngD0al)]
- **<big>GetZeroHourTimestamp</big>** : return timestamp of zero hour (timestamp of 00:00).
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetZeroHourTimestamp)]
[[play](https://go.dev/play/p/QmL2oIaGE3q)]
- **<big>GetNightTimestamp</big>** : return timestamp of zero hour (timestamp of 23:59).
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#GetNightTimestamp)]
[[play](https://go.dev/play/p/UolysR3MYP1)]
- **<big>FormatTimeToStr</big>** : convert time to string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#FormatTimeToStr)]
[[play](https://go.dev/play/p/_Ia7M8H_OvE)]
- **<big>FormatStrToTime</big>** : convert string to time.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#FormatStrToTime)]
[[play](https://go.dev/play/p/1h9FwdU8ql4)]
- **<big>NewUnix</big>** : return unix timestamp of specific time.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewUnix)]
[[play](https://go.dev/play/p/psoSuh_kLRt)]
- **<big>NewUnixNow</big>** : return unix timestamp of current time.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewUnixNow)]
[[play](https://go.dev/play/p/U4PPx-9D0oz)]
- **<big>NewFormat</big>** : return unix timestamp of specific time string, t should be "yyyy-mm-dd hh:mm:ss".
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewFormat)]
[[play](https://go.dev/play/p/VkW08ZOaXPZ)]
- **<big>NewISO8601</big>** : return unix timestamp of specific iso8601 time string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#NewISO8601)]
[[play](https://go.dev/play/p/mkhOHQkdeA2)]
- **<big>ToUnix</big>** : return unix timestamp.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToUnix)]
[[play](https://go.dev/play/p/_LUiwAdocjy)]
- **<big>ToFormat</big>** : return the time string 'yyyy-mm-dd hh:mm:ss' of unix time.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToFormat)]
[[play](https://go.dev/play/p/VkW08ZOaXPZ)]
- **<big>ToFormatForTpl</big>** : return the time string which format is specific tpl.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToFormatForTpl)]
[[play](https://go.dev/play/p/nyXxXcQJ8L5)]
- **<big>ToIso8601</big>** : return iso8601 time string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToIso8601)]
[[play](https://go.dev/play/p/mkhOHQkdeA2)]
### 7. Datastructure package constains some common data structure. eg. list, linklist, stack, queue, set, tree, graph. ### 7. Datastructure package constains some common data structure. eg. list, linklist, stack, queue, set, tree, graph.
@@ -329,16 +455,24 @@ import heap "github.com/duke-git/lancet/v2/datastructure/heap"
import hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap" import hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
``` ```
#### Function list: #### Structure list:
- [List](https://github.com/duke-git/lancet/blob/main/docs/datastructure/list.md) - **<big>List</big>** : a linear table, implemented with slice.
- [Linklist](https://github.com/duke-git/lancet/blob/main/docs/datastructure/linklist.md) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/list.md)]
- [Stack](https://github.com/duke-git/lancet/blob/main/docs/datastructure/stack.md) - **<big>Link</big>** : link list structure, contains singly link and doubly link.
- [Queue](https://github.com/duke-git/lancet/blob/main/docs/datastructure/queue.md) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/link.md)]
- [Set](https://github.com/duke-git/lancet/blob/main/docs/datastructure/set.md) - **<big>Stack</big>** : stack structure(fifo), contains array stack and link stack.
- [Tree](https://github.com/duke-git/lancet/blob/main/docs/datastructure/tree.md) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/stack.md)]
- [Heap](https://github.com/duke-git/lancet/blob/main/docs/datastructure/heap.md) - **<big>Queue</big>** : queue structure(filo), contains array queue, circular queue, link queue and priority queue.
- [HashMap](https://github.com/duke-git/lancet/blob/main/docs/datastructure/hashmap.md) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/queue.md)]
- **<big>Set</big>** : a data container, like slice, but element of set is not duplicate.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/set.md)]
- **<big>Tree</big>** : binary search tree structure.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/tree.md)]
- **<big>Heap</big>** : a binary max heap.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/heap.md)]
- **<big>Hashmap</big>** : hash map structure.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/hashmap.md)]
### 8. Fileutil package implements some basic functions for file operations. ### 8. Fileutil package implements some basic functions for file operations.
@@ -439,8 +573,6 @@ import "github.com/duke-git/lancet/v2/function"
- **<big>Watcher</big>** : Watcher is used for record code excution time. can start/stop/reset the watch timer. get the elapsed time of function execution. - **<big>Watcher</big>** : Watcher is used for record code excution time. can start/stop/reset the watch timer. get the elapsed time of function execution.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function.md#Watcher)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/function.md#Watcher)]
### 11. Maputil package includes some functions to manipulate map. ### 11. Maputil package includes some functions to manipulate map.
```go ```go
@@ -526,26 +658,62 @@ import "github.com/duke-git/lancet/v2/netutil"
#### Function list: #### Function list:
- [ConvertMapToQueryString](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#ConvertMapToQueryString) - **<big>ConvertMapToQueryString</big>** : convert map to sorted url query string.
- [EncodeUrl](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#EncodeUrl) [[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#ConvertMapToQueryString)]
- [GetInternalIp](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetInternalIp) [[play](https://go.dev/play/p/jnNt_qoSnRi)]
- [GetIps](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetIps) - **<big>EncodeUrl</big>** : encode url(?a=1&b=[2] -> ?a=1&b=%5B2%5D).
- [GetMacAddrs](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetMacAddrs) [[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#EncodeUrl)]
- [GetPublicIpInfo](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetPublicIpInfo) [[play](https://go.dev/play/p/bsZ6BRC4uKI)]
- [GetRequestPublicIp](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetRequestPublicIp) - **<big>GetInternalIp</big>** : return internal ipv4.
- [IsPublicIP](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#IsPublicIP) [[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetInternalIp)]
- [IsInternalIP](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#IsInternalIP) [[play](https://go.dev/play/p/5mbu-gFp7ei)]
- [HttpRequest](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpRequest) - **<big>GetIps</big>** : return all ipv4 of current system.
- [HttpClient](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpClient) [[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetIps)]
- [SendRequest](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#SendRequest) [[play](https://go.dev/play/p/NUFfcEmukx1)]
- [DecodeResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#DecodeResponse) - **<big>GetMacAddrs</big>** : return mac address of current system.
- [StructToUrlValues](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#StructToUrlValues) [[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetMacAddrs)]
- [HttpGet<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpGet) [[play](https://go.dev/play/p/Rq9UUBS_Xp1)]
- [HttpDelete<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpDelete) - **<big>GetPublicIpInfo</big>** : return [public ip information](http://ip-api.com/json/).
- [HttpPost<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPost) [[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetPublicIpInfo)]
- [HttpPut<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPut) [[play](https://go.dev/play/p/YDxIfozsRHR)]
- [HttpPatch<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPatch) - **<big>GetRequestPublicIp</big>** : return the http request public ip.
- [ParseHttpResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#ParseHttpResponse) [[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetRequestPublicIp)]
[[play](https://go.dev/play/p/kxU-YDc_eBo)]
- **<big>IsPublicIP</big>** : verify a ip is public or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#IsPublicIP)]
[[play](https://go.dev/play/p/nmktSQpJZnn)]
- **<big>IsInternalIP</big>** : verify an ip is intranet or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#IsInternalIP)]
[[play](https://go.dev/play/p/sYGhXbgO4Cb)]
- **<big>HttpRequest</big>** : a composed http request used for HttpClient send request.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpRequest)]
[[play](https://go.dev/play/p/jUSgynekH7G)]
- **<big>HttpClient</big>** : a http client tool, used for sending http request
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpClient)]
[[play](https://go.dev/play/p/jUSgynekH7G)]
- **<big>SendRequest</big>** : send http request.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#SendRequest)]
[[play](https://go.dev/play/p/jUSgynekH7G)]
- **<big>DecodeResponse</big>** : decode http response into target object.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#DecodeResponse)]
[[play](https://go.dev/play/p/jUSgynekH7G)]
- **<big>StructToUrlValues</big>** : convert struct to url valuse.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#StructToUrlValues)]
[[play](https://go.dev/play/p/pFqMkM40w9z)]
- **<big>HttpGet<sup>deprecated</sup></big>** : send get http request.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpGet)]
- **<big>HttpDelete<sup>deprecated</sup></big>** : send delete http request.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpDelete)]
- **<big>HttpPost<sup>deprecated</sup></big>** : send post http request.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPost)]
- **<big>HttpPut<sup>deprecated</sup></big>** : send put http request.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPut)]
- **<big>HttpPatch<sup>deprecated</sup></big>** : send patch http request.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPatch)]
- **<big>ParseHttpResponse</big>** : decode http response into target object.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#ParseHttpResponse)]
### 14. Random package implements some basic functions to generate random int and string. ### 14. Random package implements some basic functions to generate random int and string.
@@ -561,7 +729,7 @@ import "github.com/duke-git/lancet/v2/random"
- **<big>RandInt</big>** : generate random int number between min and max. - **<big>RandInt</big>** : generate random int number between min and max.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandInt)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandInt)]
[[play](https://go.dev/play/p/pXyyAAI5YxD)] [[play](https://go.dev/play/p/pXyyAAI5YxD)]
- **<big>RandString</big>** : generate random string of specified length. - **<big>RandString</big>** : generate random string of specific length.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandString)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandString)]
[[play](https://go.dev/play/p/W2xvRUXA7Mi)] [[play](https://go.dev/play/p/W2xvRUXA7Mi)]
- **<big>RandUpper</big>** : generate a random upper case string. - **<big>RandUpper</big>** : generate a random upper case string.
@@ -570,7 +738,7 @@ import "github.com/duke-git/lancet/v2/random"
- **<big>RandLower</big>** : generate a random lower case string. - **<big>RandLower</big>** : generate a random lower case string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandLower)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandLower)]
[[play](https://go.dev/play/p/XJtZ471cmtI)] [[play](https://go.dev/play/p/XJtZ471cmtI)]
- **<big>RandNumeral</big>** : generate a random numeral string of specified length. - **<big>RandNumeral</big>** : generate a random numeral string of specific length.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandNumeral)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandNumeral)]
[[play](https://go.dev/play/p/g4JWVpHsJcf)] [[play](https://go.dev/play/p/g4JWVpHsJcf)]
- **<big>RandNumeralOrLetter</big>** : generate a random numeral or letter string. - **<big>RandNumeralOrLetter</big>** : generate a random numeral or letter string.
@@ -588,11 +756,21 @@ import "github.com/duke-git/lancet/v2/retry"
#### Function list: #### Function list:
- [Context](https://github.com/duke-git/lancet/blob/main/docs/retry.md#Context) - **<big>Context</big>** : set retry context config option.
- [Retry](https://github.com/duke-git/lancet/blob/main/docs/retry.md#Retry) [[doc](https://github.com/duke-git/lancet/blob/main/docs/retry.md#Context)]
- [RetryFunc](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryFunc) [[play](https://go.dev/play/p/xnAOOXv9GkS)]
- [RetryDuration](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryDuration) - **<big>Retry</big>** : executes the retryFunc repeatedly until it was successful or canceled by the context.
- [RetryTimes](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryTimes) [[doc](https://github.com/duke-git/lancet/blob/main/docs/retry.md#Retry)]
[[play](https://go.dev/play/p/nk2XRmagfVF)]
- **<big>RetryFunc</big>** : function that retry executes.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryFunc)]
[[play](https://go.dev/play/p/nk2XRmagfVF)]
- **<big>RetryDuration</big>** : set duration of retry
[[doc](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryDuration)]
[[play](https://go.dev/play/p/nk2XRmagfVF)]
- **<big>RetryTimes</big>** : set times of retry.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryTimes)]
[[play](https://go.dev/play/p/ssfVeU2SwLO)]
### 16. Slice contains some functions to manipulate slice. ### 16. Slice contains some functions to manipulate slice.
@@ -770,15 +948,15 @@ import "github.com/duke-git/lancet/v2/strutil"
#### Function list: #### Function list:
- **<big>After</big>** : returns the substring after the first occurrence of a specified string in the source string. - **<big>After</big>** : returns the substring after the first occurrence of a specific string in the source string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#After)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#After)]
[[play](https://go.dev/play/p/RbCOQqCDA7m)] [[play](https://go.dev/play/p/RbCOQqCDA7m)]
- **<big>AfterLast</big>** : returns the substring after the last occurrence of a specified string in the source string. [[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#AfterLast)] - **<big>AfterLast</big>** : returns the substring after the last occurrence of a specific string in the source string. [[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#AfterLast)]
[[play](https://go.dev/play/p/1TegARrb8Yn)] [[play](https://go.dev/play/p/1TegARrb8Yn)]
- **<big>Before</big>** : returns the substring before the first occurrence of a specified string in the source string. - **<big>Before</big>** : returns the substring before the first occurrence of a specific string in the source string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Before)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Before)]
[[play](https://go.dev/play/p/JAWTZDS4F5w)] [[play](https://go.dev/play/p/JAWTZDS4F5w)]
- **<big>BeforeLast</big>** : returns the substring before the last occurrence of a specified string in the source string. - **<big>BeforeLast</big>** : returns the substring before the last occurrence of a specific string in the source string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#BeforeLast)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#BeforeLast)]
[[play](https://go.dev/play/p/pJfXXAoG_Te)] [[play](https://go.dev/play/p/pJfXXAoG_Te)]
- **<big>CamelCase</big>** : coverts source string to its camelCase string. - **<big>CamelCase</big>** : coverts source string to its camelCase string.
@@ -820,7 +998,7 @@ import "github.com/duke-git/lancet/v2/strutil"
- **<big>SplitEx</big>** : split a given string which can control the result slice contains empty string or not. - **<big>SplitEx</big>** : split a given string which can control the result slice contains empty string or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SplitEx)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SplitEx)]
[[play](https://go.dev/play/p/Us-ySSbWh-3)] [[play](https://go.dev/play/p/Us-ySSbWh-3)]
- **<big>Substring</big>** : returns a substring of the specified length starting at the specified offset position. - **<big>Substring</big>** : returns a substring of the specific length starting at the specific offset position.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Substring)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Substring)]
- **<big>Wrap</big>** : wrap a string with given string. - **<big>Wrap</big>** : wrap a string with given string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Wrap)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Wrap)]
@@ -966,7 +1144,10 @@ import "github.com/duke-git/lancet/v2/xerror"
#### Function list: #### Function list:
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#Unwrap) - **<big>Unwrap</big>** : check if err is nil then it returns a valid value. If err is not nil, Unwrap panics with err.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror.md#Unwrap)]
[[play](https://go.dev/play/p/w84d7Mb3Afk)]
## How to Contribute ## How to Contribute

View File

@@ -4,7 +4,7 @@
<br/> <br/>
![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf) ![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf)
[![Release](https://img.shields.io/badge/release-2.1.12-green.svg)](https://github.com/duke-git/lancet/releases) [![Release](https://img.shields.io/badge/release-2.1.13-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2) [![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2) [![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
[![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml) [![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
@@ -170,7 +170,7 @@ import "github.com/duke-git/lancet/v2/condition"
[[play](https://go.dev/play/p/g2j08F_zZky) [[play](https://go.dev/play/p/g2j08F_zZky)
- **<big>Xnor</big>** : 如果 a 和 b 都是真的或 a 和 b 均是假的,则返回 true。 - **<big>Xnor</big>** : 如果 a 和 b 都是真的或 a 和 b 均是假的,则返回 true。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Xnor)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Xnor)]
[[play](https://go.dev/play/p/OuDB9g51643)] [[play](https://go.dev/play/p/OuDB9g51643)]]
- **<big>Nand</big>** : 如果 a 和 b 都为真,返回 false否则返回 true - **<big>Nand</big>** : 如果 a 和 b 都为真,返回 false否则返回 true
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Nand)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Nand)]
[[play](https://go.dev/play/p/vSRMLxLIbq8)] [[play](https://go.dev/play/p/vSRMLxLIbq8)]
@@ -243,38 +243,103 @@ import "github.com/duke-git/lancet/v2/cryptor"
#### 函数列表: #### 函数列表:
- [AesEcbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesEcbEncrypt) - **<big>AesEcbEncrypt</big>** : 使用AES ECB算法模式加密数据。
- [AesEcbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesEcbDecrypt) [[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesEcbEncrypt)]
- [AesCbcEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCbcEncrypt) [[play](https://go.dev/play/p/zI6xsmuQRbn)]
- [AesCbcDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCbcDecrypt) - **<big>AesEcbDecrypt</big>** : 使用AES ECB算法模解密数据。
- [AesCtrCrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCtrCrypt) [[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesEcbDecrypt)]
- [AesCfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCfbEncrypt) [[play](https://go.dev/play/p/zI6xsmuQRbn)]
- [AesCfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCfbDecrypt) - **<big>AesCbcEncrypt</big>** : 使用AES CBC算法模式加密数据。
- [AesOfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesOfbEncrypt) [[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCbcEncrypt)]
- [AesOfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesOfbDecrypt) [[play](https://go.dev/play/p/IOq_g8_lKZD)]
- [Base64StdEncode](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Base64StdEncode) - **<big>AesCbcDecrypt</big>** : 使用AES CBC算法模式解密数据。
- [Base64StdDecode](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Base64StdDecode) [[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCbcDecrypt)]
- [DesEcbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesEcbEncrypt) [[play](https://go.dev/play/p/IOq_g8_lKZD)]
- [DesEcbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesEcbDecrypt) - **<big>AesCtrCrypt</big>** : 使用AES CTR算法模式加密/解密数据。
- [DesCbcEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCbcEncrypt) [[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCtrCrypt)]
- [DesCbcDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCbcDecrypt) [[play](https://go.dev/play/p/SpaZO0-5Nsp)]
- [DesCtrCrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCtrCrypt) - **<big>AesCfbEncrypt</big>** : 使用AES CFB算法模式加密数据。
- [DesCfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCfbEncrypt) [[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCfbEncrypt)]
- [DesCfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCfbDecrypt) [[play](https://go.dev/play/p/tfkF10B13kH)]
- [DesOfbEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesOfbEncrypt) - **<big>AesCfbDecrypt</big>** : 使用AES CFB算法模式解密数据。
- [DesOfbDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesOfbDecrypt) [[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesCfbDecrypt)]
- [HmacMd5](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacMd5) [[play](https://go.dev/play/p/tfkF10B13kH)]
- [HmacSha1](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha1) - **<big>AesOfbEncrypt</big>** : 使用AES OFB算法模式加密数据。
- [HmacSha256](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha256) [[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesOfbEncrypt)]
- [HmacSha512](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha512) [[play](https://go.dev/play/p/VtHxtkUj-3F)]
- [Md5String](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Md5String) - **<big>AesOfbDecrypt</big>** : 使用AES OFB算法模式解密数据。
- [Md5File](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Md5File) [[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#AesOfbDecrypt)]
- [Sha1](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha1) [[play](https://go.dev/play/p/VtHxtkUj-3F)]
- [Sha256](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha256) - **<big>Base64StdEncode</big>** : 将字符串base64编码。
- [Sha512](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha512) [[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Base64StdEncode)]
- [GenerateRsaKey](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#GenerateRsaKey) [[play](https://go.dev/play/p/VOaUyQUreoK)]
- [RsaEncrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#RsaEncrypt) - **<big>Base64StdDecode</big>** : 解码base64字符串。
- [RsaDecrypt](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#RsaDecrypt) [[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Base64StdDecode)]
[[play](https://go.dev/play/p/RWQylnJVgIe)]
- **<big>DesEcbEncrypt</big>** : 使用DES ECB算法模式加密数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesEcbEncrypt)]
[[play](https://go.dev/play/p/8qivmPeZy4P)]
- **<big>DesEcbDecrypt</big>** : 使用DES ECB算法模解密数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesEcbDecrypt)]
[[play](https://go.dev/play/p/8qivmPeZy4P)]
- **<big>DesCbcEncrypt</big>** : 使用DES CBC算法模式加密数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCbcEncrypt)]
[[play](https://go.dev/play/p/4cC4QvWfe3_1)]
- **<big>DesCbcDecrypt</big>** : 使用DES CBC算法模式解密数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCbcDecrypt)]
[[play](https://go.dev/play/p/4cC4QvWfe3_1)]
- **<big>DesCtrCrypt</big>** : 使用DES CTR算法模式加密/解密数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCtrCrypt)]
[[play](https://go.dev/play/p/9-T6OjKpcdw)]
- **<big>DesCfbEncrypt</big>** : 使用DES CFB算法模式加密数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCfbEncrypt)]
[[play](https://go.dev/play/p/y-eNxcFBlxL)]
- **<big>DesCfbDecrypt</big>** : 使用DES CFB算法模式解密数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesCfbDecrypt)]
[[play](https://go.dev/play/p/y-eNxcFBlxL)]
- **<big>DesOfbEncrypt</big>** : 使用DES OFB算法模式加密数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesOfbEncrypt)]
[[play](https://go.dev/play/p/74KmNadjN1J)]
- **<big>DesOfbDecrypt</big>** : 使用DES OFB算法模式解密数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#DesOfbDecrypt)]
[[play](https://go.dev/play/p/74KmNadjN1J)]
- **<big>HmacMd5</big>** : 返回字符串md5 hmac值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacMd5)]
[[play](https://go.dev/play/p/uef0q1fz53I)]
- **<big>HmacSha1</big>** : 返回字符串sha1 hmac值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha1)]
[[play](https://go.dev/play/p/1UI4oQ4WXKM)]
- **<big>HmacSha256</big>** : 返回字符串sha256 hmac值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha256)]
[[play](https://go.dev/play/p/HhpwXxFhhC0)]
- **<big>HmacSha512</big>** : 返回字符串sha256 hmac值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#HmacSha512)]
[[play](https://go.dev/play/p/59Od6m4A0Ud)]
- **<big>Md5String</big>** : 返回字符串md5值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Md5String)]
[[play](https://go.dev/play/p/1bLcVetbTOI)]
- **<big>Md5File</big>** : 返回文件md5值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Md5File)]
- **<big>Sha1</big>** : 返回字符串sha1哈希值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha1)]
[[play](https://go.dev/play/p/_m_uoD1deMT)]
- **<big>Sha256</big>** :返回字符串sha256哈希值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha256)]
[[play](https://go.dev/play/p/tU9tfBMIAr1)]
- **<big>Sha512</big>** : 返回字符串sha512哈希值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#Sha512)]
[[play](https://go.dev/play/p/3WsvLYZxsHa)]
- **<big>GenerateRsaKey</big>** : 在当前目录下创建rsa私钥文件和公钥文件。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#GenerateRsaKey)]
[[play](https://go.dev/play/p/zutRHrDqs0X)]
- **<big>RsaEncrypt</big>** : 用公钥文件ras加密数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#RsaEncrypt)]
[[play](https://go.dev/play/p/uef0q1fz53I)]
- **<big>RsaDecrypt</big>** : 用私钥文件rsa解密数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#RsaDecrypt)]
[[play](https://go.dev/play/p/uef0q1fz53I)]
### 6. datetime 日期时间处理包,格式化日期,比较日期。 ### 6. datetime 日期时间处理包,格式化日期,比较日期。
@@ -284,36 +349,98 @@ import "github.com/duke-git/lancet/v2/datetime"
#### 函数列表: #### 函数列表:
- [AddDay](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddDay) - **<big>AddDay</big>** : 将日期加/减天数。
- [AddHour](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddHour) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddDay)]
- [AddMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddMinute) [[play](https://go.dev/play/p/dIGbs_uTdFa)]
- [BeginOfMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMinute) - **<big>AddHour</big>** : 将日期加/减小时数。
- [BeginOfHour](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfHour) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddHour)]
- [BeginOfDay](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfDay) [[play](https://go.dev/play/p/rcMjd7OCsi5)]
- [BeginOfWeek](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfWeek) - **<big>AddMinute</big>** : 将日期加/减分钟数。
- [BeginOfMonth](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMonth) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddMinute)]
- [BeginOfYear](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfYear) [[play](https://go.dev/play/p/nT1heB1KUUK)]
- [EndOfMinute](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfMinute) - **<big>BeginOfMinute</big>** : 返回指定时间的分钟开始时间。
- [EndOfHour](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfHour) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#BeginOfMinute)]
- [EndOfDay](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfDay) [[play](https://go.dev/play/p/ieOLVJ9CiFT)]
- [EndOfWeek](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfWeek) - **<big>BeginOfHour</big>** : 返回指定时间的小时开始时间。
- [EndOfMonth](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfMonth) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#BeginOfHour)]
- [EndOfYear](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#EndOfYear) [[play](https://go.dev/play/p/GhdGFnDWpYs)]
- [GetNowDate](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNowDate) - **<big>BeginOfDay</big>** : 返回指定时间的当天开始时间。
- [GetNowTime](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNowTime) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#BeginOfDay)]
- [GetNowDateTime](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNowDateTime) [[play](https://go.dev/play/p/94m_UT6cWs9)]
- [GetZeroHourTimestamp](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetZeroHourTimestamp) - **<big>BeginOfWeek</big>** : 返回指定时间的每周开始时间,默认开始时间星期日。
- [GetNightTimestamp](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNightTimestamp) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#BeginOfWeek)]
- [FormatTimeToStr](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#FormatTimeToStr) [[play](https://go.dev/play/p/ynjoJPz7VNV)]
- [FormatStrToTime](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#FormatStrToTime) - **<big>BeginOfMonth</big>** : 返回指定时间的当月开始时间。
- [NewUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewUnix) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#BeginOfMonth)]
- [NewUnixNow](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewUnixNow) [[play](https://go.dev/play/p/bWXVFsmmzwL)]
- [NewFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewFormat) - **<big>BeginOfYear</big>** : 返回指定时间的当年开始时间。
- [NewISO8601](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewISO8601) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#BeginOfYear)]
- [ToUnix](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToUnix) [[play](https://go.dev/play/p/i326DSwLnV8)]
- [ToFormat](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToFormat) - **<big>EndOfMinute</big>** : 返回指定时间的分钟结束时间。
- [ToFormatForTpl](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToFormatForTpl) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#EndOfMinute)]
- [ToIso8601](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToIso8601) [[play](https://go.dev/play/p/yrL5wGzPj4z)]
- **<big>EndOfHour</big>** : 返回指定时间的小时结束时间。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#EndOfHour)]
[[play](https://go.dev/play/p/6ce3j_6cVqN)]
- **<big>EndOfDay</big>** : 返回指定时间的当天结束时间。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#EndOfDay)]
[[play](https://go.dev/play/p/eMBOvmq5Ih1)]
- **<big>EndOfWeek</big>** : 返回指定时间的星期结束时间,默认结束时间星期六。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#EndOfWeek)]
[[play](https://go.dev/play/p/i08qKXD9flf)]
- **<big>EndOfMonth</big>** : 返回指定时间的月份结束时间。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#EndOfMonth)]
[[play](https://go.dev/play/p/_GWh10B3Nqi)]
- **<big>EndOfYear</big>** : 返回指定时间的年份结束时间。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#EndOfYear)]
[[play](https://go.dev/play/p/G01cKlMCvNm)]
- **<big>GetNowDate</big>** : 获取当天日期返回格式yyyy-mm-dd。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNowDate)]
[[play](https://go.dev/play/p/PvfkPpcpBBf)]
- **<big>GetNowTime</big>** : 获取当时时间返回格式hh:mm:ss。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNowTime)]
[[play](https://go.dev/play/p/l7BNxCkTmJS)]
- **<big>GetNowDateTime</big>** : 获取当时日期和时间返回格式yyyy-mm-dd hh:mm:ss。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNowDateTime)]
[[play](https://go.dev/play/p/pI4AqngD0al)]
- **<big>GetZeroHourTimestamp</big>** : 获取零时时间戳(timestamp of 00:00)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetZeroHourTimestamp)]
[[play](https://go.dev/play/p/QmL2oIaGE3q)]
- **<big>GetNightTimestamp</big>** : 获取午夜时间戳(timestamp of 23:59)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#GetNightTimestamp)]
[[play](https://go.dev/play/p/UolysR3MYP1)]
- **<big>FormatTimeToStr</big>** : 将日期格式化成字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#FormatTimeToStr)]
[[play](https://go.dev/play/p/_Ia7M8H_OvE)]
- **<big>FormatStrToTime</big>** : 将字符串格式化成时间。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#FormatStrToTime)]
[[play](https://go.dev/play/p/1h9FwdU8ql4)]
- **<big>NewUnix</big>** : 创建一个unix时间戳。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewUnix)]
[[play](https://go.dev/play/p/psoSuh_kLRt)]
- **<big>NewUnixNow</big>** : 创建一个当前时间的unix时间戳。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewUnixNow)]
[[play](https://go.dev/play/p/U4PPx-9D0oz)]
- **<big>NewFormat</big>** : 创建一个yyyy-mm-dd hh:mm:ss格式时间字符串的unix时间戳。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewFormat)]
[[play](https://go.dev/play/p/VkW08ZOaXPZ)]
- **<big>NewISO8601</big>** : 创建一个iso8601格式时间字符串的unix时间戳。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#NewISO8601)]
[[play](https://go.dev/play/p/mkhOHQkdeA2)]
- **<big>ToUnix</big>** : 返回unix时间戳。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToUnix)]
[[play](https://go.dev/play/p/_LUiwAdocjy)]
- **<big>ToFormat</big>** : 返回格式'yyyy-mm-dd hh:mm:ss'的日期字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToFormat)]
[[play](https://go.dev/play/p/VkW08ZOaXPZ)]
- **<big>ToFormatForTpl</big>** : 返回tpl格式指定的日期字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToFormatForTpl)]
[[play](https://go.dev/play/p/nyXxXcQJ8L5)]
- **<big>ToIso8601</big>** : 返回iso8601日期字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToIso8601)]
[[play](https://go.dev/play/p/mkhOHQkdeA2)]
### 7. datastructure 包含一些普通的数据结构实现。例如list, linklist, stack, queue, set, tree, graph. ### 7. datastructure 包含一些普通的数据结构实现。例如list, linklist, stack, queue, set, tree, graph.
@@ -330,14 +457,25 @@ import hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
#### Function list: #### Function list:
- [List](https://github.com/duke-git/lancet/blob/main/docs/datastructure/list_zh-CN.md) - **<big>List</big>** : 线性表结构, 用切片实现。
- [Linklist](https://github.com/duke-git/lancet/blob/main/docs/datastructure/linklist_zh-CN.md) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/list_zh-CN.md)]
- [Stack](https://github.com/duke-git/lancet/blob/main/docs/datastructure/stack_zh-CN.md) - **<big>Link</big>** : 链表解构, 包括单链表和双向链表。
- [Queue](https://github.com/duke-git/lancet/blob/main/docs/datastructure/queue_zh-CN.md) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/link_zh-CN.md)]
- [Set](https://github.com/duke-git/lancet/blob/main/docs/datastructure/set_zh-CN.md) - **<big>Stack</big>** : 栈结构(fifo), 包括数组栈和链表栈。
- [Tree](https://github.com/duke-git/lancet/blob/main/docs/datastructure/tree_zh-CN.md) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/stack_zh-CN.md)]
- [Heap](https://github.com/duke-git/lancet/blob/main/docs/datastructure/heap.md) - **<big>Queue</big>** : 队列结构(filo), 包括数组队列,链表队列,循环队列,优先级队列。
- [HashMap](https://github.com/duke-git/lancet/blob/main/docs/datastructure/hashmap.md) [[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/queue_zh-CN.md)]
- **<big>Set</big>** : 集合set结构。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/set_zh-CN.md)]
- **<big>Tree</big>** : 二叉搜索树。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/tree_zh-CN.md)]
- **<big>Heap</big>** : 二叉max堆。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/heap_zh-CN.md)]
- **<big>Hashmap</big>** : 哈希映射。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/hashmap_zh-CN.md)]
### 8. fileutil 包含文件基本操作。 ### 8. fileutil 包含文件基本操作。
@@ -524,26 +662,63 @@ import "github.com/duke-git/lancet/v2/netutil"
#### 函数列表: #### 函数列表:
- [ConvertMapToQueryString](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#ConvertMapToQueryString) - **<big>ConvertMapToQueryString</big>** : 将map转换成http查询字符串。
- [GetInternalIp](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetInternalIp) [[doc](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) [[play](https://go.dev/play/p/jnNt_qoSnRi)]
- [GetIps](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetIps) - **<big>EncodeUrl</big>** : 编码url query string的值(?a=1&b=[2] -> ?a=1&b=%5B2%5D)。
- [GetMacAddrs](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#GetMacAddrs) [[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#EncodeUrl)]
- [GetPublicIpInfo](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetPublicIpInfo) [[play](https://go.dev/play/p/bsZ6BRC4uKI)]
- [GetRequestPublicIp](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetRequestPublicIp) - **<big>GetInternalIp</big>** : 获取内部ipv4。
- [IsPublicIP](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#IsPublicIP) [[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetInternalIp)]
- [IsInternalIP](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#IsInternalIP) [[play](https://go.dev/play/p/5mbu-gFp7ei)]
- [HttpRequest](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpRequest) - **<big>GetIps</big>** : 获取系统ipv4地址列表。
- [HttpClient](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpClient) [[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetIps)]
- [SendRequest](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#SendRequest) [[play](https://go.dev/play/p/NUFfcEmukx1)]
- [DecodeResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#DecodeResponse) - **<big>GetMacAddrs</big>** : 获取系统mac地址列。
- [StructToUrlValues](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#StructToUrlValues) [[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetMacAddrs)]
- [HttpGet<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpGet) [[play](https://go.dev/play/p/Rq9UUBS_Xp1)]
- [HttpDelete<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpDelete) - **<big>GetPublicIpInfo</big>** : 获取[公网ip信息](http://ip-api.com/json/).
- [HttpPost<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPost) [[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetPublicIpInfo)]
- [HttpPut<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPut) [[play](https://go.dev/play/p/YDxIfozsRHR)]
- [HttpPatch<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPatch) - **<big>GetRequestPublicIp</big>** : 获取http请求ip。
- [ParseHttpResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#ParseHttpResponse) [[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#GetRequestPublicIp)]
[[play](https://go.dev/play/p/kxU-YDc_eBo)]
- **<big>IsPublicIP</big>** : 判断ip是否是公共ip。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#IsPublicIP)]
[[play](https://go.dev/play/p/nmktSQpJZnn)]
- **<big>IsInternalIP</big>** : 判断ip是否是局域网ip。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#IsInternalIP)]
[[play](https://go.dev/play/p/sYGhXbgO4Cb)]
- **<big>HttpRequest</big>** : 用于抽象HTTP请求实体的结构。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpRequest)]
[[play](https://go.dev/play/p/jUSgynekH7G)]
- **<big>HttpClient</big>** : 用于发送HTTP请求。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpClient)]
[[play](https://go.dev/play/p/jUSgynekH7G)]
- **<big>SendRequest</big>** : 发送http请求。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#SendRequest)]
[[play](https://go.dev/play/p/jUSgynekH7G)]
- **<big>DecodeResponse</big>** : 解析http响应体到目标结构体。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#DecodeResponse)]
[[play](https://go.dev/play/p/jUSgynekH7G)]
- **<big>StructToUrlValues</big>** : 将结构体转为url values, 仅转化结构体导出字段并且包含`json` tag。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#StructToUrlValues)]
[[play](https://go.dev/play/p/pFqMkM40w9z)]
- **<big>HttpGet<sup>deprecated</sup></big>** : 发送http get请求已弃用SendRequest代替
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpGet)]
- **<big>HttpDelete<sup>deprecated</sup></big>** : 发送http delete请求已弃用SendRequest代替
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpDelete)]
- **<big>HttpPost<sup>deprecated</sup></big>** : 发送http post请求已弃用SendRequest代替
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPost)]
- **<big>HttpPut<sup>deprecated</sup></big>** : 发送http put请求已弃用SendRequest代替
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPut)]
- **<big>HttpPatch<sup>deprecated</sup></big>** : 发送http patch请求已弃用SendRequest代替
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPatch)]
- **<big>ParseHttpResponse</big>** : 解析http响应体到目标结构体。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#ParseHttpResponse)]
### 14. random 随机数生成器包,可以生成随机[]bytes, int, string。 ### 14. random 随机数生成器包,可以生成随机[]bytes, int, string。
@@ -588,11 +763,23 @@ import "github.com/duke-git/lancet/v2/retry"
#### 函数列表: #### 函数列表:
- [Context](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#Context) - **<big>Context</big>** : 设置重试context参数。
- [Retry](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#Retry) [[doc](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#Context)]
- [RetryFunc](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryFunc) [[play](https://go.dev/play/p/xnAOOXv9GkS)]
- [RetryDuration](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryDuration) - **<big>Retry</big>** : 重试执行函数retryFunc直到函数运行成功或被context取消。
- [RetryTimes](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryTimes) [[doc](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#Retry)]
[[play](https://go.dev/play/p/nk2XRmagfVF)]
- **<big>RetryFunc</big>** : 重试执行的函数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryFunc)]
[[play](https://go.dev/play/p/nk2XRmagfVF)]
- **<big>RetryDuration</big>** : 设置重试间隔时间默认3秒。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryDuration)]
[[play](https://go.dev/play/p/nk2XRmagfVF)]
- **<big>RetryTimes</big>** : 设置重试次数默认5。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryTimes)]
[[play](https://go.dev/play/p/ssfVeU2SwLO)]
### 16. slice 包含操作切片的方法集合。 ### 16. slice 包含操作切片的方法集合。
@@ -968,6 +1155,11 @@ import "github.com/duke-git/lancet/v2/xerror"
#### 函数列表: #### 函数列表:
- **<big>Unwrap</big>** : 检查error, 如果err为nil则展开则它返回一个有效值如果err不是nil则Unwrap使用err发生panic。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#Unwrap)]
[[play](https://go.dev/play/p/w84d7Mb3Afk)]
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#Unwrap) - [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/xerror_zh-CN.md#Unwrap)
## 如何贡献代码 ## 如何贡献代码

View File

@@ -10,6 +10,7 @@ import "github.com/duke-git/lancet/v2/lancetconstraints"
// LinearSearch return the index of target in slice base on equal function. // LinearSearch return the index of target in slice base on equal function.
// If not found return -1 // If not found return -1
// Play: Todo
func LinearSearch[T any](slice []T, target T, equal func(a, b T) bool) int { func LinearSearch[T any](slice []T, target T, equal func(a, b T) bool) int {
for i, v := range slice { for i, v := range slice {
if equal(v, target) { if equal(v, target) {

View File

@@ -20,7 +20,7 @@ func NewChannel[T any]() *Channel[T] {
} }
// Generate creates channel, then put values into the channel. // Generate creates channel, then put values into the channel.
// Play: // Play: Todo
func (c *Channel[T]) Generate(ctx context.Context, values ...T) <-chan T { func (c *Channel[T]) Generate(ctx context.Context, values ...T) <-chan T {
dataStream := make(chan T) dataStream := make(chan T)
@@ -40,7 +40,7 @@ func (c *Channel[T]) Generate(ctx context.Context, values ...T) <-chan T {
} }
// Repeat create channel, put values into the channel repeatly until cancel the context. // Repeat create channel, put values into the channel repeatly until cancel the context.
// Play: // Play: Todo
func (c *Channel[T]) Repeat(ctx context.Context, values ...T) <-chan T { func (c *Channel[T]) Repeat(ctx context.Context, values ...T) <-chan T {
dataStream := make(chan T) dataStream := make(chan T)
@@ -61,7 +61,7 @@ func (c *Channel[T]) Repeat(ctx context.Context, values ...T) <-chan T {
// RepeatFn create a channel, excutes fn repeatly, and put the result into the channel // RepeatFn create a channel, excutes fn repeatly, and put the result into the channel
// until close context. // until close context.
// Play: // Play: Todo
func (c *Channel[T]) RepeatFn(ctx context.Context, fn func() T) <-chan T { func (c *Channel[T]) RepeatFn(ctx context.Context, fn func() T) <-chan T {
dataStream := make(chan T) dataStream := make(chan T)
@@ -79,7 +79,7 @@ func (c *Channel[T]) RepeatFn(ctx context.Context, fn func() T) <-chan T {
} }
// Take create a channel whose values are taken from another channel with limit number. // Take create a channel whose values are taken from another channel with limit number.
// Play: // Play: Todo
func (c *Channel[T]) Take(ctx context.Context, valueStream <-chan T, number int) <-chan T { func (c *Channel[T]) Take(ctx context.Context, valueStream <-chan T, number int) <-chan T {
takeStream := make(chan T) takeStream := make(chan T)
@@ -99,7 +99,7 @@ func (c *Channel[T]) Take(ctx context.Context, valueStream <-chan T, number int)
} }
// FanIn merge multiple channels into one channel. // FanIn merge multiple channels into one channel.
// Play: // Play: Todo
func (c *Channel[T]) FanIn(ctx context.Context, channels ...<-chan T) <-chan T { func (c *Channel[T]) FanIn(ctx context.Context, channels ...<-chan T) <-chan T {
out := make(chan T) out := make(chan T)
@@ -127,7 +127,7 @@ func (c *Channel[T]) FanIn(ctx context.Context, channels ...<-chan T) <-chan T {
} }
// Tee split one chanel into two channels, until cancel the context. // Tee split one chanel into two channels, until cancel the context.
// Play: // Play: Todo
func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T) { func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T) {
out1 := make(chan T) out1 := make(chan T)
out2 := make(chan T) out2 := make(chan T)
@@ -154,7 +154,7 @@ func (c *Channel[T]) Tee(ctx context.Context, in <-chan T) (<-chan T, <-chan T)
} }
// Bridge link multiply channels into one channel. // Bridge link multiply channels into one channel.
// Play: // Play: Todo
func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T { func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-chan T {
valStream := make(chan T) valStream := make(chan T)
@@ -186,7 +186,7 @@ func (c *Channel[T]) Bridge(ctx context.Context, chanStream <-chan <-chan T) <-c
} }
// Or read one or more channels into one channel, will close when any readin channel is closed. // Or read one or more channels into one channel, will close when any readin channel is closed.
// Play: // Play: Todo
func (c *Channel[T]) Or(channels ...<-chan T) <-chan T { func (c *Channel[T]) Or(channels ...<-chan T) <-chan T {
switch len(channels) { switch len(channels) {
case 0: case 0:
@@ -220,7 +220,7 @@ func (c *Channel[T]) Or(channels ...<-chan T) <-chan T {
} }
// OrDone read a channel into another channel, will close until cancel context. // OrDone read a channel into another channel, will close until cancel context.
// Play: // Play: Todo
func (c *Channel[T]) OrDone(ctx context.Context, channel <-chan T) <-chan T { func (c *Channel[T]) OrDone(ctx context.Context, channel <-chan T) <-chan T {
valStream := make(chan T) valStream := make(chan T)

View File

@@ -1,186 +0,0 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package cryptor implements some util functions to encrypt and decrypt.
// Note:
// 1. for aes crypt function, the `key` param length should be 16, 24 or 32. if not, will panic.
package cryptor
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"io"
)
// AesEcbEncrypt encrypt data with key use AES ECB algorithm
// len(key) should be 16, 24 or 32
func AesEcbEncrypt(data, key []byte) []byte {
length := (len(data) + aes.BlockSize) / aes.BlockSize
plain := make([]byte, length*aes.BlockSize)
copy(plain, data)
pad := byte(len(plain) - len(data))
for i := len(data); i < len(plain); i++ {
plain[i] = pad
}
encrypted := make([]byte, len(plain))
cipher, _ := aes.NewCipher(generateAesKey(key))
for bs, be := 0, cipher.BlockSize(); bs <= len(data); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
}
return encrypted
}
// AesEcbDecrypt decrypt data with key use AES ECB algorithm
// len(key) should be 16, 24 or 32
func AesEcbDecrypt(encrypted, key []byte) []byte {
cipher, _ := aes.NewCipher(generateAesKey(key))
decrypted := make([]byte, len(encrypted))
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
}
trim := 0
if len(decrypted) > 0 {
trim = len(decrypted) - int(decrypted[len(decrypted)-1])
}
return decrypted[:trim]
}
// AesCbcEncrypt encrypt data with key use AES CBC algorithm
// len(key) should be 16, 24 or 32
func AesCbcEncrypt(data, key []byte) []byte {
block, _ := aes.NewCipher(key)
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)
return encrypted
}
// AesCbcDecrypt decrypt data with key use AES CBC algorithm
// len(key) should be 16, 24 or 32
func AesCbcDecrypt(encrypted, key []byte) []byte {
block, _ := aes.NewCipher(key)
iv := encrypted[:aes.BlockSize]
encrypted = encrypted[aes.BlockSize:]
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(encrypted, encrypted)
decrypted := pkcs7UnPadding(encrypted)
return decrypted
}
// AesCtrCrypt encrypt data with key use AES CTR algorithm
// len(key) should be 16, 24 or 32
func AesCtrCrypt(data, key []byte) []byte {
block, _ := aes.NewCipher(key)
iv := bytes.Repeat([]byte("1"), block.BlockSize())
stream := cipher.NewCTR(block, iv)
dst := make([]byte, len(data))
stream.XORKeyStream(dst, data)
return dst
}
// AesCfbEncrypt encrypt data with key use AES CFB algorithm
// len(key) should be 16, 24 or 32
func AesCfbEncrypt(data, key []byte) []byte {
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
encrypted := make([]byte, aes.BlockSize+len(data))
iv := encrypted[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(encrypted[aes.BlockSize:], data)
return encrypted
}
// AesCfbDecrypt decrypt data with key use AES CFB algorithm
// len(encrypted) should be great than 16, len(key) should be 16, 24 or 32
func AesCfbDecrypt(encrypted, key []byte) []byte {
if len(encrypted) < aes.BlockSize {
panic("encrypted data is too short")
}
block, _ := aes.NewCipher(key)
iv := encrypted[:aes.BlockSize]
encrypted = encrypted[aes.BlockSize:]
stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(encrypted, encrypted)
return encrypted
}
// AesOfbEncrypt encrypt data with key use AES OFB algorithm
// len(key) should be 16, 24 or 32
func AesOfbEncrypt(data, key []byte) []byte {
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
data = pkcs7Padding(data, aes.BlockSize)
encrypted := make([]byte, aes.BlockSize+len(data))
iv := encrypted[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
stream := cipher.NewOFB(block, iv)
stream.XORKeyStream(encrypted[aes.BlockSize:], data)
return encrypted
}
// AesOfbDecrypt decrypt data with key use AES OFB algorithm
// len(key) should be 16, 24 or 32
func AesOfbDecrypt(data, key []byte) []byte {
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
iv := data[:aes.BlockSize]
data = data[aes.BlockSize:]
if len(data)%aes.BlockSize != 0 {
return nil
}
decrypted := make([]byte, len(data))
mode := cipher.NewOFB(block, iv)
mode.XORKeyStream(decrypted, data)
decrypted = pkcs7UnPadding(decrypted)
return decrypted
}

View File

@@ -1,62 +0,0 @@
package cryptor
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestAesEcbEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefghijklmnop"
aesEcbEncrypt := AesEcbEncrypt([]byte(data), []byte(key))
aesEcbDecrypt := AesEcbDecrypt(aesEcbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestAesEcbEncrypt")
assert.Equal(data, string(aesEcbDecrypt))
}
func TestAesCbcEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefghijklmnop"
aesCbcEncrypt := AesCbcEncrypt([]byte(data), []byte(key))
aesCbcDecrypt := AesCbcDecrypt(aesCbcEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestAesCbcEncrypt")
assert.Equal(data, string(aesCbcDecrypt))
}
func TestAesCtrCrypt(t *testing.T) {
data := "hello world"
key := "abcdefghijklmnop"
aesCtrCrypt := AesCtrCrypt([]byte(data), []byte(key))
aesCtrDeCrypt := AesCtrCrypt(aesCtrCrypt, []byte(key))
assert := internal.NewAssert(t, "TestAesCtrCrypt")
assert.Equal(data, string(aesCtrDeCrypt))
}
func TestAesCfbEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefghijklmnop"
aesCfbEncrypt := AesCfbEncrypt([]byte(data), []byte(key))
aesCfbDecrypt := AesCfbDecrypt(aesCfbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestAesCfbEncrypt")
assert.Equal(data, string(aesCfbDecrypt))
}
func TestAesOfbEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefghijklmnop"
aesOfbEncrypt := AesOfbEncrypt([]byte(data), []byte(key))
aesOfbDecrypt := AesOfbDecrypt(aesOfbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestAesOfbEncrypt")
assert.Equal(data, string(aesOfbDecrypt))
}

View File

@@ -19,25 +19,28 @@ import (
"os" "os"
) )
// Base64StdEncode encode string with base64 encoding // Base64StdEncode encode string with base64 encoding.
// Play: https://go.dev/play/p/VOaUyQUreoK
func Base64StdEncode(s string) string { func Base64StdEncode(s string) string {
return base64.StdEncoding.EncodeToString([]byte(s)) return base64.StdEncoding.EncodeToString([]byte(s))
} }
// Base64StdDecode decode a base64 encoded string // Base64StdDecode decode a base64 encoded string.
// Play: https://go.dev/play/p/RWQylnJVgIe
func Base64StdDecode(s string) string { func Base64StdDecode(s string) string {
b, _ := base64.StdEncoding.DecodeString(s) b, _ := base64.StdEncoding.DecodeString(s)
return string(b) return string(b)
} }
// Md5String return the md5 value of string // Md5String return the md5 value of string.
// Play: https://go.dev/play/p/1bLcVetbTOI
func Md5String(s string) string { func Md5String(s string) string {
h := md5.New() h := md5.New()
h.Write([]byte(s)) h.Write([]byte(s))
return hex.EncodeToString(h.Sum(nil)) return hex.EncodeToString(h.Sum(nil))
} }
// Md5File return the md5 value of file // Md5File return the md5 value of file.
func Md5File(filename string) (string, error) { func Md5File(filename string) (string, error) {
if fileInfo, err := os.Stat(filename); err != nil { if fileInfo, err := os.Stat(filename); err != nil {
return "", err return "", err
@@ -69,49 +72,56 @@ func Md5File(filename string) (string, error) {
return checksum, nil return checksum, nil
} }
// HmacMd5 return the hmac hash of string use md5 // HmacMd5 return the hmac hash of string use md5.
// Play: https://go.dev/play/p/uef0q1fz53I
func HmacMd5(data, key string) string { func HmacMd5(data, key string) string {
h := hmac.New(md5.New, []byte(key)) h := hmac.New(md5.New, []byte(key))
h.Write([]byte(data)) h.Write([]byte(data))
return hex.EncodeToString(h.Sum([]byte(""))) return hex.EncodeToString(h.Sum([]byte("")))
} }
// HmacSha1 return the hmac hash of string use sha1 // HmacSha1 return the hmac hash of string use sha1.
// Play: https://go.dev/play/p/1UI4oQ4WXKM
func HmacSha1(data, key string) string { func HmacSha1(data, key string) string {
h := hmac.New(sha1.New, []byte(key)) h := hmac.New(sha1.New, []byte(key))
h.Write([]byte(data)) h.Write([]byte(data))
return hex.EncodeToString(h.Sum([]byte(""))) return hex.EncodeToString(h.Sum([]byte("")))
} }
// HmacSha256 return the hmac hash of string use sha256 // HmacSha256 return the hmac hash of string use sha256.
// Play: https://go.dev/play/p/HhpwXxFhhC0
func HmacSha256(data, key string) string { func HmacSha256(data, key string) string {
h := hmac.New(sha256.New, []byte(key)) h := hmac.New(sha256.New, []byte(key))
h.Write([]byte(data)) h.Write([]byte(data))
return hex.EncodeToString(h.Sum([]byte(""))) return hex.EncodeToString(h.Sum([]byte("")))
} }
// HmacSha512 return the hmac hash of string use sha512 // HmacSha512 return the hmac hash of string use sha512.
// Play: https://go.dev/play/p/59Od6m4A0Ud
func HmacSha512(data, key string) string { func HmacSha512(data, key string) string {
h := hmac.New(sha512.New, []byte(key)) h := hmac.New(sha512.New, []byte(key))
h.Write([]byte(data)) h.Write([]byte(data))
return hex.EncodeToString(h.Sum([]byte(""))) return hex.EncodeToString(h.Sum([]byte("")))
} }
// Sha1 return the sha1 value (SHA-1 hash algorithm) of string // Sha1 return the sha1 value (SHA-1 hash algorithm) of string.
// Play: https://go.dev/play/p/_m_uoD1deMT
func Sha1(data string) string { func Sha1(data string) string {
sha1 := sha1.New() sha1 := sha1.New()
sha1.Write([]byte(data)) sha1.Write([]byte(data))
return hex.EncodeToString(sha1.Sum([]byte(""))) return hex.EncodeToString(sha1.Sum([]byte("")))
} }
// Sha256 return the sha256 value (SHA256 hash algorithm) of string // Sha256 return the sha256 value (SHA256 hash algorithm) of string.
// Play: https://go.dev/play/p/tU9tfBMIAr1
func Sha256(data string) string { func Sha256(data string) string {
sha256 := sha256.New() sha256 := sha256.New()
sha256.Write([]byte(data)) sha256.Write([]byte(data))
return hex.EncodeToString(sha256.Sum([]byte(""))) return hex.EncodeToString(sha256.Sum([]byte("")))
} }
// Sha512 return the sha512 value (SHA512 hash algorithm) of string // Sha512 return the sha512 value (SHA512 hash algorithm) of string.
// Play: https://go.dev/play/p/3WsvLYZxsHa
func Sha512(data string) string { func Sha512(data string) string {
sha512 := sha512.New() sha512 := sha512.New()
sha512.Write([]byte(data)) sha512.Write([]byte(data))

View File

@@ -0,0 +1,410 @@
package cryptor
import "fmt"
func ExampleAesEcbEncrypt() {
data := "hello"
key := "abcdefghijklmnop"
encrypted := AesEcbEncrypt([]byte(data), []byte(key))
decrypted := AesEcbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleAesEcbDecrypt() {
data := "hello"
key := "abcdefghijklmnop"
encrypted := AesEcbEncrypt([]byte(data), []byte(key))
decrypted := AesEcbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleAesCbcEncrypt() {
data := "hello"
key := "abcdefghijklmnop"
encrypted := AesCbcEncrypt([]byte(data), []byte(key))
decrypted := AesCbcDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleAesCbcDecrypt() {
data := "hello"
key := "abcdefghijklmnop"
encrypted := AesCbcEncrypt([]byte(data), []byte(key))
decrypted := AesCbcDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleAesCtrCrypt() {
data := "hello"
key := "abcdefghijklmnop"
encrypted := AesCtrCrypt([]byte(data), []byte(key))
decrypted := AesCtrCrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleAesCfbEncrypt() {
data := "hello"
key := "abcdefghijklmnop"
encrypted := AesCfbEncrypt([]byte(data), []byte(key))
decrypted := AesCfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleAesCfbDecrypt() {
data := "hello"
key := "abcdefghijklmnop"
encrypted := AesCfbEncrypt([]byte(data), []byte(key))
decrypted := AesCfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleAesOfbEncrypt() {
data := "hello"
key := "abcdefghijklmnop"
encrypted := AesOfbEncrypt([]byte(data), []byte(key))
decrypted := AesOfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleAesOfbDecrypt() {
data := "hello"
key := "abcdefghijklmnop"
encrypted := AesOfbEncrypt([]byte(data), []byte(key))
decrypted := AesOfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleDesEcbEncrypt() {
data := "hello"
key := "abcdefgh"
encrypted := DesEcbEncrypt([]byte(data), []byte(key))
decrypted := DesEcbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleDesEcbDecrypt() {
data := "hello"
key := "abcdefgh"
encrypted := DesEcbEncrypt([]byte(data), []byte(key))
decrypted := DesEcbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleDesCbcEncrypt() {
data := "hello"
key := "abcdefgh"
encrypted := DesCbcEncrypt([]byte(data), []byte(key))
decrypted := DesCbcDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleDesCbcDecrypt() {
data := "hello"
key := "abcdefgh"
encrypted := DesCbcEncrypt([]byte(data), []byte(key))
decrypted := DesCbcDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleDesCtrCrypt() {
data := "hello"
key := "abcdefgh"
encrypted := DesCtrCrypt([]byte(data), []byte(key))
decrypted := DesCtrCrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleDesCfbEncrypt() {
data := "hello"
key := "abcdefgh"
encrypted := DesCfbEncrypt([]byte(data), []byte(key))
decrypted := DesCfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleDesCfbDecrypt() {
data := "hello"
key := "abcdefgh"
encrypted := DesCfbEncrypt([]byte(data), []byte(key))
decrypted := DesCfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleDesOfbEncrypt() {
data := "hello"
key := "abcdefgh"
encrypted := DesOfbEncrypt([]byte(data), []byte(key))
decrypted := DesOfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleDesOfbDecrypt() {
data := "hello"
key := "abcdefgh"
encrypted := DesOfbEncrypt([]byte(data), []byte(key))
decrypted := DesOfbDecrypt(encrypted, []byte(key))
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleGenerateRsaKey() {
// Create ras private and public pem file
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
if err != nil {
return
}
fmt.Println("foo")
// Output:
// foo
}
func ExampleRsaEncrypt() {
// Create ras private and public pem file
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
if err != nil {
return
}
data := []byte("hello")
encrypted := RsaEncrypt(data, "rsa_public.pem")
decrypted := RsaDecrypt(encrypted, "rsa_private.pem")
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleRsaDecrypt() {
// Create ras private and public pem file
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
if err != nil {
return
}
data := []byte("hello")
encrypted := RsaEncrypt(data, "rsa_public.pem")
decrypted := RsaDecrypt(encrypted, "rsa_private.pem")
fmt.Println(string(decrypted))
// Output:
// hello
}
func ExampleBase64StdEncode() {
base64Str := Base64StdEncode("hello")
fmt.Println(base64Str)
// Output:
// aGVsbG8=
}
func ExampleBase64StdDecode() {
str := Base64StdDecode("aGVsbG8=")
fmt.Println(str)
// Output:
// hello
}
func ExampleHmacMd5() {
str := "hello"
key := "12345"
hms := HmacMd5(str, key)
fmt.Println(hms)
// Output:
// e834306eab892d872525d4918a7a639a
}
func ExampleHmacSha1() {
str := "hello"
key := "12345"
hms := HmacSha1(str, key)
fmt.Println(hms)
// Output:
// 5c6a9db0cccb92e36ed0323fd09b7f936de9ace0
}
func ExampleHmacSha256() {
str := "hello"
key := "12345"
hms := HmacSha256(str, key)
fmt.Println(hms)
// Output:
// 315bb93c4e989862ba09cb62e05d73a5f376cb36f0d786edab0c320d059fde75
}
func ExampleHmacSha512() {
str := "hello"
key := "12345"
hms := HmacSha512(str, key)
fmt.Println(hms)
// Output:
// dd8f1290a9dd23d354e2526d9a2e9ce8cffffdd37cb320800d1c6c13d2efc363288376a196c5458daf53f8e1aa6b45a6d856303d5c0a2064bff9785861d48cfc
}
func ExampleMd5String() {
str := "hello"
md5Str := Md5String(str)
fmt.Println(md5Str)
// Output:
// 5d41402abc4b2a76b9719d911017c592
}
func ExampleSha1() {
str := "hello"
result := Sha1(str)
fmt.Println(result)
// Output:
// aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
}
func ExampleSha256() {
str := "hello"
result := Sha256(str)
fmt.Println(result)
// Output:
// 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
}
func ExampleSha512() {
str := "hello"
result := Sha512(str)
fmt.Println(result)
// Output:
// 9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043
}

View File

@@ -1,180 +0,0 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package cryptor implements some util functions to encrypt and decrypt.
package cryptor
import (
"bytes"
"crypto/cipher"
"crypto/des"
"crypto/rand"
"io"
)
// DesEcbEncrypt encrypt data with key use DES ECB algorithm
// len(key) should be 8
func DesEcbEncrypt(data, key []byte) []byte {
length := (len(data) + des.BlockSize) / des.BlockSize
plain := make([]byte, length*des.BlockSize)
copy(plain, data)
pad := byte(len(plain) - len(data))
for i := len(data); i < len(plain); i++ {
plain[i] = pad
}
encrypted := make([]byte, len(plain))
cipher, _ := des.NewCipher(generateDesKey(key))
for bs, be := 0, cipher.BlockSize(); bs <= len(data); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
}
return encrypted
}
// DesEcbDecrypt decrypt data with key use DES ECB algorithm
// len(key) should be 8
func DesEcbDecrypt(encrypted, key []byte) []byte {
cipher, _ := des.NewCipher(generateDesKey(key))
decrypted := make([]byte, len(encrypted))
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
}
trim := 0
if len(decrypted) > 0 {
trim = len(decrypted) - int(decrypted[len(decrypted)-1])
}
return decrypted[:trim]
}
// DesCbcEncrypt encrypt data with key use DES CBC algorithm
// len(key) should be 8
func DesCbcEncrypt(data, key []byte) []byte {
block, _ := des.NewCipher(key)
data = pkcs7Padding(data, block.BlockSize())
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
}
// DesCbcDecrypt decrypt data with key use DES CBC algorithm
// len(key) should be 8
func DesCbcDecrypt(encrypted, key []byte) []byte {
block, _ := des.NewCipher(key)
iv := encrypted[:des.BlockSize]
encrypted = encrypted[des.BlockSize:]
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(encrypted, encrypted)
decrypted := pkcs7UnPadding(encrypted)
return decrypted
}
// DesCtrCrypt encrypt data with key use DES CTR algorithm
// len(key) should be 8
func DesCtrCrypt(data, key []byte) []byte {
block, _ := des.NewCipher(key)
iv := bytes.Repeat([]byte("1"), block.BlockSize())
stream := cipher.NewCTR(block, iv)
dst := make([]byte, len(data))
stream.XORKeyStream(dst, data)
return dst
}
// DesCfbEncrypt encrypt data with key use DES CFB algorithm
// len(key) should be 8
func DesCfbEncrypt(data, key []byte) []byte {
block, err := des.NewCipher(key)
if err != nil {
panic(err)
}
encrypted := make([]byte, des.BlockSize+len(data))
iv := encrypted[:des.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(encrypted[des.BlockSize:], data)
return encrypted
}
// DesCfbDecrypt decrypt data with key use DES CFB algorithm
// len(encrypted) should be great than 16, len(key) should be 8
func DesCfbDecrypt(encrypted, key []byte) []byte {
block, _ := des.NewCipher(key)
if len(encrypted) < des.BlockSize {
panic("encrypted data is too short")
}
iv := encrypted[:des.BlockSize]
encrypted = encrypted[des.BlockSize:]
stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(encrypted, encrypted)
return encrypted
}
// DesOfbEncrypt encrypt data with key use DES OFB algorithm
// len(key) should be 16, 24 or 32
func DesOfbEncrypt(data, key []byte) []byte {
block, err := des.NewCipher(key)
if err != nil {
panic(err)
}
data = pkcs7Padding(data, des.BlockSize)
encrypted := make([]byte, des.BlockSize+len(data))
iv := encrypted[:des.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
stream := cipher.NewOFB(block, iv)
stream.XORKeyStream(encrypted[des.BlockSize:], data)
return encrypted
}
// DesOfbDecrypt decrypt data with key use DES OFB algorithm
// len(key) should be 8
func DesOfbDecrypt(data, key []byte) []byte {
block, err := des.NewCipher(key)
if err != nil {
panic(err)
}
iv := data[:des.BlockSize]
data = data[des.BlockSize:]
if len(data)%des.BlockSize != 0 {
return nil
}
decrypted := make([]byte, len(data))
mode := cipher.NewOFB(block, iv)
mode.XORKeyStream(decrypted, data)
decrypted = pkcs7UnPadding(decrypted)
return decrypted
}

View File

@@ -1,62 +0,0 @@
package cryptor
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestDesEcbEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefgh"
desEcbEncrypt := DesEcbEncrypt([]byte(data), []byte(key))
desEcbDecrypt := DesEcbDecrypt(desEcbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestDesEcbEncrypt")
assert.Equal(data, string(desEcbDecrypt))
}
func TestDesCbcEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefgh"
desCbcEncrypt := DesCbcEncrypt([]byte(data), []byte(key))
desCbcDecrypt := DesCbcDecrypt(desCbcEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestDesCbcEncrypt")
assert.Equal(data, string(desCbcDecrypt))
}
func TestDesCtrCrypt(t *testing.T) {
data := "hello world"
key := "abcdefgh"
desCtrCrypt := DesCtrCrypt([]byte(data), []byte(key))
desCtrDeCrypt := DesCtrCrypt(desCtrCrypt, []byte(key))
assert := internal.NewAssert(t, "TestDesCtrCrypt")
assert.Equal(data, string(desCtrDeCrypt))
}
func TestDesCfbEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefgh"
desCfbEncrypt := DesCfbEncrypt([]byte(data), []byte(key))
desCfbDecrypt := DesCfbDecrypt(desCfbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestDesCfbEncrypt")
assert.Equal(data, string(desCfbDecrypt))
}
func TestDesOfbEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefgh"
desOfbEncrypt := DesOfbEncrypt([]byte(data), []byte(key))
desOfbDecrypt := DesOfbDecrypt(desOfbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestDesOfbEncrypt")
assert.Equal(data, string(desOfbDecrypt))
}

498
cryptor/encrypt.go Normal file
View File

@@ -0,0 +1,498 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package cryptor implements some util functions to encrypt and decrypt.
// Note:
// 1. for aes crypt function, the `key` param length should be 16, 24 or 32. if not, will panic.
package cryptor
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/des"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"io"
"os"
)
// AesEcbEncrypt encrypt data with key use AES ECB algorithm
// len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/jT5irszHx-j
func AesEcbEncrypt(data, key []byte) []byte {
length := (len(data) + aes.BlockSize) / aes.BlockSize
plain := make([]byte, length*aes.BlockSize)
copy(plain, data)
pad := byte(len(plain) - len(data))
for i := len(data); i < len(plain); i++ {
plain[i] = pad
}
encrypted := make([]byte, len(plain))
cipher, _ := aes.NewCipher(generateAesKey(key))
for bs, be := 0, cipher.BlockSize(); bs <= len(data); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
}
return encrypted
}
// AesEcbDecrypt decrypt data with key use AES ECB algorithm
// len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/jT5irszHx-j
func AesEcbDecrypt(encrypted, key []byte) []byte {
cipher, _ := aes.NewCipher(generateAesKey(key))
decrypted := make([]byte, len(encrypted))
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
}
trim := 0
if len(decrypted) > 0 {
trim = len(decrypted) - int(decrypted[len(decrypted)-1])
}
return decrypted[:trim]
}
// AesCbcEncrypt encrypt data with key use AES CBC algorithm
// len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/IOq_g8_lKZD
func AesCbcEncrypt(data, key []byte) []byte {
block, _ := aes.NewCipher(key)
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)
return encrypted
}
// AesCbcDecrypt decrypt data with key use AES CBC algorithm
// len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/IOq_g8_lKZD
func AesCbcDecrypt(encrypted, key []byte) []byte {
block, _ := aes.NewCipher(key)
iv := encrypted[:aes.BlockSize]
encrypted = encrypted[aes.BlockSize:]
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(encrypted, encrypted)
decrypted := pkcs7UnPadding(encrypted)
return decrypted
}
// AesCtrCrypt encrypt data with key use AES CTR algorithm
// len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/SpaZO0-5Nsp
func AesCtrCrypt(data, key []byte) []byte {
block, _ := aes.NewCipher(key)
iv := bytes.Repeat([]byte("1"), block.BlockSize())
stream := cipher.NewCTR(block, iv)
dst := make([]byte, len(data))
stream.XORKeyStream(dst, data)
return dst
}
// AesCfbEncrypt encrypt data with key use AES CFB algorithm
// len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/tfkF10B13kH
func AesCfbEncrypt(data, key []byte) []byte {
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
encrypted := make([]byte, aes.BlockSize+len(data))
iv := encrypted[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(encrypted[aes.BlockSize:], data)
return encrypted
}
// AesCfbDecrypt decrypt data with key use AES CFB algorithm
// len(encrypted) should be great than 16, len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/tfkF10B13kH
func AesCfbDecrypt(encrypted, key []byte) []byte {
if len(encrypted) < aes.BlockSize {
panic("encrypted data is too short")
}
block, _ := aes.NewCipher(key)
iv := encrypted[:aes.BlockSize]
encrypted = encrypted[aes.BlockSize:]
stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(encrypted, encrypted)
return encrypted
}
// AesOfbEncrypt encrypt data with key use AES OFB algorithm
// len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/VtHxtkUj-3F
func AesOfbEncrypt(data, key []byte) []byte {
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
data = pkcs7Padding(data, aes.BlockSize)
encrypted := make([]byte, aes.BlockSize+len(data))
iv := encrypted[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
stream := cipher.NewOFB(block, iv)
stream.XORKeyStream(encrypted[aes.BlockSize:], data)
return encrypted
}
// AesOfbDecrypt decrypt data with key use AES OFB algorithm
// len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/VtHxtkUj-3F
func AesOfbDecrypt(data, key []byte) []byte {
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
iv := data[:aes.BlockSize]
data = data[aes.BlockSize:]
if len(data)%aes.BlockSize != 0 {
return nil
}
decrypted := make([]byte, len(data))
mode := cipher.NewOFB(block, iv)
mode.XORKeyStream(decrypted, data)
decrypted = pkcs7UnPadding(decrypted)
return decrypted
}
// DesEcbEncrypt encrypt data with key use DES ECB algorithm
// len(key) should be 8.
// Play: https://go.dev/play/p/8qivmPeZy4P
func DesEcbEncrypt(data, key []byte) []byte {
length := (len(data) + des.BlockSize) / des.BlockSize
plain := make([]byte, length*des.BlockSize)
copy(plain, data)
pad := byte(len(plain) - len(data))
for i := len(data); i < len(plain); i++ {
plain[i] = pad
}
encrypted := make([]byte, len(plain))
cipher, _ := des.NewCipher(generateDesKey(key))
for bs, be := 0, cipher.BlockSize(); bs <= len(data); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
}
return encrypted
}
// DesEcbDecrypt decrypt data with key use DES ECB algorithm
// len(key) should be 8.
// Play: https://go.dev/play/p/8qivmPeZy4P
func DesEcbDecrypt(encrypted, key []byte) []byte {
cipher, _ := des.NewCipher(generateDesKey(key))
decrypted := make([]byte, len(encrypted))
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
}
trim := 0
if len(decrypted) > 0 {
trim = len(decrypted) - int(decrypted[len(decrypted)-1])
}
return decrypted[:trim]
}
// DesCbcEncrypt encrypt data with key use DES CBC algorithm
// len(key) should be 8.
// Play: https://go.dev/play/p/4cC4QvWfe3_1
func DesCbcEncrypt(data, key []byte) []byte {
block, _ := des.NewCipher(key)
data = pkcs7Padding(data, block.BlockSize())
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
}
// DesCbcDecrypt decrypt data with key use DES CBC algorithm
// len(key) should be 8.
// Play: https://go.dev/play/p/4cC4QvWfe3_1
func DesCbcDecrypt(encrypted, key []byte) []byte {
block, _ := des.NewCipher(key)
iv := encrypted[:des.BlockSize]
encrypted = encrypted[des.BlockSize:]
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(encrypted, encrypted)
decrypted := pkcs7UnPadding(encrypted)
return decrypted
}
// DesCtrCrypt encrypt data with key use DES CTR algorithm
// len(key) should be 8.
// Play: https://go.dev/play/p/9-T6OjKpcdw
func DesCtrCrypt(data, key []byte) []byte {
block, _ := des.NewCipher(key)
iv := bytes.Repeat([]byte("1"), block.BlockSize())
stream := cipher.NewCTR(block, iv)
dst := make([]byte, len(data))
stream.XORKeyStream(dst, data)
return dst
}
// DesCfbEncrypt encrypt data with key use DES CFB algorithm
// len(key) should be 8.
// Play: https://go.dev/play/p/y-eNxcFBlxL
func DesCfbEncrypt(data, key []byte) []byte {
block, err := des.NewCipher(key)
if err != nil {
panic(err)
}
encrypted := make([]byte, des.BlockSize+len(data))
iv := encrypted[:des.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(encrypted[des.BlockSize:], data)
return encrypted
}
// DesCfbDecrypt decrypt data with key use DES CFB algorithm
// len(encrypted) should be great than 16, len(key) should be 8.
// Play: https://go.dev/play/p/y-eNxcFBlxL
func DesCfbDecrypt(encrypted, key []byte) []byte {
block, _ := des.NewCipher(key)
if len(encrypted) < des.BlockSize {
panic("encrypted data is too short")
}
iv := encrypted[:des.BlockSize]
encrypted = encrypted[des.BlockSize:]
stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(encrypted, encrypted)
return encrypted
}
// DesOfbEncrypt encrypt data with key use DES OFB algorithm
// len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/74KmNadjN1J
func DesOfbEncrypt(data, key []byte) []byte {
block, err := des.NewCipher(key)
if err != nil {
panic(err)
}
data = pkcs7Padding(data, des.BlockSize)
encrypted := make([]byte, des.BlockSize+len(data))
iv := encrypted[:des.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
stream := cipher.NewOFB(block, iv)
stream.XORKeyStream(encrypted[des.BlockSize:], data)
return encrypted
}
// DesOfbDecrypt decrypt data with key use DES OFB algorithm
// len(key) should be 8.
// Play: https://go.dev/play/p/74KmNadjN1J
func DesOfbDecrypt(data, key []byte) []byte {
block, err := des.NewCipher(key)
if err != nil {
panic(err)
}
iv := data[:des.BlockSize]
data = data[des.BlockSize:]
if len(data)%des.BlockSize != 0 {
return nil
}
decrypted := make([]byte, len(data))
mode := cipher.NewOFB(block, iv)
mode.XORKeyStream(decrypted, data)
decrypted = pkcs7UnPadding(decrypted)
return decrypted
}
// GenerateRsaKey create rsa private and public pemo file.
// Play: https://go.dev/play/p/zutRHrDqs0X
func GenerateRsaKey(keySize int, priKeyFile, pubKeyFile string) error {
// private key
privateKey, err := rsa.GenerateKey(rand.Reader, keySize)
if err != nil {
return err
}
derText := x509.MarshalPKCS1PrivateKey(privateKey)
block := pem.Block{
Type: "rsa private key",
Bytes: derText,
}
file, err := os.Create(priKeyFile)
if err != nil {
panic(err)
}
err = pem.Encode(file, &block)
if err != nil {
return err
}
file.Close()
// public key
publicKey := privateKey.PublicKey
derpText, err := x509.MarshalPKIXPublicKey(&publicKey)
if err != nil {
return err
}
block = pem.Block{
Type: "rsa public key",
Bytes: derpText,
}
file, err = os.Create(pubKeyFile)
if err != nil {
return err
}
err = pem.Encode(file, &block)
if err != nil {
return err
}
file.Close()
return nil
}
// RsaEncrypt encrypt data with ras algorithm.
// Play: https://go.dev/play/p/rDqTT01SPkZ
func RsaEncrypt(data []byte, pubKeyFileName string) []byte {
file, err := os.Open(pubKeyFileName)
if err != nil {
panic(err)
}
fileInfo, err := file.Stat()
if err != nil {
panic(err)
}
defer file.Close()
buf := make([]byte, fileInfo.Size())
_, err = file.Read(buf)
if err != nil {
panic(err)
}
block, _ := pem.Decode(buf)
pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
panic(err)
}
pubKey := pubInterface.(*rsa.PublicKey)
cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, pubKey, data)
if err != nil {
panic(err)
}
return cipherText
}
// RsaDecrypt decrypt data with ras algorithm.
// Play: https://go.dev/play/p/rDqTT01SPkZ
func RsaDecrypt(data []byte, privateKeyFileName string) []byte {
file, err := os.Open(privateKeyFileName)
if err != nil {
panic(err)
}
fileInfo, err := file.Stat()
if err != nil {
panic(err)
}
buf := make([]byte, fileInfo.Size())
defer file.Close()
_, err = file.Read(buf)
if err != nil {
panic(err)
}
block, _ := pem.Decode(buf)
priKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
panic(err)
}
plainText, err := rsa.DecryptPKCS1v15(rand.Reader, priKey, data)
if err != nil {
panic(err)
}
return plainText
}

130
cryptor/encrypt_test.go Normal file
View File

@@ -0,0 +1,130 @@
package cryptor
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestAesEcbEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefghijklmnop"
aesEcbEncrypt := AesEcbEncrypt([]byte(data), []byte(key))
aesEcbDecrypt := AesEcbDecrypt(aesEcbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestAesEcbEncrypt")
assert.Equal(data, string(aesEcbDecrypt))
}
func TestAesCbcEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefghijklmnop"
aesCbcEncrypt := AesCbcEncrypt([]byte(data), []byte(key))
aesCbcDecrypt := AesCbcDecrypt(aesCbcEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestAesCbcEncrypt")
assert.Equal(data, string(aesCbcDecrypt))
}
func TestAesCtrCrypt(t *testing.T) {
data := "hello world"
key := "abcdefghijklmnop"
aesCtrCrypt := AesCtrCrypt([]byte(data), []byte(key))
aesCtrDeCrypt := AesCtrCrypt(aesCtrCrypt, []byte(key))
assert := internal.NewAssert(t, "TestAesCtrCrypt")
assert.Equal(data, string(aesCtrDeCrypt))
}
func TestAesCfbEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefghijklmnop"
aesCfbEncrypt := AesCfbEncrypt([]byte(data), []byte(key))
aesCfbDecrypt := AesCfbDecrypt(aesCfbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestAesCfbEncrypt")
assert.Equal(data, string(aesCfbDecrypt))
}
func TestAesOfbEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefghijklmnop"
aesOfbEncrypt := AesOfbEncrypt([]byte(data), []byte(key))
aesOfbDecrypt := AesOfbDecrypt(aesOfbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestAesOfbEncrypt")
assert.Equal(data, string(aesOfbDecrypt))
}
func TestDesEcbEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefgh"
desEcbEncrypt := DesEcbEncrypt([]byte(data), []byte(key))
desEcbDecrypt := DesEcbDecrypt(desEcbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestDesEcbEncrypt")
assert.Equal(data, string(desEcbDecrypt))
}
func TestDesCbcEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefgh"
desCbcEncrypt := DesCbcEncrypt([]byte(data), []byte(key))
desCbcDecrypt := DesCbcDecrypt(desCbcEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestDesCbcEncrypt")
assert.Equal(data, string(desCbcDecrypt))
}
func TestDesCtrCrypt(t *testing.T) {
data := "hello world"
key := "abcdefgh"
desCtrCrypt := DesCtrCrypt([]byte(data), []byte(key))
desCtrDeCrypt := DesCtrCrypt(desCtrCrypt, []byte(key))
assert := internal.NewAssert(t, "TestDesCtrCrypt")
assert.Equal(data, string(desCtrDeCrypt))
}
func TestDesCfbEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefgh"
desCfbEncrypt := DesCfbEncrypt([]byte(data), []byte(key))
desCfbDecrypt := DesCfbDecrypt(desCfbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestDesCfbEncrypt")
assert.Equal(data, string(desCfbDecrypt))
}
func TestDesOfbEncrypt(t *testing.T) {
data := "hello world"
key := "abcdefgh"
desOfbEncrypt := DesOfbEncrypt([]byte(data), []byte(key))
desOfbDecrypt := DesOfbDecrypt(desOfbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestDesOfbEncrypt")
assert.Equal(data, string(desOfbDecrypt))
}
func TestRsaEncrypt(t *testing.T) {
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
if err != nil {
t.FailNow()
}
data := []byte("hello world")
encrypted := RsaEncrypt(data, "rsa_public.pem")
decrypted := RsaDecrypt(encrypted, "rsa_private.pem")
assert := internal.NewAssert(t, "TestRsaEncrypt")
assert.Equal(string(data), string(decrypted))
}

View File

@@ -1,134 +0,0 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package cryptor implements some util functions to encrypt and decrypt.
package cryptor
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"os"
)
// GenerateRsaKey make a rsa private key, and return key file name
// Generated key file is `rsa_private.pem` and `rsa_public.pem` in current path
func GenerateRsaKey(keySize int, priKeyFile, pubKeyFile string) error {
// private key
privateKey, err := rsa.GenerateKey(rand.Reader, keySize)
if err != nil {
return err
}
derText := x509.MarshalPKCS1PrivateKey(privateKey)
block := pem.Block{
Type: "rsa private key",
Bytes: derText,
}
//file,err := os.Create("rsa_private.pem")
file, err := os.Create(priKeyFile)
if err != nil {
panic(err)
}
err = pem.Encode(file, &block)
if err != nil {
return err
}
file.Close()
// public key
publicKey := privateKey.PublicKey
derpText, err := x509.MarshalPKIXPublicKey(&publicKey)
if err != nil {
return err
}
block = pem.Block{
Type: "rsa public key",
Bytes: derpText,
}
file, err = os.Create(pubKeyFile)
if err != nil {
return err
}
err = pem.Encode(file, &block)
if err != nil {
return err
}
file.Close()
return nil
}
// RsaEncrypt encrypt data with ras algorithm
func RsaEncrypt(data []byte, pubKeyFileName string) []byte {
file, err := os.Open(pubKeyFileName)
if err != nil {
panic(err)
}
fileInfo, err := file.Stat()
if err != nil {
panic(err)
}
defer file.Close()
buf := make([]byte, fileInfo.Size())
_, err = file.Read(buf)
if err != nil {
panic(err)
}
block, _ := pem.Decode(buf)
pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
panic(err)
}
pubKey := pubInterface.(*rsa.PublicKey)
cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, pubKey, data)
if err != nil {
panic(err)
}
return cipherText
}
// RsaDecrypt decrypt data with ras algorithm
func RsaDecrypt(data []byte, privateKeyFileName string) []byte {
file, err := os.Open(privateKeyFileName)
if err != nil {
panic(err)
}
fileInfo, err := file.Stat()
if err != nil {
panic(err)
}
buf := make([]byte, fileInfo.Size())
defer file.Close()
_, err = file.Read(buf)
if err != nil {
panic(err)
}
block, _ := pem.Decode(buf)
priKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
panic(err)
}
plainText, err := rsa.DecryptPKCS1v15(rand.Reader, priKey, data)
if err != nil {
panic(err)
}
return plainText
}

View File

@@ -1,20 +0,0 @@
package cryptor
import (
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestRsaEncrypt(t *testing.T) {
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
if err != nil {
t.FailNow()
}
data := []byte("hello world")
encrypted := RsaEncrypt(data, "rsa_public.pem")
decrypted := RsaDecrypt(encrypted, "rsa_private.pem")
assert := internal.NewAssert(t, "TestRsaEncrypt")
assert.Equal(string(data), string(decrypted))
}

View File

@@ -8,17 +8,17 @@ import (
"reflect" "reflect"
) )
// List is a linear table, implemented with slice // List is a linear table, implemented with slice.
type List[T any] struct { type List[T any] struct {
data []T data []T
} }
// NewList return a pointer of List // NewList return a pointer of List.
func NewList[T any](data []T) *List[T] { func NewList[T any](data []T) *List[T] {
return &List[T]{data: data} return &List[T]{data: data}
} }
// Data return list data // Data return list data.
func (l *List[T]) Data() []T { func (l *List[T]) Data() []T {
return l.data return l.data
} }
@@ -31,7 +31,7 @@ func (l *List[T]) ValueOf(index int) (*T, bool) {
return &l.data[index], true return &l.data[index], true
} }
// IndexOf returns the index of value. if not found return -1 // IndexOf returns the index of value. if not found return -1.
func (l *List[T]) IndexOf(value T) int { func (l *List[T]) IndexOf(value T) int {
index := -1 index := -1
data := l.data data := l.data
@@ -45,7 +45,7 @@ func (l *List[T]) IndexOf(value T) int {
} }
// LastIndexOf returns the index of the last occurrence of the value in this list. // LastIndexOf returns the index of the last occurrence of the value in this list.
// if not found return -1 // if not found return -1.
func (l *List[T]) LastIndexOf(value T) int { func (l *List[T]) LastIndexOf(value T) int {
index := -1 index := -1
data := l.data data := l.data
@@ -59,7 +59,7 @@ func (l *List[T]) LastIndexOf(value T) int {
} }
// IndexOfFunc returns the first index satisfying f(v) // IndexOfFunc returns the first index satisfying f(v)
// if not found return -1 // if not found return -1.
func (l *List[T]) IndexOfFunc(f func(T) bool) int { func (l *List[T]) IndexOfFunc(f func(T) bool) int {
index := -1 index := -1
data := l.data data := l.data
@@ -73,7 +73,7 @@ func (l *List[T]) IndexOfFunc(f func(T) bool) int {
} }
// LastIndexOfFunc returns the index of the last occurrence of the value in this list satisfying f(data[i]) // LastIndexOfFunc returns the index of the last occurrence of the value in this list satisfying f(data[i])
// if not found return -1 // if not found return -1.
func (l *List[T]) LastIndexOfFunc(f func(T) bool) int { func (l *List[T]) LastIndexOfFunc(f func(T) bool) int {
index := -1 index := -1
data := l.data data := l.data
@@ -86,7 +86,7 @@ func (l *List[T]) LastIndexOfFunc(f func(T) bool) int {
return index return index
} }
// Contain checks if the value in the list or not // Contain checks if the value in the list or not.
func (l *List[T]) Contain(value T) bool { func (l *List[T]) Contain(value T) bool {
data := l.data data := l.data
for _, v := range data { for _, v := range data {
@@ -97,22 +97,22 @@ func (l *List[T]) Contain(value T) bool {
return false return false
} }
// Push append value to the list data // Push append value to the list data.
func (l *List[T]) Push(value T) { func (l *List[T]) Push(value T) {
l.data = append(l.data, value) l.data = append(l.data, value)
} }
// InsertAtFirst insert value into list at first index // InsertAtFirst insert value into list at first index.
func (l *List[T]) InsertAtFirst(value T) { func (l *List[T]) InsertAtFirst(value T) {
l.InsertAt(0, value) l.InsertAt(0, value)
} }
// InsertAtLast insert value into list at last index // InsertAtLast insert value into list at last index.
func (l *List[T]) InsertAtLast(value T) { func (l *List[T]) InsertAtLast(value T) {
l.InsertAt(len(l.data), value) l.InsertAt(len(l.data), value)
} }
// InsertAt insert value into list at index // InsertAt insert value into list at index.
func (l *List[T]) InsertAt(index int, value T) { func (l *List[T]) InsertAt(index int, value T) {
data := l.data data := l.data
size := len(data) size := len(data)
@@ -123,7 +123,7 @@ func (l *List[T]) InsertAt(index int, value T) {
l.data = append(data[:index], append([]T{value}, data[index:]...)...) l.data = append(data[:index], append([]T{value}, data[index:]...)...)
} }
// PopFirst delete the first value of list and return it // PopFirst delete the first value of list and return it.
func (l *List[T]) PopFirst() (*T, bool) { func (l *List[T]) PopFirst() (*T, bool) {
if len(l.data) == 0 { if len(l.data) == 0 {
return nil, false return nil, false
@@ -135,7 +135,7 @@ func (l *List[T]) PopFirst() (*T, bool) {
return &v, true return &v, true
} }
// PopLast delete the last value of list and return it // PopLast delete the last value of list and return it.
func (l *List[T]) PopLast() (*T, bool) { func (l *List[T]) PopLast() (*T, bool) {
size := len(l.data) size := len(l.data)
if size == 0 { if size == 0 {
@@ -148,7 +148,7 @@ func (l *List[T]) PopLast() (*T, bool) {
return &v, true return &v, true
} }
// DeleteAt delete the value of list at index // DeleteAt delete the value of list at index.
func (l *List[T]) DeleteAt(index int) { func (l *List[T]) DeleteAt(index int) {
data := l.data data := l.data
size := len(data) size := len(data)
@@ -199,7 +199,7 @@ func (l *List[T]) UpdateAt(index int, value T) {
l.data = append(data[:index], append([]T{value}, data[index+1:]...)...) l.data = append(data[:index], append([]T{value}, data[index+1:]...)...)
} }
// Equal compare list to other list, use reflect.DeepEqual // Equal compare list to other list, use reflect.DeepEqual.
func (l *List[T]) Equal(other *List[T]) bool { func (l *List[T]) Equal(other *List[T]) bool {
if len(l.data) != len(other.data) { if len(l.data) != len(other.data) {
return false return false
@@ -214,17 +214,17 @@ func (l *List[T]) Equal(other *List[T]) bool {
return true return true
} }
// IsEmpty check if the list is empty or not // IsEmpty check if the list is empty or not.
func (l *List[T]) IsEmpty() bool { func (l *List[T]) IsEmpty() bool {
return len(l.data) == 0 return len(l.data) == 0
} }
// Clear the data of list // Clear the data of list.
func (l *List[T]) Clear() { func (l *List[T]) Clear() {
l.data = make([]T, 0) l.data = make([]T, 0)
} }
// Clone return a copy of list // Clone return a copy of list.
func (l *List[T]) Clone() *List[T] { func (l *List[T]) Clone() *List[T] {
cl := NewList(make([]T, len(l.data))) cl := NewList(make([]T, len(l.data)))
copy(cl.data, l.data) copy(cl.data, l.data)
@@ -232,7 +232,7 @@ func (l *List[T]) Clone() *List[T] {
return cl return cl
} }
// Merge two list, return new list, don't change original list // Merge two list, return new list, don't change original list.
func (l *List[T]) Merge(other *List[T]) *List[T] { func (l *List[T]) Merge(other *List[T]) *List[T] {
l1, l2 := len(l.data), len(other.data) l1, l2 := len(l.data), len(other.data)
ml := NewList(make([]T, l1+l2)) ml := NewList(make([]T, l1+l2))
@@ -243,17 +243,17 @@ func (l *List[T]) Merge(other *List[T]) *List[T] {
return ml return ml
} }
// Size return number of list data items // Size return number of list data items.
func (l *List[T]) Size() int { func (l *List[T]) Size() int {
return len(l.data) return len(l.data)
} }
// Cap return cap of the inner data // Cap return cap of the inner data.
func (l *List[T]) Cap() int { func (l *List[T]) Cap() int {
return cap(l.data) return cap(l.data)
} }
// Swap the value of index i and j in list // Swap the value of index i and j in list.
func (l *List[T]) Swap(i, j int) { func (l *List[T]) Swap(i, j int) {
size := len(l.data) size := len(l.data)
if i < 0 || i >= size || j < 0 || j >= size { if i < 0 || i >= size || j < 0 || j >= size {
@@ -262,14 +262,14 @@ func (l *List[T]) Swap(i, j int) {
l.data[i], l.data[j] = l.data[j], l.data[i] l.data[i], l.data[j] = l.data[j], l.data[i]
} }
// Reverse the item order of list // Reverse the item order of list.
func (l *List[T]) Reverse() { func (l *List[T]) Reverse() {
for i, j := 0, len(l.data)-1; i < j; i, j = i+1, j-1 { for i, j := 0, len(l.data)-1; i < j; i, j = i+1, j-1 {
l.data[i], l.data[j] = l.data[j], l.data[i] l.data[i], l.data[j] = l.data[j], l.data[i]
} }
} }
// Unique remove duplicate items in list // Unique remove duplicate items in list.
func (l *List[T]) Unique() { func (l *List[T]) Unique() {
data := l.data data := l.data
size := len(data) size := len(data)
@@ -303,7 +303,7 @@ func (l *List[T]) Union(other *List[T]) *List[T] {
return result return result
} }
// Intersection creates a new list whose element both be contained in list l and other // Intersection creates a new list whose element both be contained in list l and other.
func (l *List[T]) Intersection(other *List[T]) *List[T] { func (l *List[T]) Intersection(other *List[T]) *List[T] {
result := NewList(make([]T, 0)) result := NewList(make([]T, 0))

View File

@@ -9,17 +9,20 @@ type theTime struct {
unix int64 unix int64
} }
// NewUnixNow return unix timestamp of current time // NewUnixNow return unix timestamp of current time.
// Play: https://go.dev/play/p/U4PPx-9D0oz
func NewUnixNow() *theTime { func NewUnixNow() *theTime {
return &theTime{unix: time.Now().Unix()} return &theTime{unix: time.Now().Unix()}
} }
// NewUnix return unix timestamp of specified time // NewUnix return unix timestamp of specified time.
// Play: https://go.dev/play/p/psoSuh_kLRt
func NewUnix(unix int64) *theTime { func NewUnix(unix int64) *theTime {
return &theTime{unix: unix} return &theTime{unix: unix}
} }
// NewFormat return unix timestamp of specified time string, t should be "yyyy-mm-dd hh:mm:ss" // NewFormat return unix timestamp of specified time string, t should be "yyyy-mm-dd hh:mm:ss".
// Play: https://go.dev/play/p/VkW08ZOaXPZ
func NewFormat(t string) (*theTime, error) { func NewFormat(t string) (*theTime, error) {
timeLayout := "2006-01-02 15:04:05" timeLayout := "2006-01-02 15:04:05"
loc := time.FixedZone("CST", 8*3600) loc := time.FixedZone("CST", 8*3600)
@@ -30,7 +33,8 @@ func NewFormat(t string) (*theTime, error) {
return &theTime{unix: tt.Unix()}, nil return &theTime{unix: tt.Unix()}, nil
} }
// NewISO8601 return unix timestamp of specified iso8601 time string // NewISO8601 return unix timestamp of specified iso8601 time string.
// Play: https://go.dev/play/p/mkhOHQkdeA2
func NewISO8601(iso8601 string) (*theTime, error) { func NewISO8601(iso8601 string) (*theTime, error) {
t, err := time.ParseInLocation(time.RFC3339, iso8601, time.UTC) t, err := time.ParseInLocation(time.RFC3339, iso8601, time.UTC)
if err != nil { if err != nil {
@@ -39,22 +43,26 @@ func NewISO8601(iso8601 string) (*theTime, error) {
return &theTime{unix: t.Unix()}, nil return &theTime{unix: t.Unix()}, nil
} }
// ToUnix return unix timestamp // ToUnix return unix timestamp.
// Play: https://go.dev/play/p/_LUiwAdocjy
func (t *theTime) ToUnix() int64 { func (t *theTime) ToUnix() int64 {
return t.unix return t.unix
} }
// ToFormat return the time string 'yyyy-mm-dd hh:mm:ss' of unix time // ToFormat return the time string 'yyyy-mm-dd hh:mm:ss' of unix time.
// Play: https://go.dev/play/p/VkW08ZOaXPZ
func (t *theTime) ToFormat() string { func (t *theTime) ToFormat() string {
return time.Unix(t.unix, 0).Format("2006-01-02 15:04:05") return time.Unix(t.unix, 0).Format("2006-01-02 15:04:05")
} }
// ToFormatForTpl return the time string which format is specified tpl // ToFormatForTpl return the time string which format is specified tpl.
// Play: https://go.dev/play/p/nyXxXcQJ8L5
func (t *theTime) ToFormatForTpl(tpl string) string { func (t *theTime) ToFormatForTpl(tpl string) string {
return time.Unix(t.unix, 0).Format(tpl) return time.Unix(t.unix, 0).Format(tpl)
} }
// ToFormatForTpl return iso8601 time string // ToFormatForTpl return iso8601 time string.
// Play: https://go.dev/play/p/mkhOHQkdeA2
func (t *theTime) ToIso8601() string { func (t *theTime) ToIso8601() string {
return time.Unix(t.unix, 0).Format(time.RFC3339) return time.Unix(t.unix, 0).Format(time.RFC3339)
} }

View File

@@ -19,9 +19,6 @@ func TestToUnix(t *testing.T) {
func TestToFormat(t *testing.T) { func TestToFormat(t *testing.T) {
assert := internal.NewAssert(t, "TestToFormat") assert := internal.NewAssert(t, "TestToFormat")
_, err := NewFormat("2022/03/18 17:04:05")
assert.IsNotNil(err)
tm, err := NewFormat("2022-03-18 17:04:05") tm, err := NewFormat("2022-03-18 17:04:05")
assert.IsNil(err) assert.IsNil(err)

View File

@@ -54,54 +54,64 @@ func init() {
} }
} }
// AddMinute add or sub minute to the time // AddMinute add or sub minute to the time.
// Play: https://go.dev/play/p/nT1heB1KUUK
func AddMinute(t time.Time, minute int64) time.Time { func AddMinute(t time.Time, minute int64) time.Time {
return t.Add(time.Minute * time.Duration(minute)) return t.Add(time.Minute * time.Duration(minute))
} }
// AddHour add or sub hour to the time // AddHour add or sub hour to the time.
// Play: https://go.dev/play/p/rcMjd7OCsi5
func AddHour(t time.Time, hour int64) time.Time { func AddHour(t time.Time, hour int64) time.Time {
return t.Add(time.Hour * time.Duration(hour)) return t.Add(time.Hour * time.Duration(hour))
} }
// AddDay add or sub day to the time // AddDay add or sub day to the time.
// Play: https://go.dev/play/p/dIGbs_uTdFa
func AddDay(t time.Time, day int64) time.Time { func AddDay(t time.Time, day int64) time.Time {
return t.Add(24 * time.Hour * time.Duration(day)) return t.Add(24 * time.Hour * time.Duration(day))
} }
// GetNowDate return format yyyy-mm-dd of current date // GetNowDate return format yyyy-mm-dd of current date.
// Play: https://go.dev/play/p/PvfkPpcpBBf
func GetNowDate() string { func GetNowDate() string {
return time.Now().Format("2006-01-02") return time.Now().Format("2006-01-02")
} }
// GetNowTime return format hh-mm-ss of current time // GetNowTime return format hh-mm-ss of current time.
// Play: https://go.dev/play/p/l7BNxCkTmJS
func GetNowTime() string { func GetNowTime() string {
return time.Now().Format("15:04:05") return time.Now().Format("15:04:05")
} }
// GetNowDateTime return format yyyy-mm-dd hh-mm-ss of current datetime // GetNowDateTime return format yyyy-mm-dd hh-mm-ss of current datetime.
// Play: https://go.dev/play/p/pI4AqngD0al
func GetNowDateTime() string { func GetNowDateTime() string {
return time.Now().Format("2006-01-02 15:04:05") return time.Now().Format("2006-01-02 15:04:05")
} }
// GetZeroHourTimestamp return timestamp of zero hour (timestamp of 00:00) // GetZeroHourTimestamp return timestamp of zero hour (timestamp of 00:00).
// Play: https://go.dev/play/p/QmL2oIaGE3q
func GetZeroHourTimestamp() int64 { func GetZeroHourTimestamp() int64 {
ts := time.Now().Format("2006-01-02") ts := time.Now().Format("2006-01-02")
t, _ := time.Parse("2006-01-02", ts) t, _ := time.Parse("2006-01-02", ts)
return t.UTC().Unix() - 8*3600 return t.UTC().Unix() - 8*3600
} }
// GetNightTimestamp return timestamp of zero hour (timestamp of 23:59) // GetNightTimestamp return timestamp of zero hour (timestamp of 23:59).
// Play: https://go.dev/play/p/UolysR3MYP1
func GetNightTimestamp() int64 { func GetNightTimestamp() int64 {
return GetZeroHourTimestamp() + 86400 - 1 return GetZeroHourTimestamp() + 86400 - 1
} }
// FormatTimeToStr convert time to string // FormatTimeToStr convert time to string.
// Play: https://go.dev/play/p/_Ia7M8H_OvE
func FormatTimeToStr(t time.Time, format string) string { func FormatTimeToStr(t time.Time, format string) string {
return t.Format(timeFormat[format]) return t.Format(timeFormat[format])
} }
// FormatStrToTime convert string to time // FormatStrToTime convert string to time.
// Play: https://go.dev/play/p/1h9FwdU8ql4
func FormatStrToTime(str, format string) (time.Time, error) { func FormatStrToTime(str, format string) (time.Time, error) {
v, ok := timeFormat[format] v, ok := timeFormat[format]
if !ok { if !ok {
@@ -111,43 +121,50 @@ func FormatStrToTime(str, format string) (time.Time, error) {
return time.Parse(v, str) return time.Parse(v, str)
} }
// BeginOfMinute return beginning minute time of day // BeginOfMinute return beginning minute time of day.
// Play: https://go.dev/play/p/ieOLVJ9CiFT
func BeginOfMinute(t time.Time) time.Time { func BeginOfMinute(t time.Time) time.Time {
y, m, d := t.Date() y, m, d := t.Date()
return time.Date(y, m, d, t.Hour(), t.Minute(), 0, 0, t.Location()) return time.Date(y, m, d, t.Hour(), t.Minute(), 0, 0, t.Location())
} }
// EndOfMinute return end minute time of day // EndOfMinute return end minute time of day.
// Play: https://go.dev/play/p/yrL5wGzPj4z
func EndOfMinute(t time.Time) time.Time { func EndOfMinute(t time.Time) time.Time {
y, m, d := t.Date() y, m, d := t.Date()
return time.Date(y, m, d, t.Hour(), t.Minute(), 59, int(time.Second-time.Nanosecond), t.Location()) return time.Date(y, m, d, t.Hour(), t.Minute(), 59, int(time.Second-time.Nanosecond), t.Location())
} }
// BeginOfHour return beginning hour time of day // BeginOfHour return beginning hour time of day.
// Play: https://go.dev/play/p/GhdGFnDWpYs
func BeginOfHour(t time.Time) time.Time { func BeginOfHour(t time.Time) time.Time {
y, m, d := t.Date() y, m, d := t.Date()
return time.Date(y, m, d, t.Hour(), 0, 0, 0, t.Location()) return time.Date(y, m, d, t.Hour(), 0, 0, 0, t.Location())
} }
// EndOfHour return end hour time of day // EndOfHour return end hour time of day.
// Play: https://go.dev/play/p/6ce3j_6cVqN
func EndOfHour(t time.Time) time.Time { func EndOfHour(t time.Time) time.Time {
y, m, d := t.Date() y, m, d := t.Date()
return time.Date(y, m, d, t.Hour(), 59, 59, int(time.Second-time.Nanosecond), t.Location()) return time.Date(y, m, d, t.Hour(), 59, 59, int(time.Second-time.Nanosecond), t.Location())
} }
// BeginOfDay return beginning hour time of day // BeginOfDay return beginning hour time of day.
// Play: https://go.dev/play/p/94m_UT6cWs9
func BeginOfDay(t time.Time) time.Time { func BeginOfDay(t time.Time) time.Time {
y, m, d := t.Date() y, m, d := t.Date()
return time.Date(y, m, d, 0, 0, 0, 0, t.Location()) return time.Date(y, m, d, 0, 0, 0, 0, t.Location())
} }
// EndOfDay return end time of day // EndOfDay return end time of day.
// Play: https://go.dev/play/p/eMBOvmq5Ih1
func EndOfDay(t time.Time) time.Time { func EndOfDay(t time.Time) time.Time {
y, m, d := t.Date() y, m, d := t.Date()
return time.Date(y, m, d, 23, 59, 59, int(time.Second-time.Nanosecond), t.Location()) return time.Date(y, m, d, 23, 59, 59, int(time.Second-time.Nanosecond), t.Location())
} }
// BeginOfWeek return beginning week, default week begin from Sunday // BeginOfWeek return beginning week, default week begin from Sunday.
// Play: https://go.dev/play/p/ynjoJPz7VNV
func BeginOfWeek(t time.Time, beginFrom ...time.Weekday) time.Time { func BeginOfWeek(t time.Time, beginFrom ...time.Weekday) time.Time {
var beginFromWeekday = time.Sunday var beginFromWeekday = time.Sunday
if len(beginFrom) > 0 { if len(beginFrom) > 0 {
@@ -161,7 +178,8 @@ func BeginOfWeek(t time.Time, beginFrom ...time.Weekday) time.Time {
return beginOfWeek return beginOfWeek
} }
// EndOfWeek return end week time, default week end with Saturday // EndOfWeek return end week time, default week end with Saturday.
// Play: https://go.dev/play/p/i08qKXD9flf
func EndOfWeek(t time.Time, endWith ...time.Weekday) time.Time { func EndOfWeek(t time.Time, endWith ...time.Weekday) time.Time {
var endWithWeekday = time.Saturday var endWithWeekday = time.Saturday
if len(endWith) > 0 { if len(endWith) > 0 {
@@ -175,24 +193,28 @@ func EndOfWeek(t time.Time, endWith ...time.Weekday) time.Time {
return endWithWeek return endWithWeek
} }
// BeginOfMonth return beginning of month // BeginOfMonth return beginning of month.
// Play: https://go.dev/play/p/bWXVFsmmzwL
func BeginOfMonth(t time.Time) time.Time { func BeginOfMonth(t time.Time) time.Time {
y, m, _ := t.Date() y, m, _ := t.Date()
return time.Date(y, m, 1, 0, 0, 0, 0, t.Location()) return time.Date(y, m, 1, 0, 0, 0, 0, t.Location())
} }
// EndOfMonth return end of month // EndOfMonth return end of month.
// Play: https://go.dev/play/p/_GWh10B3Nqi
func EndOfMonth(t time.Time) time.Time { func EndOfMonth(t time.Time) time.Time {
return BeginOfMonth(t).AddDate(0, 1, 0).Add(-time.Nanosecond) return BeginOfMonth(t).AddDate(0, 1, 0).Add(-time.Nanosecond)
} }
// BeginOfYear return beginning of year // BeginOfYear return the date time at the begin of year.
// Play: https://go.dev/play/p/i326DSwLnV8
func BeginOfYear(t time.Time) time.Time { func BeginOfYear(t time.Time) time.Time {
y, _, _ := t.Date() y, _, _ := t.Date()
return time.Date(y, time.January, 1, 0, 0, 0, 0, t.Location()) return time.Date(y, time.January, 1, 0, 0, 0, 0, t.Location())
} }
// EndOfYear return end of year // EndOfYear return the date time at the end of year.
// Play: https://go.dev/play/p/G01cKlMCvNm
func EndOfYear(t time.Time) time.Time { func EndOfYear(t time.Time) time.Time {
return BeginOfYear(t).AddDate(1, 0, 0).Add(-time.Nanosecond) return BeginOfYear(t).AddDate(1, 0, 0).Add(-time.Nanosecond)
} }

View File

@@ -0,0 +1,323 @@
package datetime
import (
"fmt"
"reflect"
"time"
)
func ExampleAddDay() {
now := time.Now()
tomorrow := AddDay(now, 1)
diff1 := tomorrow.Sub(now)
yesterday := AddDay(now, -1)
diff2 := yesterday.Sub(now)
fmt.Println(diff1)
fmt.Println(diff2)
// Output:
// 24h0m0s
// -24h0m0s
}
func ExampleAddHour() {
now := time.Now()
after2Hours := AddHour(now, 2)
diff1 := after2Hours.Sub(now)
before2Hours := AddHour(now, -2)
diff2 := before2Hours.Sub(now)
fmt.Println(diff1)
fmt.Println(diff2)
// Output:
// 2h0m0s
// -2h0m0s
}
func ExampleAddMinute() {
now := time.Now()
after2Minutes := AddMinute(now, 2)
diff1 := after2Minutes.Sub(now)
before2Minutes := AddMinute(now, -2)
diff2 := before2Minutes.Sub(now)
fmt.Println(diff1)
fmt.Println(diff2)
// Output:
// 2m0s
// -2m0s
}
func ExampleGetNowDate() {
result := GetNowDate()
expected := time.Now().Format("2006-01-02")
fmt.Println(result == expected)
// Output:
// true
}
func ExampleGetNowTime() {
result := GetNowTime()
expected := time.Now().Format("15:04:05")
fmt.Println(result == expected)
// Output:
// true
}
func ExampleGetNowDateTime() {
result := GetNowDateTime()
expected := time.Now().Format("2006-01-02 15:04:05")
fmt.Println(result == expected)
// Output:
// true
}
// func ExampleGetZeroHourTimestamp() {
// ts := GetZeroHourTimestamp()
// fmt.Println(ts)
// // Output:
// // 1673107200
// }
// func ExampleGetNightTimestamp() {
// ts := GetNightTimestamp()
// fmt.Println(ts)
// // Output:
// // 1673193599
// }
func ExampleFormatTimeToStr() {
datetime, _ := time.Parse("2006-01-02 15:04:05", "2021-01-02 16:04:08")
result1 := FormatTimeToStr(datetime, "yyyy-mm-dd hh:mm:ss")
result2 := FormatTimeToStr(datetime, "yyyy-mm-dd")
result3 := FormatTimeToStr(datetime, "dd-mm-yy hh:mm:ss")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 2021-01-02 16:04:08
// 2021-01-02
// 02-01-21 16:04:08
}
func ExampleFormatStrToTime() {
result1, _ := FormatStrToTime("2021-01-02 16:04:08", "yyyy-mm-dd hh:mm:ss")
result2, _ := FormatStrToTime("2021-01-02", "yyyy-mm-dd")
result3, _ := FormatStrToTime("02-01-21 16:04:08", "dd-mm-yy hh:mm:ss")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 2021-01-02 16:04:08 +0000 UTC
// 2021-01-02 00:00:00 +0000 UTC
// 2021-01-02 16:04:08 +0000 UTC
}
func ExampleBeginOfMinute() {
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := BeginOfMinute(input)
fmt.Println(result)
// Output:
// 2023-01-08 18:50:00 +0000 UTC
}
func ExampleEndOfMinute() {
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := EndOfMinute(input)
fmt.Println(result)
// Output:
// 2023-01-08 18:50:59.999999999 +0000 UTC
}
func ExampleBeginOfHour() {
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := BeginOfHour(input)
fmt.Println(result)
// Output:
// 2023-01-08 18:00:00 +0000 UTC
}
func ExampleEndOfHour() {
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := EndOfHour(input)
fmt.Println(result)
// Output:
// 2023-01-08 18:59:59.999999999 +0000 UTC
}
func ExampleBeginOfDay() {
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := BeginOfDay(input)
fmt.Println(result)
// Output:
// 2023-01-08 00:00:00 +0000 UTC
}
func ExampleEndOfDay() {
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := EndOfDay(input)
fmt.Println(result)
// Output:
// 2023-01-08 23:59:59.999999999 +0000 UTC
}
func ExampleBeginOfWeek() {
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := BeginOfWeek(input)
fmt.Println(result)
// Output:
// 2023-01-08 00:00:00 +0000 UTC
}
func ExampleEndOfWeek() {
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := EndOfWeek(input)
fmt.Println(result)
// Output:
// 2023-01-14 23:59:59.999999999 +0000 UTC
}
func ExampleBeginOfMonth() {
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := BeginOfMonth(input)
fmt.Println(result)
// Output:
// 2023-01-01 00:00:00 +0000 UTC
}
func ExampleEndOfMonth() {
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := EndOfMonth(input)
fmt.Println(result)
// Output:
// 2023-01-31 23:59:59.999999999 +0000 UTC
}
func ExampleBeginOfYear() {
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := BeginOfYear(input)
fmt.Println(result)
// Output:
// 2023-01-01 00:00:00 +0000 UTC
}
func ExampleEndOfYear() {
input := time.Date(2023, 1, 8, 18, 50, 10, 100, time.UTC)
result := EndOfYear(input)
fmt.Println(result)
// Output:
// 2023-12-31 23:59:59.999999999 +0000 UTC
}
func ExampleNewUnix() {
result := NewUnix(1647597438)
fmt.Println(result)
// Output:
// &{1647597438}
}
func ExampleNewUnixNow() {
tm1 := NewUnixNow()
unixTimestamp := tm1.ToUnix()
tm2 := NewUnix(unixTimestamp)
fmt.Println(reflect.DeepEqual(tm1, tm2))
// Output:
// true
}
// func ExampleNewFormat() {
// tm, err := NewFormat("2022-03-18 17:04:05")
// if err != nil {
// return
// }
// result := tm.ToFormat()
// fmt.Println(result)
// // Output:
// // 2022-03-18 17:04:05
// }
// func ExampleNewISO8601() {
// tm, err := NewISO8601("2006-01-02T15:04:05.999Z")
// if err != nil {
// return
// }
// result := tm.ToIso8601()
// fmt.Println(result)
// // Output:
// // 2006-01-02T23:04:05+08:00
// }

View File

@@ -52,8 +52,8 @@ func TestGetNowDate(t *testing.T) {
assert.Equal(expected, GetNowDate()) assert.Equal(expected, GetNowDate())
} }
func TestGetNotTime(t *testing.T) { func TestGetNowTime(t *testing.T) {
assert := internal.NewAssert(t, "TestGetNotTime") assert := internal.NewAssert(t, "TestGetNowTime")
expected := time.Now().Format("15:04:05") expected := time.Now().Format("15:04:05")
assert.Equal(expected, GetNowTime()) assert.Equal(expected, GetNowTime())
} }
@@ -81,7 +81,6 @@ func TestFormatTimeToStr(t *testing.T) {
for i := 0; i < len(cases); i++ { for i := 0; i < len(cases); i++ {
actual := FormatTimeToStr(datetime, cases[i]) actual := FormatTimeToStr(datetime, cases[i])
assert.Equal(expected[i], actual) assert.Equal(expected[i], actual)
} }
} }

View File

@@ -5,10 +5,10 @@ Package cryptor contains some functions for data encryption and decryption. Supp
## Source: ## 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/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/main/cryptor/encrypt.go](https://github.com/duke-git/lancet/blob/main/cryptor/encrypt.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>

View File

@@ -5,10 +5,8 @@ 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/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/main/cryptor/encrypt.go](https://github.com/duke-git/lancet/blob/main/cryptor/encrypt.go)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -186,7 +184,7 @@ func main() {
### <span id="AesCtrCrypt">AesCtrCrypt</span> ### <span id="AesCtrCrypt">AesCtrCrypt</span>
<p>使用AES CTR算法模式加密/解密数据. 参数`key`的长度是16, 24 or 32。</p> <p>使用AES CTR算法模式加密/解密数据参数`key`的长度是16, 24 or 32。</p>
<b>函数签名:</b> <b>函数签名:</b>

View File

@@ -377,7 +377,7 @@ func main() {
``` ```
### <span id="EndOfDay">EndOfDay</span> ### <span id="EndOfDay">EndOfDay</span>
<p>返回指定时间的当天结束时间.</p> <p>返回指定时间的当天结束时间</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -541,7 +541,7 @@ func main() {
### <span id="GetNowDateTime">GetNowDateTime</span> ### <span id="GetNowDateTime">GetNowDateTime</span>
<p>获取当时日期和时间返回格式yyyy-mm-dd hh:mm:ss.</p> <p>获取当时日期和时间返回格式yyyy-mm-dd hh:mm:ss</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -568,7 +568,7 @@ func main() {
### <span id="GetZeroHourTimestamp">GetZeroHourTimestamp</span> ### <span id="GetZeroHourTimestamp">GetZeroHourTimestamp</span>
<p>获取零时时间戳(timestamp of 00:00).</p> <p>获取零时时间戳(timestamp of 00:00)</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -595,7 +595,7 @@ func main() {
### <span id="GetNightTimestamp">GetNightTimestamp</span> ### <span id="GetNightTimestamp">GetNightTimestamp</span>
<p>获取午夜时间戳(timestamp of 23:59).</p> <p>获取午夜时间戳(timestamp of 23:59)</p>
<b>函数签名:</b> <b>函数签名:</b>

View File

@@ -531,7 +531,7 @@ func main() {
### <span id="StructToUrlValues">StructToUrlValues</span> ### <span id="StructToUrlValues">StructToUrlValues</span>
<p>将结构体转为url values, 仅转化结构体导出字段并且包含`json` tag.</p> <p>将结构体转为url values, 仅转化结构体导出字段并且包含`json` tag</p>
<b>函数签名:</b> <b>函数签名:</b>

View File

@@ -46,12 +46,20 @@ import (
) )
func main() { func main() {
result1 := xerror.Unwrap(strconv.Atoi("42"))
fmt.Println(result1)
_, err := strconv.Atoi("4o2") _, err := strconv.Atoi("4o2")
defer func() { defer func() {
v := recover() v := recover()
fmt.Println(err.Error()) // err.Error() == v.(*strconv.NumError).Error() result2 := reflect.DeepEqual(err.Error(), v.(*strconv.NumError).Error())
fmt.Println(result2)
}() }()
xerror.Unwrap(strconv.Atoi("4o2")) xerror.Unwrap(strconv.Atoi("4o2"))
// Output:
// 42
// true
} }
``` ```

View File

@@ -28,7 +28,7 @@ import (
### <span id="Unwrap">Unwrap</span> ### <span id="Unwrap">Unwrap</span>
<p>如果err为nil则展开则它返回一个有效值如果err不是nil则Unwrap使用err发生恐慌。</p> <p>检查error, 如果err为nil则展开则它返回一个有效值如果err不是nil则Unwrap使用err发生panic。</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -46,12 +46,20 @@ import (
) )
func main() { func main() {
result1 := xerror.Unwrap(strconv.Atoi("42"))
fmt.Println(result1)
_, err := strconv.Atoi("4o2") _, err := strconv.Atoi("4o2")
defer func() { defer func() {
v := recover() v := recover()
fmt.Println(err.Error()) // err.Error() == v.(*strconv.NumError).Error() result2 := reflect.DeepEqual(err.Error(), v.(*strconv.NumError).Error())
fmt.Println(result2)
}() }()
xerror.Unwrap(strconv.Atoi("4o2")) xerror.Unwrap(strconv.Atoi("4o2"))
// Output:
// 42
// true
} }
``` ```

View File

@@ -19,7 +19,7 @@ func ExampleIsExist() {
} }
func ExampleCreateFile() { func ExampleCreateFile() {
fname := "./test.txt" fname := "./a.txt"
result1 := IsExist(fname) result1 := IsExist(fname)
@@ -175,11 +175,11 @@ func ExampleReadFileByLine() {
} }
func ExampleListFileNames() { func ExampleListFileNames() {
fileList, _ := ListFileNames("./") fileList, _ := ListFileNames("../formatter/")
fmt.Println(fileList) fmt.Println(fileList)
// Output: // Output:
// [file.go file_example_test.go file_test.go] // [formatter.go formatter_example_test.go formatter_test.go]
} }
func ExampleZip() { func ExampleZip() {

View File

@@ -96,16 +96,6 @@ func TestCopyFile(t *testing.T) {
os.Remove(destFile) os.Remove(destFile)
} }
func TestListFileNames(t *testing.T) {
assert := internal.NewAssert(t, "TestListFileNames")
filesInPath, err := ListFileNames("./")
assert.IsNil(err)
expected := []string{"file.go", "file_test.go"}
assert.Equal(expected, filesInPath)
}
func TestReadFileToString(t *testing.T) { func TestReadFileToString(t *testing.T) {
assert := internal.NewAssert(t, "TestReadFileToString") assert := internal.NewAssert(t, "TestReadFileToString")
@@ -241,3 +231,13 @@ func TestMiMeType(t *testing.T) {
assert.Equal("text/plain; charset=utf-8", MiMeType(f)) assert.Equal("text/plain; charset=utf-8", MiMeType(f))
assert.Equal("text/plain; charset=utf-8", MiMeType("./file.go")) assert.Equal("text/plain; charset=utf-8", MiMeType("./file.go"))
} }
func TestListFileNames(t *testing.T) {
assert := internal.NewAssert(t, "TestListFileNames")
filesInPath, err := ListFileNames("../formatter/")
assert.IsNil(err)
expected := []string{"formatter.go", "formatter_example_test.go", "formatter_test.go"}
assert.Equal(expected, filesInPath)
}

View File

@@ -145,14 +145,6 @@ func unsafeInvokeFunc(fn any, args ...any) []reflect.Value {
return fv.Call(params) return fv.Call(params)
} }
func functionValue(function any) reflect.Value {
v := reflect.ValueOf(function)
if v.Kind() != reflect.Func {
panic(fmt.Sprintf("Invalid function type, value of type %T", function))
}
return v
}
func mustBeFunction(function any) { func mustBeFunction(function any) {
v := reflect.ValueOf(function) v := reflect.ValueOf(function)
if v.Kind() != reflect.Func { if v.Kind() != reflect.Func {

View File

@@ -108,21 +108,21 @@ func ExampleDebounced() {
} }
func ExampleSchedule() { func ExampleSchedule() {
var result []string count := 0
appendFn := func(s string) { increase := func() {
result = append(result, s) count++
} }
stop := Schedule(1*time.Second, appendFn, "*") stop := Schedule(1*time.Second, increase)
time.Sleep(3 * time.Second) time.Sleep(3 * time.Second)
close(stop) close(stop)
fmt.Println(result) fmt.Println(count)
// Output: // Output:
// [* * *] // 3
} }
func ExamplePipeline() { func ExamplePipeline() {

View File

@@ -55,6 +55,7 @@ func Factorial(x uint) uint {
} }
// Percent calculate the percentage of value to total. // Percent calculate the percentage of value to total.
// Play: Todo
func Percent(val, total float64, n int) float64 { func Percent(val, total float64, n int) float64 {
if total == 0 { if total == 0 {
return float64(0) return float64(0)

View File

@@ -21,32 +21,32 @@ import (
"strings" "strings"
) )
//HttpGet send get http request // HttpGet send get http request.
func HttpGet(url string, params ...any) (*http.Response, error) { func HttpGet(url string, params ...any) (*http.Response, error) {
return doHttpRequest(http.MethodGet, url, params...) return doHttpRequest(http.MethodGet, url, params...)
} }
//HttpPost send post http request // HttpPost send post http request.
func HttpPost(url string, params ...any) (*http.Response, error) { func HttpPost(url string, params ...any) (*http.Response, error) {
return doHttpRequest(http.MethodPost, url, params...) return doHttpRequest(http.MethodPost, url, params...)
} }
//HttpPut send put http request // HttpPut send put http request.
func HttpPut(url string, params ...any) (*http.Response, error) { func HttpPut(url string, params ...any) (*http.Response, error) {
return doHttpRequest(http.MethodPut, url, params...) return doHttpRequest(http.MethodPut, url, params...)
} }
//HttpDelete send delete http request // HttpDelete send delete http request.
func HttpDelete(url string, params ...any) (*http.Response, error) { func HttpDelete(url string, params ...any) (*http.Response, error) {
return doHttpRequest(http.MethodDelete, url, params...) return doHttpRequest(http.MethodDelete, url, params...)
} }
// HttpPatch send patch http request // HttpPatch send patch http request.
func HttpPatch(url string, params ...any) (*http.Response, error) { func HttpPatch(url string, params ...any) (*http.Response, error) {
return doHttpRequest(http.MethodPatch, url, params...) return doHttpRequest(http.MethodPatch, url, params...)
} }
// ParseHttpResponse decode http response to specified interface // ParseHttpResponse decode http response to specified interface.
func ParseHttpResponse(resp *http.Response, obj any) error { func ParseHttpResponse(resp *http.Response, obj any) error {
if resp == nil { if resp == nil {
return errors.New("InvalidResp") return errors.New("InvalidResp")
@@ -55,7 +55,8 @@ func ParseHttpResponse(resp *http.Response, obj any) error {
return json.NewDecoder(resp.Body).Decode(obj) return json.NewDecoder(resp.Body).Decode(obj)
} }
// ConvertMapToQueryString convert map to sorted url query string // ConvertMapToQueryString convert map to sorted url query string.
// Play: https://go.dev/play/p/jnNt_qoSnRi
func ConvertMapToQueryString(param map[string]any) string { func ConvertMapToQueryString(param map[string]any) string {
if param == nil { if param == nil {
return "" return ""

View File

@@ -92,7 +92,8 @@ func NewHttpClientWithConfig(config *HttpClientConfig) *HttpClient {
return client return client
} }
// SendRequest send http request // SendRequest send http request.
// Play: https://go.dev/play/p/jUSgynekH7G
func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, error) { func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, error) {
err := validateRequest(request) err := validateRequest(request)
if err != nil { if err != nil {
@@ -128,7 +129,8 @@ func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, err
return resp, nil return resp, nil
} }
// DecodeResponse decode response into target object // DecodeResponse decode response into target object.
// Play: https://go.dev/play/p/jUSgynekH7G
func (client *HttpClient) DecodeResponse(resp *http.Response, target any) error { func (client *HttpClient) DecodeResponse(resp *http.Response, target any) error {
if resp == nil { if resp == nil {
return errors.New("invalid target param") return errors.New("invalid target param")
@@ -203,7 +205,8 @@ func validateRequest(req *HttpRequest) error {
} }
// StructToUrlValues convert struct to url valuse, // StructToUrlValues convert struct to url valuse,
// only convert the field which is exported and has `json` tag // only convert the field which is exported and has `json` tag.
// Play: https://go.dev/play/p/pFqMkM40w9z
func StructToUrlValues(targetStruct any) url.Values { func StructToUrlValues(targetStruct any) url.Values {
rv := reflect.ValueOf(targetStruct) rv := reflect.ValueOf(targetStruct)
rt := reflect.TypeOf(targetStruct) rt := reflect.TypeOf(targetStruct)

View File

@@ -0,0 +1,99 @@
package netutil
import "fmt"
func ExampleHttpClient_SendRequest() {
request := &HttpRequest{
RawURL: "https://jsonplaceholder.typicode.com/todos/1",
Method: "GET",
}
httpClient := NewHttpClient()
resp, err := httpClient.SendRequest(request)
if err != nil || resp.StatusCode != 200 {
return
}
type Todo struct {
UserId int `json:"userId"`
Id int `json:"id"`
Title string `json:"title"`
Completed bool `json:"completed"`
}
var todo Todo
err = httpClient.DecodeResponse(resp, &todo)
if err != nil {
return
}
fmt.Println(todo.Id)
// Output:
// 1
}
func ExampleHttpClient_DecodeResponse() {
request := &HttpRequest{
RawURL: "https://jsonplaceholder.typicode.com/todos/1",
Method: "GET",
}
httpClient := NewHttpClient()
resp, err := httpClient.SendRequest(request)
if err != nil || resp.StatusCode != 200 {
return
}
type Todo struct {
UserId int `json:"userId"`
Id int `json:"id"`
Title string `json:"title"`
Completed bool `json:"completed"`
}
var todo Todo
err = httpClient.DecodeResponse(resp, &todo)
if err != nil {
return
}
fmt.Println(todo.Id)
// Output:
// 1
}
func ExampleStructToUrlValues() {
type TodoQuery struct {
Id int `json:"id"`
Name string `json:"name"`
}
todoQuery := TodoQuery{
Id: 1,
Name: "Test",
}
todoValues := StructToUrlValues(todoQuery)
fmt.Println(todoValues.Get("id"))
fmt.Println(todoValues.Get("name"))
// Output:
// 1
// Test
}
func ExampleConvertMapToQueryString() {
var m = map[string]any{
"c": 3,
"a": 1,
"b": 2,
}
qs := ConvertMapToQueryString(m)
fmt.Println(qs)
// Output:
// a=1&b=2&c=3
}

View File

@@ -9,7 +9,8 @@ import (
"strings" "strings"
) )
// GetInternalIp return internal ipv4 // GetInternalIp return internal ipv4.
// Play: https://go.dev/play/p/5mbu-gFp7ei
func GetInternalIp() string { func GetInternalIp() string {
addr, err := net.InterfaceAddrs() addr, err := net.InterfaceAddrs()
if err != nil { if err != nil {
@@ -26,7 +27,8 @@ func GetInternalIp() string {
return "" return ""
} }
// GetRequestPublicIp return the requested public ip // GetRequestPublicIp return the requested public ip.
// Play: https://go.dev/play/p/kxU-YDc_eBo
func GetRequestPublicIp(req *http.Request) string { func GetRequestPublicIp(req *http.Request) string {
var ip string var ip string
for _, ip = range strings.Split(req.Header.Get("X-Forwarded-For"), ",") { for _, ip = range strings.Split(req.Header.Get("X-Forwarded-For"), ",") {
@@ -47,7 +49,8 @@ func GetRequestPublicIp(req *http.Request) string {
} }
// GetPublicIpInfo return public ip information // GetPublicIpInfo return public ip information
// return the PublicIpInfo struct // return the PublicIpInfo struct.
// Play: https://go.dev/play/p/YDxIfozsRHR
func GetPublicIpInfo() (*PublicIpInfo, error) { func GetPublicIpInfo() (*PublicIpInfo, error) {
resp, err := http.Get("http://ip-api.com/json/") resp, err := http.Get("http://ip-api.com/json/")
if err != nil { if err != nil {
@@ -69,7 +72,8 @@ func GetPublicIpInfo() (*PublicIpInfo, error) {
return &ip, nil return &ip, nil
} }
// GetIps return all ipv4 of system // GetIps return all ipv4 of system.
// Play: https://go.dev/play/p/NUFfcEmukx1
func GetIps() []string { func GetIps() []string {
var ips []string var ips []string
@@ -89,7 +93,8 @@ func GetIps() []string {
return ips return ips
} }
// GetMacAddrs get mac address // GetMacAddrs get mac address.
// Play: https://go.dev/play/p/Rq9UUBS_Xp1
func GetMacAddrs() []string { func GetMacAddrs() []string {
var macAddrs []string var macAddrs []string
@@ -125,7 +130,8 @@ type PublicIpInfo struct {
Ip string `json:"query"` Ip string `json:"query"`
} }
// IsPublicIP verify a ip is public or not // IsPublicIP verify a ip is public or not.
// Play: https://go.dev/play/p/nmktSQpJZnn
func IsPublicIP(IP net.IP) bool { func IsPublicIP(IP net.IP) bool {
if IP.IsLoopback() || IP.IsLinkLocalMulticast() || IP.IsLinkLocalUnicast() { if IP.IsLoopback() || IP.IsLinkLocalMulticast() || IP.IsLinkLocalUnicast() {
return false return false
@@ -145,7 +151,8 @@ func IsPublicIP(IP net.IP) bool {
return false return false
} }
// IsInternalIP verify an ip is intranet or not // IsInternalIP verify an ip is intranet or not.
// Play: https://go.dev/play/p/sYGhXbgO4Cb
func IsInternalIP(IP net.IP) bool { func IsInternalIP(IP net.IP) bool {
if IP.IsLoopback() { if IP.IsLoopback() {
return true return true
@@ -159,7 +166,8 @@ func IsInternalIP(IP net.IP) bool {
return false return false
} }
// EncodeUrl encode url // EncodeUrl encode url.
// Play: https://go.dev/play/p/bsZ6BRC4uKI
func EncodeUrl(urlStr string) (string, error) { func EncodeUrl(urlStr string) (string, error) {
URL, err := url.Parse(urlStr) URL, err := url.Parse(urlStr)
if err != nil { if err != nil {

View File

@@ -0,0 +1,91 @@
package netutil
import (
"fmt"
"net"
"net/http"
)
func ExampleGetInternalIp() {
internalIp := GetInternalIp()
result := IsInternalIP(net.ParseIP(internalIp))
fmt.Println(result)
// Output:
// true
}
func ExampleGetPublicIpInfo() {
ipInfo, err := GetPublicIpInfo()
if err != nil {
return
}
result := IsPublicIP(net.ParseIP(ipInfo.Ip))
fmt.Println(result)
// Output:
// true
}
func ExampleGetRequestPublicIp() {
ip := "36.112.24.10"
request := http.Request{
Method: "GET",
Header: http.Header{
"X-Forwarded-For": {ip},
},
}
publicIp := GetRequestPublicIp(&request)
fmt.Println(publicIp)
// Output:
// 36.112.24.10
}
func ExampleIsInternalIP() {
ip1 := IsInternalIP(net.ParseIP("127.0.0.1"))
ip2 := IsInternalIP(net.ParseIP("192.168.0.1"))
ip3 := IsInternalIP(net.ParseIP("36.112.24.10"))
fmt.Println(ip1)
fmt.Println(ip2)
fmt.Println(ip3)
// Output:
// true
// true
// false
}
func ExampleIsPublicIP() {
ip1 := IsPublicIP(net.ParseIP("127.0.0.1"))
ip2 := IsPublicIP(net.ParseIP("192.168.0.1"))
ip3 := IsPublicIP(net.ParseIP("36.112.24.10"))
fmt.Println(ip1)
fmt.Println(ip2)
fmt.Println(ip3)
// Output:
// false
// false
// true
}
func ExampleEncodeUrl() {
urlAddr := "http://www.lancet.com?a=1&b=[2]"
encodedUrl, err := EncodeUrl(urlAddr)
if err != nil {
return
}
fmt.Println(encodedUrl)
// Output:
// http://www.lancet.com?a=1&b=%5B2%5D
}

View File

@@ -34,21 +34,24 @@ type RetryFunc func() error
// Option is for adding retry config // Option is for adding retry config
type Option func(*RetryConfig) type Option func(*RetryConfig)
// RetryTimes set times of retry // RetryTimes set times of retry.
// Play: https://go.dev/play/p/ssfVeU2SwLO
func RetryTimes(n uint) Option { func RetryTimes(n uint) Option {
return func(rc *RetryConfig) { return func(rc *RetryConfig) {
rc.retryTimes = n rc.retryTimes = n
} }
} }
// RetryDuration set duration of retries // RetryDuration set duration of retries.
// Play: https://go.dev/play/p/nk2XRmagfVF
func RetryDuration(d time.Duration) Option { func RetryDuration(d time.Duration) Option {
return func(rc *RetryConfig) { return func(rc *RetryConfig) {
rc.retryDuration = d rc.retryDuration = d
} }
} }
// Context set retry context config // Context set retry context config.
// Play: https://go.dev/play/p/xnAOOXv9GkS
func Context(ctx context.Context) Option { func Context(ctx context.Context) Option {
return func(rc *RetryConfig) { return func(rc *RetryConfig) {
rc.context = ctx rc.context = ctx
@@ -56,7 +59,8 @@ func Context(ctx context.Context) Option {
} }
// Retry executes the retryFunc repeatedly until it was successful or canceled by the context // Retry executes the retryFunc repeatedly until it was successful or canceled by the context
// The default times of retries is 5 and the default duration between retries is 3 seconds // The default times of retries is 5 and the default duration between retries is 3 seconds.
// Play: https://go.dev/play/p/nk2XRmagfVF
func Retry(retryFunc RetryFunc, opts ...Option) error { func Retry(retryFunc RetryFunc, opts ...Option) error {
config := &RetryConfig{ config := &RetryConfig{
retryTimes: DefaultRetryTimes, retryTimes: DefaultRetryTimes,

View File

@@ -0,0 +1,93 @@
package retry
import (
"context"
"errors"
"fmt"
"time"
)
func ExampleContext() {
ctx, cancel := context.WithCancel(context.TODO())
number := 0
increaseNumber := func() error {
number++
if number > 3 {
cancel()
}
return errors.New("error occurs")
}
Retry(increaseNumber,
RetryDuration(time.Microsecond*50),
Context(ctx),
)
fmt.Println(number)
// Output:
// 4
}
func ExampleRetryDuration() {
number := 0
increaseNumber := func() error {
number++
if number == 3 {
return nil
}
return errors.New("error occurs")
}
err := Retry(increaseNumber, RetryDuration(time.Microsecond*50))
if err != nil {
return
}
fmt.Println(number)
// Output:
// 3
}
func ExampleRetryTimes() {
number := 0
increaseNumber := func() error {
number++
if number == 3 {
return nil
}
return errors.New("error occurs")
}
err := Retry(increaseNumber, RetryTimes(2))
if err != nil {
fmt.Println(err)
}
// Output:
// function retry.ExampleRetryTimes.func1 run failed after 2 times retry
}
func ExampleRetry() {
number := 0
increaseNumber := func() error {
number++
if number == 3 {
return nil
}
return errors.New("error occurs")
}
err := Retry(increaseNumber, RetryDuration(time.Microsecond*50))
if err != nil {
return
}
fmt.Println(number)
// Output:
// 3
}

View File

@@ -283,6 +283,7 @@ func SplitEx(s, sep string, removeEmptyString bool) []string {
} }
// Substring returns a substring of the specified length starting at the specified offset position. // Substring returns a substring of the specified length starting at the specified offset position.
// Play: Todo
func Substring(s string, offset int, length uint) string { func Substring(s string, offset int, length uint) string {
rs := []rune(s) rs := []rune(s)
size := len(rs) size := len(rs)

View File

@@ -6,6 +6,7 @@ package xerror
// Unwrap if err is nil then it returns a valid value // Unwrap if err is nil then it returns a valid value
// If err is not nil, Unwrap panics with err. // If err is not nil, Unwrap panics with err.
// Play: https://go.dev/play/p/w84d7Mb3Afk
func Unwrap[T any](val T, err error) T { func Unwrap[T any](val T, err error) T {
if err != nil { if err != nil {
panic(err) panic(err)

View File

@@ -0,0 +1,25 @@
package xerror
import (
"fmt"
"reflect"
"strconv"
)
func ExampleUnwrap() {
result1 := Unwrap(strconv.Atoi("42"))
fmt.Println(result1)
_, err := strconv.Atoi("4o2")
defer func() {
v := recover()
result2 := reflect.DeepEqual(err.Error(), v.(*strconv.NumError).Error())
fmt.Println(result2)
}()
Unwrap(strconv.Atoi("4o2"))
// Output:
// 42
// true
}