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

Compare commits

..

86 Commits

Author SHA1 Message Date
dudaodong
584aabdf62 release v2.2.3 2023-07-03 14:09:04 +08:00
dudaodong
1b754a6264 doc: update link in readme 2023-07-03 11:57:50 +08:00
dudaodong
06a558d797 doc: update link in readme 2023-07-03 11:21:49 +08:00
dudaodong
423779d3ff doc: update link in readme 2023-07-03 11:14:55 +08:00
dudaodong
78c17a9e7b doc: update link in readme 2023-07-03 10:52:26 +08:00
dudaodong
529b9317d0 doc: update link in readme 2023-07-03 10:48:04 +08:00
dudaodong
dc838f645b doc: update link in readme 2023-07-03 10:43:05 +08:00
dudaodong
7f559c4940 doc: update link in readme 2023-07-03 10:42:22 +08:00
dudaodong
acb08dfd90 doc: update link in readme 2023-07-03 10:40:50 +08:00
dudaodong
ffe46fd06d update readme file 2023-07-02 22:31:17 +08:00
dudaodong
b419e46b9b doc: add package index 2023-07-02 22:12:47 +08:00
dudaodong
8fbcdfd515 doc: add pointer and tuple package to readme file 2023-07-02 21:06:10 +08:00
dudaodong
f03f48210c doc: update system package 2023-06-30 15:12:18 +08:00
dudaodong
742944e2f0 doc: add doc for tuple package 2023-06-30 15:11:26 +08:00
dudaodong
c0b491ad78 doc: add example for tuple package 2023-06-30 11:20:46 +08:00
dudaodong
e9abae2a92 doc: add doc for pointer package 2023-06-30 10:31:22 +08:00
dudaodong
8229de2f10 test: add parallel running for all unit test functions 2023-06-30 10:18:45 +08:00
dudaodong
ab364744b6 test: add parallel running for all unit test functions 2023-06-29 14:49:28 +08:00
dudaodong
17ff84fa1f test: add test for Tuple Zip and Unzip 2023-06-29 11:34:43 +08:00
dudaodong
bf50baa07d feat: add GetTodayStartTime and GetTodayEndTime 2023-06-29 11:03:28 +08:00
dudaodong
7d56da8108 feat: add Md5Byte 2023-06-29 10:33:29 +08:00
dudaodong
16c2df711b feat: add unzip for tuple 2023-06-28 20:06:02 +08:00
dudaodong
015f8c3f5c feat: add zip 2023-06-28 19:41:46 +08:00
dudaodong
ba25701d89 feat: add zip 2023-06-28 17:52:12 +08:00
dudaodong
a0cb4bb266 doc: add example for tuple package 2023-06-28 16:25:43 +08:00
dudaodong
d6ba7497f9 feat: add Tuple package 2023-06-28 15:58:41 +08:00
dudaodong
7da931e0a0 feat: add Abs 2023-06-27 10:24:35 +08:00
dudaodong
8f49078eb3 doc: add go playground demo 2023-06-20 14:04:18 +08:00
dudaodong
3050d93703 release v2.2.2 2023-06-20 11:11:27 +08:00
dudaodong
efcfbfb6a1 fix: fix failed unit test 2023-06-20 11:10:33 +08:00
dudaodong
844b7a2c3b release v2.2.2 2023-06-20 10:59:12 +08:00
dudaodong
c8a536eafc doc: add doc for ZipAppendEntry 2023-06-17 19:54:09 +08:00
dudaodong
0fd268face Merge branch 'main' into v2 2023-06-17 19:38:53 +08:00
TheLastSunset
8ced7e887f feat: add ZipAppendEntry (#113) 2023-06-17 19:36:42 +08:00
dudaodong
957568ed5c doc: format code in doc file 2023-06-15 10:13:27 +08:00
dudaodong
fffabd0ffa Merge branch 'main' into v2 2023-06-13 13:58:29 +08:00
Mickls
e839af3ef9 feat: Add support for uploading files in SendRequest (#111) 2023-06-13 13:55:47 +08:00
dudaodong
1650e70d04 Merge branch 'main' into v2 2023-06-13 10:15:17 +08:00
Thijs Schreijer
23382b2b76 fix doc comment typo (#110) 2023-06-12 20:13:14 +08:00
dudaodong
daa3aa3da2 doc: update text error 2023-06-09 11:31:16 +08:00
dudaodong
be355a23f3 doc: add doc for Utf8ToGbk and GbkToUtf8 2023-06-09 11:29:29 +08:00
dudaodong
95af83b0cb doc: add doc for Sum 2023-06-09 11:23:24 +08:00
dudaodong
1efdbc0973 doc: add doc for RemoveWhiteSpace 2023-06-09 11:19:35 +08:00
dudaodong
9b829aa695 feat: add RemoveWhiteSpace 2023-06-08 16:47:31 +08:00
dudaodong
bfa9091c09 test: clean code 2023-06-08 16:25:48 +08:00
dudaodong
c11d63c2e2 feat: add Sum 2023-06-08 16:18:25 +08:00
dudaodong
83832daeb1 feat: add Utf8ToGbk and GbkToUtf8 2023-06-08 15:50:44 +08:00
dudaodong
7311f84772 test: add test file 2023-06-08 14:50:46 +08:00
dudaodong
a63d78111e test: update ExampleRandUniqueIntSlice 2023-06-08 14:41:17 +08:00
dudaodong
e2fc2f1bc9 feat: add WirteCsvFile 2023-06-08 14:40:37 +08:00
dudaodong
23a0135947 doc: add doc for RandUniqueIntSlice 2023-06-07 14:21:29 +08:00
dudaodong
013b6457bb Merge branch 'main' into v2 2023-06-07 11:38:20 +08:00
dudaodong
e08a62b0ba doc: add doc for Log function 2023-06-07 11:37:12 +08:00
Liu Shuang
850800a233 feat: add RandUniqueIntSlice (#108) 2023-06-07 11:33:37 +08:00
dudaodong
a6a8fd88bc feat: add Log function 2023-06-06 14:34:40 +08:00
dudaodong
2f6ee84443 feat: add Of and Unwrap 2023-06-02 11:48:17 +08:00
dudaodong
b1c6614549 refactor: clean code 2023-06-01 16:58:42 +08:00
dudaodong
a8761eefb0 doc: update package comment for datastructure package 2023-06-01 14:28:04 +08:00
dudaodong
cbf8cfdffa doc: add go playground demo 2023-06-01 14:11:57 +08:00
dudaodong
286a187942 fix: fix go report validation issue 2023-06-01 11:49:49 +08:00
dudaodong
b787e99528 release v2.2.1 2023-06-01 10:45:32 +08:00
dudaodong
e54c9b2850 doc: add new function to readme file 2023-06-01 10:44:00 +08:00
dudaodong
8944109c4c doc: add doc for WriteBytesToFile and WriteStringToFile 2023-05-31 17:42:34 +08:00
dudaodong
10e3732f32 feat: add IsWeekend 2023-05-31 17:13:06 +08:00
dudaodong
a415597c6b Merge branch 'main' into v2 2023-05-31 17:06:47 +08:00
hhhhhxm
69b32fd043 新增判断是否是周末的方法 (#105)
* 新增判断是否是周末的方法

* 新增判断是否是周末的方法

---------

Co-authored-by: huangxingming <huangxingming@kezaihui.com>
2023-05-31 17:05:20 +08:00
dudaodong
75ed359084 feat: add WriteBytesToFile and WriteStringToFile 2023-05-31 16:56:18 +08:00
dudaodong
2c71b6375c doc: add doc for ContainsAny and ContainsAll 2023-05-31 15:56:20 +08:00
dudaodong
2894bec80c feat: add ContainsAll and ContainsAny 2023-05-31 10:51:16 +08:00
dudaodong
09ec5b97a6 doc: add doc for DayOfYear 2023-05-31 10:04:59 +08:00
hhhhhxm
46ecb117a5 增加判断某个日期是一年当中的第几天的方法 (#103)
* 增加判断某个日期是一年当中的第几天的方法

* 修改下函数名字

---------

Co-authored-by: huangxingming <huangxingming@kezaihui.com>
2023-05-31 09:54:23 +08:00
dudaodong
388171e739 doc: add doc for BetweenSeconds 2023-05-30 17:47:16 +08:00
dudaodong
6fbaf2b005 refactor: update TestBetweenSeconds and ExampleBetweenSeconds 2023-05-30 17:44:28 +08:00
dudaodong
53a91cad71 Merge branch 'main' into v2 2023-05-30 17:38:58 +08:00
tlei995
a51a182fb2 feat:add betweenSeconds func (#102)
Co-authored-by: leitao <leitao@kezaihui.com>
2023-05-30 17:37:29 +08:00
dudaodong
64982f0c89 fix: fix body param bug when send post request 2023-05-30 10:51:33 +08:00
dudaodong
f38f69ce17 Merge branch 'main' into v2 2023-05-29 20:10:34 +08:00
燕归来
a33ea3d013 fix: timeFormat["yyyy-mm-dd hh"] should be "2006-01-02 15" (#99) (#100)
* fix: timeFormat["yyyy-mm-dd hh"] should be "2006-01-02 15" (#99)

* test: add use cases for FormatTimeToStr
2023-05-29 20:08:17 +08:00
dudaodong
e35462fb14 fix: fix format error in init function 2023-05-29 16:09:30 +08:00
dudaodong
af106a4a8e doc: add doc for Cos and Sin 2023-05-28 20:12:40 +08:00
dudaodong
ec7232ec40 update readme file 2023-05-25 19:29:59 +08:00
dudaodong
67c1b54b5a feat: add Cos and Sin function 2023-05-25 17:51:40 +08:00
dudaodong
e149ae2f72 feat: add HideString 2023-05-23 18:39:59 +08:00
dudaodong
b1fcfce188 doc: add go playground demo 2023-05-19 11:42:29 +08:00
dudaodong
259dbce85e doc: add go playground demo 2023-05-19 11:42:17 +08:00
will
78aa679670 feat: add ContainNumber for validator (#97)
Co-authored-by: sunyaoyao <sunyaoyao@kezaihui.com>
2023-05-19 11:23:19 +08:00
120 changed files with 9266 additions and 1141 deletions

246
README.md
View File

@@ -4,7 +4,7 @@
<br/>
![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf)
[![Release](https://img.shields.io/badge/release-2.2.0-green.svg)](https://github.com/duke-git/lancet/releases)
[![Release](https://img.shields.io/badge/release-2.2.3-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)
[![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)
@@ -24,8 +24,8 @@ English | [简体中文](./README_zh-CN.md)
## Feature
- 👏 Comprehensive, efficient and reusable.
- 💪 500+ go util functions, support string, slice, datetime, net, crypt...
- 💅 Only depend on the go standard library.
- 💪 600+ go util functions, support string, slice, datetime, net, crypt...
- 💅 Only depends on two kinds of libraries: go standard library and golang.org/x.
- 🌍 Unit test for every exported function.
## Installation
@@ -38,7 +38,7 @@ English | [简体中文](./README_zh-CN.md)
go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x
```
2. <b>For users who use version below go1.18, you should install v1.x.x. The latest of v1.x.x is v1.3.8. </b>
2. <b>For users who use version below go1.18, you should install v1.x.x. The latest of v1.x.x is v1.4.0. </b>
```go
go get github.com/duke-git/lancet // below go1.18, install latest version of v1.x.x
@@ -73,7 +73,35 @@ func main() {
## Documentation
### 1. Algorithm package implements some basic algorithm. eg. sort, search.
### <span id="index">Index<span>
- [Algorithm](#Algorithm)
- [Compare](#Compare)
- [Concurrency](#Concurrency)
- [Condition](#Condition)
- [Convertor](#Convertor)
- [Cryptor](#Cryptor)
- [Datetime](#Datetime)
- [Datastructure](#Datastructure)
- [Fileutil](#Fileutil)
- [Formatter](#Formatter)
- [Function](#Function)
- [Maputil](#Maputil)
- [Mathutil](#Mathutil)
- [Netutil](#Netutil)
- [Pointer](#Pointer)
- [Random](#Random)
- [Retry](#Retry)
- [Slice](#Slice)
- [Stream](#Stream)
- [Structs](#Structs)
- [Strutil](#Strutil)
- [System](#System)
- [Tuple](#Tuple)
- [Validator](#Validator)
- [Xerror](#Xerror)
<h3 id="Algorithm"> 1. Algorithm package implements some basic algorithm. eg. sort, search. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span> </h3>
```go
import "github.com/duke-git/lancet/v2/algorithm"
@@ -118,7 +146,7 @@ import "github.com/duke-git/lancet/v2/algorithm"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm.md#LRUCache)]
[[play](https://go.dev/play/p/-EZjgOURufP)]
### 2. Compare package provides a lightweight comparison function on any type.
<h3 id="Compare"> 2. Compare package provides a lightweight comparison function on any type. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span> </h3>
```go
import "github.com/duke-git/lancet/v2/compare"
@@ -145,7 +173,7 @@ import "github.com/duke-git/lancet/v2/compare"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare.md#GreaterOrEqual)]
[[play](https://go.dev/play/p/vx8mP0U8DFk)]
### 3. Concurrency package contain some functions to support concurrent programming. eg, goroutine, channel, async.
<h3 id="Concurrency"> 3. Concurrency package contain some functions to support concurrent programming. eg, goroutine, channel, async. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span> </h3>
```go
import "github.com/duke-git/lancet/v2/concurrency"
@@ -184,7 +212,7 @@ import "github.com/duke-git/lancet/v2/concurrency"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency.md#Tee)]
[[play](https://go.dev/play/p/3TQPKnCirrP)]
### 4. Condition package contains some functions for conditional judgment. eg. And, Or, TernaryOperator...
<h3 id="Condition"> 4. Condition package contains some functions for conditional judgment. eg. And, Or, TernaryOperator...&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span> </h3>
```go
import "github.com/duke-git/lancet/v2/condition"
@@ -217,7 +245,7 @@ import "github.com/duke-git/lancet/v2/condition"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#TernaryOperator)]
[[play](https://go.dev/play/p/ElllPZY0guT)]
### 5. Convertor package contains some functions for data convertion.
<h3 id="Convertor"> 5. Convertor package contains some functions for data convertion. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span> </h3>
```go
import "github.com/duke-git/lancet/v2/convertor"
@@ -281,8 +309,15 @@ import "github.com/duke-git/lancet/v2/convertor"
[[play](https://go.dev/play/p/oZujoB5Sgg5)]
- **<big>ToInterface</big>** : converts reflect value to its interface type.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToInterface)]
[[play](https://go.dev/play/p/syqw0-WG7Xd)]
- **<big>Utf8ToGbk</big>** : converts utf8 encoding data to GBK encoding data
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#Utf8ToGbk)]
[[play](https://go.dev/play/p/9FlIaFLArIL)]
- **<big>GbkToUtf8</big>** : converts GBK encoding data to utf8 encoding data.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#GbkToUtf8)]
[[play](https://go.dev/play/p/OphmHCN_9u8)]
### 6. Cryptor package is for data encryption and decryption.
<h3 id="Cryptor"> 6. Cryptor package is for data encryption and decryption.</span> &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span></h3>
```go
import "github.com/duke-git/lancet/v2/cryptor"
@@ -386,7 +421,7 @@ import "github.com/duke-git/lancet/v2/cryptor"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor.md#RsaDecrypt)]
[[play](https://go.dev/play/p/uef0q1fz53I)]
### 7. Datetime package supports date and time format and compare.
<h3 id="Datetime"> 7. Datetime package supports date and time format and compare. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span></h3>
```go
import "github.com/duke-git/lancet/v2/datetime"
@@ -405,6 +440,7 @@ import "github.com/duke-git/lancet/v2/datetime"
[[play](https://go.dev/play/p/nT1heB1KUUK)]
- **<big>AddYear</big>** : add or sub year to the time.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddYear)]
[[play](https://go.dev/play/p/MqW2ujnBx10)]
- **<big>BeginOfMinute</big>** : return the date time at the begin of minute of specific date.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMinute)]
[[play](https://go.dev/play/p/ieOLVJ9CiFT)]
@@ -488,8 +524,18 @@ import "github.com/duke-git/lancet/v2/datetime"
[[play](https://go.dev/play/p/mkhOHQkdeA2)]
- **<big>IsLeapYear</big>** : check if param `year` is leap year or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#IsLeapYear)]
[[play](https://go.dev/play/p/xS1eS2ejGew)]
- **<big>BetweenSeconds</big>** : returns the number of seconds between two times.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BetweenSeconds)]
[[play](https://go.dev/play/p/n3YDRyfyXJu)]
- **<big>DayOfYear</big>** : returns which day of the year the parameter date `t` is.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#DayOfYear)]
[[play](https://go.dev/play/p/0hjqhTwFNlH)]
- **<big>IsWeekend</big>** : checks if passed time is weekend or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#IsWeekend)]
[[play](https://go.dev/play/p/cupRM5aZOIY)]
### 8. Datastructure package constains some common data structure. eg. list, linklist, stack, queue, set, tree, graph.
<h3 id="Datastructure"> 8. Datastructure package constains some common data structure. eg. list, linklist, stack, queue, set, tree, graph. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span></h3>
```go
import list "github.com/duke-git/lancet/v2/datastructure/list"
@@ -521,7 +567,7 @@ import hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
- **<big>Hashmap</big>** : hash map structure.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/hashmap.md)]
### 9. Fileutil package implements some basic functions for file operations.
<h3 id="Fileutil"> 9. Fileutil package implements some basic functions for file operations. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span></h3>
```go
import "github.com/duke-git/lancet/v2/fileutil"
@@ -568,9 +614,11 @@ import "github.com/duke-git/lancet/v2/fileutil"
- **<big>ReadFileByLine</big>** : read file line by line, return string slice of file content.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ReadFileByLine)]
[[play](https://go.dev/play/p/svJP_7ZrBrD)]
- **<big>Zip</big>** : create zip file.
- **<big>Zip</big>** : create a zip file of fpath, fpath could be a file or a directory.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#Zip)]
[[play](https://go.dev/play/p/j-3sWBp8ik_P)]
- **<big>ZipAppendEntry</big>** : append a single file or directory by fpath to an existing zip file.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ZipAppendEntry)]
- **<big>UnZip</big>** : unzip the zip file and save it to dest path.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#UnZip)]
[[play](https://go.dev/play/p/g0w34kS7B8m)]
@@ -592,8 +640,17 @@ import "github.com/duke-git/lancet/v2/fileutil"
- **<big>ReadCsvFile</big>** : read file content into slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#ReadCsvFile)]
[[play](https://go.dev/play/p/OExTkhGEd3_u)]
- **<big>WriteCsvFile</big>** : write content to target csv file.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#WriteCsvFile)]
[[play](https://go.dev/play/p/dAXm58Q5U1o)]
- **<big>WriteBytesToFile</big>** : write bytes to target file.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#WriteBytesToFile)]
[[play](https://go.dev/play/p/s7QlDxMj3P8)]
- **<big>WriteStringToFile</big>** : write string to target file.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#WriteStringToFile)]
[[play](https://go.dev/play/p/GhLS6d8lH_g)]
### 10. Formatter contains some functions for data formatting.
<h3 id="Formatter"> 10. Formatter contains some functions for data formatting. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span></h3>
```go
import "github.com/duke-git/lancet/v2/formatter"
@@ -623,7 +680,7 @@ import "github.com/duke-git/lancet/v2/formatter"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#ParseBinaryBytes)]
[[play](https://go.dev/play/p/69v1tTT62x8)]
### 11. Function package can control the flow of function execution and support part of functional programming
<h3 id="Function"> 11. Function package can control the flow of function execution and support part of functional programming.&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span></h3>
```go
import "github.com/duke-git/lancet/v2/function"
@@ -659,7 +716,7 @@ import "github.com/duke-git/lancet/v2/function"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function.md#Watcher)]
[[play](https://go.dev/play/p/l2yrOpCLd1I)]
### 12. Maputil package includes some functions to manipulate map.
<h3 id="Maputil"> 12. Maputil package includes some functions to manipulate map.&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span></h3>
```go
import "github.com/duke-git/lancet/v2/maputil"
@@ -731,7 +788,7 @@ import "github.com/duke-git/lancet/v2/maputil"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#IsDisjoint)]
[[play](https://go.dev/play/p/N9qgYg_Ho6f)]
### 13. Mathutil package implements some functions for math calculation.
<h3 id="Mathutil"> 13. Mathutil package implements some functions for math calculation. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</span></h3>
```go
import "github.com/duke-git/lancet/v2/mathutil"
@@ -765,7 +822,7 @@ import "github.com/duke-git/lancet/v2/mathutil"
[[play](https://go.dev/play/p/N9qgYg_Ho6f)]
- **<big>Percent</big>** : calculate the percentage of value to total.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Percent)]
[[play](https://go.dev/play/p/QQM9B13coSP)]
[[play](https://go.dev/play/p/s0NdFCtwuyd)]
- **<big>RoundToFloat</big>** : round up to n decimal places for float64.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#RoundToFloat)]
[[play](https://go.dev/play/p/ghyb528JRJL)]
@@ -795,10 +852,24 @@ import "github.com/duke-git/lancet/v2/mathutil"
[[play](https://go.dev/play/p/Rdd8UTHZJ7u)]
- **<big>GCD</big>** : return greatest common divisor (GCD) of integers.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#GCD)]
[[play](https://go.dev/play/p/CiEceLSoAKB)]
- **<big>LCM</big>** : return Least Common Multiple (LCM) of integers.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#LCM)]
[[play](https://go.dev/play/p/EjcZxfY7G_g)]
- **<big>Cos</big>** : return the cosine of the radian argument.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Cos)]
[[play](https://go.dev/play/p/Sm89LoIfvFq)]
- **<big>Sin</big>** : return the sine of the radian argument.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Sin)]
[[play](https://go.dev/play/p/TWMQlMywDsP)]
- **<big>Log</big>** : returns the logarithm of base n.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Log)]
[[play](https://go.dev/play/p/_d4bi8oyhat)]
- **<big>Sum</big>** : return sum of passed numbers.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#Sum)]
[[play](https://go.dev/play/p/1To2ImAMJA7)]
### 14. Netutil package contains functions to get net information and send http request.
<h3 id="Netutil"> 14. Netutil package contains functions to get net information and send http request. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/netutil"
@@ -871,7 +942,25 @@ import "github.com/duke-git/lancet/v2/netutil"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#IsTelnetConnected)]
[[play](https://go.dev/play/p/yiLCGtQv_ZG)]
### 15. Random package implements some basic functions to generate random int and string.
<h3 id="Pointer"> 15. Pointer package contains some util functions to operate go pointer. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/pointer"
```
#### Function list:
- **<big>ExtractPointer</big>** : return the underlying value by the given interface type.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/pointer.md#ExtractPointer)]
[[play](https://go.dev/play/p/D7HFjeWU2ZP)]
- **<big>Of</big>** : return a pointer to the value `v`.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/pointer.md#Of)]
[[play](https://go.dev/play/p/HFd70x4DrMj)]
- **<big>Unwrap</big>** : return the value from the pointer.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/pointer.md#Unwrap)]
[[play](https://go.dev/play/p/cgeu3g7cjWb)]
<h3 id="Random"> 16. Random package implements some basic functions to generate random int and string. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/random"
@@ -903,8 +992,11 @@ import "github.com/duke-git/lancet/v2/random"
- **<big>UUIdV4</big>** : generate a random UUID of version 4 according to RFC 4122.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random.md#UUIdV4)]
[[play](https://go.dev/play/p/_Z9SFmr28ft)]
- **<big>RandUniqueIntSlice</big>** : generate a slice of random int of length n that do not repeat.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random.md#RandUniqueIntSlice)]
[[play](https://go.dev/play/p/uBkRSOz73Ec)]
### 16. Retry package is for executing a function repeatedly until it was successful or canceled by the context.
<h3 id="Retry"> 17. Retry package is for executing a function repeatedly until it was successful or canceled by the context. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/retry"
@@ -928,7 +1020,7 @@ import "github.com/duke-git/lancet/v2/retry"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/retry.md#RetryTimes)]
[[play](https://go.dev/play/p/ssfVeU2SwLO)]
### 17. Slice contains some functions to manipulate slice.
<h3 id="Slice"> 18. Slice contains some functions to manipulate slice. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/slice"
@@ -1141,7 +1233,7 @@ import "github.com/duke-git/lancet/v2/slice"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#KeyBy)]
[[play](https://go.dev/play/p/uXod2LWD1Kg)]
### 18. Stream package implements a sequence of elements supporting sequential and operations. this package is an experiment to explore if stream in go can work as the way java does. its function is very limited.
<h3 id="Stream"> 19. Stream package implements a sequence of elements supporting sequential and operations. this package is an experiment to explore if stream in go can work as the way java does. its function is very limited. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/stream"
@@ -1205,6 +1297,7 @@ import "github.com/duke-git/lancet/v2/stream"
[[play](https://go.dev/play/p/9xEf0-6C1e3)]
- **<big>FindLast</big>** : returns the last element of this stream and true, or zero value and false if the stream is empty.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#FindLast)]
[[play](https://go.dev/play/p/WZD2rDAW-2h)]
- **<big>Max</big>** : returns the maximum element of this stream according to the provided less function. less fuction: a > b
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Max)]
[[play](https://go.dev/play/p/fm-1KOPtGzn)]
@@ -1227,7 +1320,7 @@ import "github.com/duke-git/lancet/v2/stream"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#ToSlice)]
[[play](https://go.dev/play/p/jI6_iZZuVFE)]
### 19. Structs package provides several high level functions to manipulate struct, tag, and field.
<h3 id="Structs"> 20. Structs package provides several high level functions to manipulate struct, tag, and field. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/structs"
@@ -1260,7 +1353,7 @@ import "github.com/duke-git/lancet/v2/structs"
- **<big>IsSlice</big>** : check if the field is a slice
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/field.md#IsSlice)]
### 20. Strutil package contains some functions to manipulate string.
<h3 id="Strutil"> 21. Strutil package contains some functions to manipulate string. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/strutil"
@@ -1285,6 +1378,12 @@ import "github.com/duke-git/lancet/v2/strutil"
- **<big>Capitalize</big>** : converts the first character of source string to upper case and the remaining to lower case.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Capitalize)]
[[play](https://go.dev/play/p/2OAjgbmAqHZ)]
- **<big>ContainsAll</big>** : return true if target string contains all the substrings.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#ContainsAll)]
[[play](https://go.dev/play/p/KECtK2Os4zq)]
- **<big>ContainsAny</big>** : return true if target string contains any one of the substrings.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#ContainsAny)]
[[play](https://go.dev/play/p/dZGSSMB3LXE)]
- **<big>IsString</big>** : checks if the parameter value data type is string or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#IsString)]
[[play](https://go.dev/play/p/IOgq7oF9ERm)]
@@ -1359,12 +1458,20 @@ import "github.com/duke-git/lancet/v2/strutil"
[[play](https://go.dev/play/p/qZo4lV2fomB)]
- **<big>ReplaceWithMap</big>** : returns a copy of `str`, which is replaced by a map in unordered way, case-sensitively.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#ReplaceWithMap)]
[[play](https://go.dev/play/p/h3t7CNj2Vvu)]
- **<big>Trim</big>** : strips whitespace (or other characters) from the beginning and end of a string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Trim)]
[[play](https://go.dev/play/p/Y0ilP0NRV3j)]
- **<big>SplitAndTrim</big>** : splits string `str` by a string `delimiter` to a slice, and calls Trim to every element of slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SplitAndTrim)]
[[play](https://go.dev/play/p/ZNL6o4SkYQ7)]
- **<big>HideString</big>** : Hide some chars in source string with param `replaceChar`.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#HideString)]
[[play](https://go.dev/play/p/pzbaIVCTreZ)]
- **<big>RemoveWhiteSpace</big>** : remove whitespace characters from a string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#RemoveWhiteSpace)]
### 21. System package contain some functions about os, runtime, shell command.
<h3 id="System"> 22. System package contain some functions about os, runtime, shell command. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/system"
@@ -1400,7 +1507,88 @@ import "github.com/duke-git/lancet/v2/system"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system.md#GetOsBits)]
[[play](https://go.dev/play/p/ml-_XH3gJbW)]
### 22. Validator package contains some functions for data validation.
<h3 id="Tuple"> 23. Tuple package implements tuple data type and some operations on it. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/tuple"
```
#### Function list:
- **<big>Tuple2</big>** : represents a 2 elemnets tuple.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple2)]
- **<big>Tuple2_Unbox</big>** : returns values in Tuple2.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple2_Unbox)]
- **<big>Zip2</big>** : create a slice of Tuple2, whose elements are correspond to the given slice elements.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Zip2)]
- **<big>Unzip2</big>** : create a group of slice from a slice of Tuple2.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Unzip2)]
- **<big>Tuple3</big>** : represents a 3 elemnets tuple.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple3)]
- **<big>Tuple3_Unbox</big>** : returns values in Tuple3.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple3_Unbox)]
- **<big>Zip3</big>** : create a slice of Tuple3, whose elements are correspond to the given slice elements.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Zip3)]
- **<big>Unzip3</big>** : create a group of slice from a slice of Tuple3.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Unzip3)]
- **<big>Tuple4</big>** : represents a 4 elemnets tuple.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple4)]
- **<big>Tuple4_Unbox</big>** : returns values in Tuple4.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple4_Unbox)]
- **<big>Zip4</big>** : create a slice of Tuple4, whose elements are correspond to the given slice elements.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Zip4)]
- **<big>Unzip4</big>** : create a group of slice from a slice of Tuple4.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Unzip4)]
- **<big>Tuple5</big>** : represents a 5 elemnets tuple.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple5)]
- **<big>Tuple5_Unbox</big>** : returns values in Tuple4.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple5_Unbox)]
- **<big>Zip5</big>** : create a slice of Tuple5, whose elements are correspond to the given slice elements.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Zip5)]
- **<big>Unzip5</big>** : create a group of slice from a slice of Tuple5.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Unzip5)]
- **<big>Tuple6</big>** : represents a 6 elemnets tuple.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple6)]
- **<big>Tuple6_Unbox</big>** : returns values in Tuple6.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple6_Unbox)]
- **<big>Zip6</big>** : create a slice of Tuple6, whose elements are correspond to the given slice elements.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Zip6)]
- **<big>Unzip6</big>** : create a group of slice from a slice of Tuple6.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Unzip6)]
- **<big>Tuple7</big>** : represents a 7 elemnets tuple.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple7)]
- **<big>Tuple7_Unbox</big>** : returns values in Tuple7.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple7_Unbox)]
- **<big>Zip7</big>** : create a slice of Tuple7, whose elements are correspond to the given slice elements.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Zip7)]
- **<big>Unzip7</big>** : create a group of slice from a slice of Tuple7.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Unzip7)]
- **<big>Tuple8</big>** : represents a 8 elemnets tuple.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple8)]
- **<big>Tuple8_Unbox</big>** : returns values in Tuple8.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple8_Unbox)]
- **<big>Zip8</big>** : create a slice of Tuple8, whose elements are correspond to the given slice elements.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Zip8)]
- **<big>Unzip8</big>** : create a group of slice from a slice of Tuple8.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Unzip8)]
- **<big>Tuple9</big>** : represents a 9 elemnets tuple.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple9)]
- **<big>Tuple9_Unbox</big>** : returns values in Tuple9.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple9_Unbox)]
- **<big>Zip9</big>** : create a slice of Tuple9, whose elements are correspond to the given slice elements.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Zip9)]
- **<big>Unzip9</big>** : create a group of slice from a slice of Tuple9.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Unzip9)]
- **<big>Tuple10</big>** : represents a 10 elemnets tuple.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple10)]
- **<big>Tuple10_Unbox</big>** : returns values in Tuple10.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Tuple10_Unbox)]
- **<big>Zip10</big>** : create a slice of Tuple10, whose elements are correspond to the given slice elements.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Zip10)]
- **<big>Unzip10</big>** : create a group of slice from a slice of Tuple10.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple.md#Unzip10)]
<h3 id="Validator"> 24. Validator package contains some functions for data validation. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/validator"
@@ -1508,7 +1696,7 @@ import "github.com/duke-git/lancet/v2/validator"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsPrintable)]
[[play](https://go.dev/play/p/Pe1FE2gdtTP)]
### 23. xerror package implements helpers for errors.
<h3 id="Xerror"> 25. Xerror package implements helpers for errors. &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">index</a></h3>
```go
import "github.com/duke-git/lancet/v2/xerror"

View File

@@ -4,7 +4,7 @@
<br/>
![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf)
[![Release](https://img.shields.io/badge/release-2.2.0-green.svg)](https://github.com/duke-git/lancet/releases)
[![Release](https://img.shields.io/badge/release-2.2.3-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)
[![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)
@@ -22,10 +22,10 @@
## 特性
- 👏 全面、高效、可复用
- 💪 500+常用 go 工具函数,支持 string、slice、datetime、net、crypt...
- 💅 只依赖 go 标准库
- 🌍 所有导出函数单元测试覆盖率 100%
- 👏 全面、高效、可复用
- 💪 600+常用 go 工具函数,支持 string、slice、datetime、net、crypt...
- 💅 只依赖 go 标准库和 golang.org/x。
- 🌍 所有导出函数单元测试覆盖率 100%
## 安装
@@ -37,7 +37,7 @@
go get github.com/duke-git/lancet/v2 //安装v2最新版本v2.x.x
```
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.3.7。</b>
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.4.0。</b>
```go
go get github.com/duke-git/lancet// 使用go1.18以下版本, 必须安装v1.x.x版本
@@ -72,13 +72,41 @@ func main() {
## 文档
### 1. algorithm 包实现一些基本查找和排序算法。
### <span id="index">目录<span>
- [Algorithm](#Algorithm)
- [Compare](#Compare)
- [Concurrency](#Concurrency)
- [Condition](#Condition)
- [Convertor](#Convertor)
- [Cryptor](#Cryptor)
- [Datetime](#Datetime)
- [Datastructure](#Datastructure)
- [Fileutil](#Fileutil)
- [Formatter](#Formatter)
- [Function](#Function)
- [Maputil](#Maputil)
- [Mathutil](#Mathutil)
- [Netutil](#Netutil)
- [Pointer](#Pointer)
- [Random](#Random)
- [Retry](#Retry)
- [Slice](#Slice)
- [Stream](#Stream)
- [Structs](#Structs)
- [Strutil](#Strutil)
- [System](#System)
- [Tuple](#Tuple)
- [Validator](#Validator)
- [Xerror](#Xerror)
<h3 id="Algorithm"> 1. algorithm 包实现一些基本查找和排序算法。 &nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/algorithm"
```
#### Function list:
#### 函数列表:
- **<big>BubbleSort</big>** : 使用冒泡排序算法对切片进行排序。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#BubbleSort)]
@@ -117,13 +145,13 @@ import "github.com/duke-git/lancet/v2/algorithm"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/algorithm_zh-CN.md#LRUCache)]
[[play](https://go.dev/play/p/-EZjgOURufP)]
### 2. compare 包提供几个轻量级的类型比较函数。
<h3 id="Compare"> 2. compare 包提供几个轻量级的类型比较函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/compare"
```
#### Function list:
#### 函数列表:
- **<big>Equal</big>** : 检查两个值是否相等(检查类型和值)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare_zh-CN.md#Equal)]
@@ -144,13 +172,13 @@ import "github.com/duke-git/lancet/v2/compare"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/compare_zh-CN.md#GreaterOrEqual)]
[[play](https://go.dev/play/p/vx8mP0U8DFk)]
### 3. concurrency 包含一些支持并发编程的功能。例如goroutine, channel, async 等。
<h3 id="Concurrency"> 3. concurrency 包含一些支持并发编程的功能。例如goroutine, channel, async 等。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/concurrency"
```
#### Function list:
#### 函数列表:
- **<big>NewChannel</big>** : 返回一个 Channel 指针实例。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#NewChannel)]
@@ -183,13 +211,13 @@ import "github.com/duke-git/lancet/v2/concurrency"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/concurrency_zh-CN.md#Tee)]
[[play](https://go.dev/play/p/3TQPKnCirrP)]
### 4. condition 包含一些用于条件判断的函数。
<h3 id="Condition"> 4. condition 包含一些用于条件判断的函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/condition"
```
#### Function list:
#### 函数列表:
- **<big>Bool</big>** : 返回传入参数的 bool 值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Bool)]
@@ -216,7 +244,7 @@ import "github.com/duke-git/lancet/v2/condition"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#TernaryOperator)]
[[play](https://go.dev/play/p/ElllPZY0guT)]
### 5. convertor 转换器包支持一些常见的数据类型转换。
<h3 id="Convertor"> 5. convertor 转换器包支持一些常见的数据类型转换。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/convertor"
@@ -280,8 +308,15 @@ import "github.com/duke-git/lancet/v2/convertor"
[[play](https://go.dev/play/p/oZujoB5Sgg5)]
- **<big>ToInterface</big>** : 将反射值转换成对应的 interface 类型。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToInterface)]
[[play](https://go.dev/play/p/syqw0-WG7Xd)]
- **<big>Utf8ToGbk</big>** : utf8 编码转 GBK 编码。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#Utf8ToGbk)]
[[play](https://go.dev/play/p/9FlIaFLArIL)]
- **<big>GbkToUtf8</big>** : GBK 编码转 utf8 编码。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#GbkToUtf8)]
[[play](https://go.dev/play/p/OphmHCN_9u8)]
### 6. cryptor 加密包支持数据加密和解密,获取 md5hash 值。支持 base64, md5, hmac, aes, des, rsa。
<h3 id="Cryptor"> 6. cryptor 加密包支持数据加密和解密,获取 md5hash 值。支持 base64, md5, hmac, aes, des, rsa。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/cryptor"
@@ -385,7 +420,7 @@ import "github.com/duke-git/lancet/v2/cryptor"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/cryptor_zh-CN.md#RsaDecrypt)]
[[play](https://go.dev/play/p/uef0q1fz53I)]
### 7. datetime 日期时间处理包,格式化日期,比较日期。
<h3 id="Datetime"> 7. datetime 日期时间处理包,格式化日期,比较日期。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/datetime"
@@ -404,6 +439,7 @@ import "github.com/duke-git/lancet/v2/datetime"
[[play](https://go.dev/play/p/nT1heB1KUUK)]
- **<big>AddYear</big>** : 将日期加/减分年数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddYear)]
[[play](https://go.dev/play/p/MqW2ujnBx10)]
- **<big>BeginOfMinute</big>** : 返回指定时间的分钟开始时间。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#BeginOfMinute)]
[[play](https://go.dev/play/p/ieOLVJ9CiFT)]
@@ -479,16 +515,29 @@ import "github.com/duke-git/lancet/v2/datetime"
- **<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格式指定的日期字符串。
- **<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日期字符串。
- **<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)]
- **<big>IsLeapYear</big>** :验证是否是闰年。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#IsLeapYear)]
[[play](https://go.dev/play/p/xS1eS2ejGew)]
- **<big>IsLeapYear</big>** : check if param `year` is leap year or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#IsLeapYear)]
[[play](https://go.dev/play/p/xS1eS2ejGew)]
- **<big>BetweenSeconds</big>** : 返回两个时间的间隔秒数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#BetweenSeconds)]
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BetweenSeconds)]
- **<big>DayOfYear</big>** : 返回参数日期是一年中的第几天。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#DayOfYear)]
[[play](https://go.dev/play/p/0hjqhTwFNlH)]
- **<big>IsWeekend</big>** : 判断日期是否是周末。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#IsWeekend)]
[[play](https://go.dev/play/p/cupRM5aZOIY)]
### 8. datastructure 包含一些普通的数据结构实现。例如list, linklist, stack, queue, set, tree, graph.
<h3 id="Datastructure"> 8. datastructure 包含一些普通的数据结构实现。例如list, linklist, stack, queue, set, tree, graph。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import list "github.com/duke-git/lancet/v2/datastructure/list"
@@ -501,7 +550,7 @@ import heap "github.com/duke-git/lancet/v2/datastructure/heap"
import hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
```
#### Function list:
#### 函数列表:
- **<big>List</big>** : 线性表结构, 用切片实现。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/list_zh-CN.md)]
@@ -520,7 +569,7 @@ import hashmap "github.com/duke-git/lancet/v2/datastructure/hashmap"
- **<big>Hashmap</big>** : 哈希映射。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datastructure/hashmap_zh-CN.md)]
### 9. fileutil 包含文件基本操作。
<h3 id="Fileutil"> 9. fileutil 包含文件基本操作。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/fileutil"
@@ -570,6 +619,8 @@ import "github.com/duke-git/lancet/v2/fileutil"
- **<big>Zip</big>** : zip 压缩文件, 参数可以是文件或目录。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#Zip)]
[[play](https://go.dev/play/p/j-3sWBp8ik_P)]
- **<big>ZipAppendEntry</big>** : 通过将单个文件或目录追加到现有的 zip 文件。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ZipAppendEntry)]
- **<big>UnZip</big>** : zip 解压缩文件并保存在目录中。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#UnZip)]
[[play](https://go.dev/play/p/g0w34kS7B8m)]
@@ -591,8 +642,17 @@ import "github.com/duke-git/lancet/v2/fileutil"
- **<big>ReadCsvFile</big>** : 读取 csv 文件内容到切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#ReadCsvFile)]
[[play](https://go.dev/play/p/OExTkhGEd3_u)]
- **<big>WriteCsvFile</big>** : 向 csv 文件写入内容。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#WriteCsvFile)]
[[play](https://go.dev/play/p/dAXm58Q5U1o)]
- **<big>WriteBytesToFile</big>** : 将 bytes 写入文件。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#WriteBytesToFile)]
[[play](https://go.dev/play/p/s7QlDxMj3P8)]
- **<big>WriteStringToFile</big>** : 将字符串写入文件。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#WriteStringToFile)]
[[play](https://go.dev/play/p/GhLS6d8lH_g)]
### 10. formatter 格式化器包含一些数据格式化处理方法。
<h3 id="Formatter"> 10. formatter 格式化器包含一些数据格式化处理方法。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/formatter"
@@ -622,7 +682,7 @@ import "github.com/duke-git/lancet/v2/formatter"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#ParseBinaryBytes)]
[[play](https://go.dev/play/p/69v1tTT62x8)]
### 11. function 函数包控制函数执行流程,包含部分函数式编程。
<h3 id="Function"> 11. function 函数包控制函数执行流程,包含部分函数式编程。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/function"
@@ -658,7 +718,7 @@ import "github.com/duke-git/lancet/v2/function"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Watcher)]
[[play](https://go.dev/play/p/l2yrOpCLd1I)]
### 12. maputil 包括一些操作 map 的函数.
<h3 id="Maputil"> 12. maputil 包括一些操作 map 的函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/maputil"
@@ -730,13 +790,13 @@ import "github.com/duke-git/lancet/v2/maputil"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#IsDisjoint)]
[[play](https://go.dev/play/p/N9qgYg_Ho6f)]
### 13. mathutil 包实现了一些数学计算的函数。
<h3 id="Mathutil"> 13. mathutil 包实现了一些数学计算的函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/mathutil"
```
#### Function list:
#### 函数列表:
- **<big>Average</big>** :计算平均数,可能需要对结果调用 RoundToFloat 方法四舍五入。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Average)]
@@ -764,7 +824,7 @@ import "github.com/duke-git/lancet/v2/mathutil"
[[play](https://go.dev/play/p/N9qgYg_Ho6f)]
- **<big>Percent</big>** : 计算百分比,可以指定保留 n 位小数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Percent)]
[[play](https://go.dev/play/p/QQM9B13coSP)]
[[play](https://go.dev/play/p/s0NdFCtwuyd)]
- **<big>RoundToFloat</big>** : 四舍五入,保留 n 位小数,返回 float64。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RoundToFloat)]
[[play](https://go.dev/play/p/ghyb528JRJL)]
@@ -794,10 +854,24 @@ import "github.com/duke-git/lancet/v2/mathutil"
[[play](https://go.dev/play/p/Rdd8UTHZJ7u)]
- **<big>GCD</big>** : 求最大公约数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#GCD)]
[[play](https://go.dev/play/p/CiEceLSoAKB)]
- **<big>LCM</big>** : 求最小公倍数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#LCM)]
[[play](https://go.dev/play/p/EjcZxfY7G_g)]
- **<big>Cos</big>** : 计算弧度的余弦值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Cos)]
[[play](https://go.dev/play/p/Sm89LoIfvFq)]
- **<big>Sin</big>** : 计算弧度的正弦值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Sin)]
[[play](https://go.dev/play/p/TWMQlMywDsP)]
- **<big>Log</big>** : 计算以 base 为底 n 的对数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Log)]
[[play](https://go.dev/play/p/_d4bi8oyhat)]
- **<big>Sum</big>** : 求传入参数之和。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#Sum)]
[[play](https://go.dev/play/p/1To2ImAMJA7)]
### 14. netutil 网络包支持获取 ip 地址,发送 http 请求。
<h3 id="Netutil"> 14. netutil 网络包支持获取 ip 地址,发送 http 请求。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/netutil"
@@ -870,7 +944,25 @@ import "github.com/duke-git/lancet/v2/netutil"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#IsTelnetConnected)]
[[play](https://go.dev/play/p/yiLCGtQv_ZG)]
### 15. random 随机数生成器包,可以生成随机[]bytes, int, string。
<h3 id="Pointer"> 15. pointer 包支持一些指针类型的操作。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/pointer"
```
#### 函数列表:
- **<big>ExtractPointer</big>** : 返回传入 interface 的底层值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/pointer_zh-CN.md#ExtractPointer)]
[[play](https://go.dev/play/p/D7HFjeWU2ZP)]
- **<big>Of</big>** : 返回传入参数的指针值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/pointer_zh-CN.md#Of)]
[[play](https://go.dev/play/p/HFd70x4DrMj)]
- **<big>Unwrap</big>** : 返回传入指针指向的值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/pointer_zh-CN.md#Unwrap)]
[[play](https://go.dev/play/p/cgeu3g7cjWb)]
<h3 id="Random"> 16. random 随机数生成器包,可以生成随机[]bytes, int, string。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/random"
@@ -902,8 +994,11 @@ import "github.com/duke-git/lancet/v2/random"
- **<big>UUIdV4</big>** : 生成 UUID v4 字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#UUIdV4)]
[[play](https://go.dev/play/p/_Z9SFmr28ft)]
- **<big>RandUniqueIntSlice</big>** : 生成一个不重复的长度为 n 的随机 int 切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/random_zh-CN.md#RandUniqueIntSlice)]
[[play](https://go.dev/play/p/uBkRSOz73Ec)]
### 16. retry 重试执行函数直到函数运行成功或被 context cancel。
<h3 id="Retry"> 17. retry 重试执行函数直到函数运行成功或被 context cancel。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/retry"
@@ -927,7 +1022,7 @@ import "github.com/duke-git/lancet/v2/retry"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/retry_zh-CN.md#RetryTimes)]
[[play](https://go.dev/play/p/ssfVeU2SwLO)]
### 17. slice 包含操作切片的方法集合。
<h3 id="Slice"> 18. slice 包含操作切片的方法集合。</span>&nbsp; &nbsp; &nbsp; &nbsp; [回到目录](#index)
```go
import "github.com/duke-git/lancet/v2/slice"
@@ -1140,13 +1235,13 @@ import "github.com/duke-git/lancet/v2/slice"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#KeyBy)]
[[play](https://go.dev/play/p/uXod2LWD1Kg)]
### 18. Stream流该包仅验证简单的stream实现功能有限。
<h3 id="Stream"> 19. stream 流,该包仅验证简单的 stream 实现,功能有限。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/stream"
```
#### Function list:
#### 函数列表:
- **<big>Of</big>** : 创建元素为指定值的 stream。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Of)]
@@ -1199,11 +1294,12 @@ import "github.com/duke-git/lancet/v2/stream"
- **<big>Reduce</big>** : 使用关联累加函数对 stream 的元素执行 reduce 操作,并 reduce 操作结果(如果有)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Reduce)]
[[play](https://go.dev/play/p/6uzZjq_DJLU)]
- **<big>FindFirst</big>** : 返回此 stream的第一个元素如果 stream 为空,则返回零值和 false。
- **<big>FindFirst</big>** : 返回此 stream 的第一个元素,如果 stream 为空,则返回零值和 false。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#FindFirst)]
[[play](https://go.dev/play/p/9xEf0-6C1e3)]
- **<big>FindLast</big>** : 返回此 stream的最后一个元素如果 stream 为空,则返回零值和 false。
- **<big>FindLast</big>** : 返回此 stream 的最后一个元素,如果 stream 为空,则返回零值和 false。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#FindLast)]
[[play](https://go.dev/play/p/WZD2rDAW-2h)]
- **<big>Max</big>** : 根据提供的 less 函数返回 stream 的最大元素。less 函数: a > b
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Max)]
[[play](https://go.dev/play/p/fm-1KOPtGzn)]
@@ -1226,13 +1322,13 @@ import "github.com/duke-git/lancet/v2/stream"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#ToSlice)]
[[play](https://go.dev/play/p/jI6_iZZuVFE)]
### 19. structs 提供操作 struct, tag, field 的相关函数。
<h3 id="Structs"> 20. structs 提供操作 struct, tag, field 的相关函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/structs"
```
#### Function list:
#### 函数列表:
- **<big>New</big>** : `Struct`结构体的构造函数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/struct_zh-CN.md#New)]
@@ -1261,7 +1357,7 @@ import "github.com/duke-git/lancet/v2/structs"
- **<big>IsSlice</big>** : 判断属性是否是切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/field_zh-CN.md#IsSlice)]
### 20. strutil 包含字符串处理的相关函数。
<h3 id="Strutil"> 21. strutil 包含字符串处理的相关函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/strutil"
@@ -1287,6 +1383,12 @@ import "github.com/duke-git/lancet/v2/strutil"
- **<big>Capitalize</big>** : 将字符串的第一个字符转换为大写。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Capitalize)]
[[play](https://go.dev/play/p/2OAjgbmAqHZ)]
- **<big>ContainsAll</big>** : 判断字符串是否包括全部给定的子字符串切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#ContainsAll)]
[[play](https://go.dev/play/p/KECtK2Os4zq)]
- **<big>ContainsAny</big>** : 判断字符串是否包括给定的子字符串切片中任意一个子字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#ContainsAny)]
[[play](https://go.dev/play/p/dZGSSMB3LXE)]
- **<big>IsString</big>** : 判断传入参数的数据类型是否为字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#IsString)]
[[play](https://go.dev/play/p/IOgq7oF9ERm)]
@@ -1361,12 +1463,20 @@ import "github.com/duke-git/lancet/v2/strutil"
[[play](https://go.dev/play/p/qZo4lV2fomB)]
- **<big>ReplaceWithMap</big>** : 返回 string 的副本,以无序的方式被 map 替换,区分大小写。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#ReplaceWithMap)]
[[play](https://go.dev/play/p/h3t7CNj2Vvu)]
- **<big>Trim</big>** : 从字符串的开头和结尾去除空格(或其他字符)。 可选参数 characterMask 指定额外的剥离字符。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Trim)]
- **<big>SplitAndTrim</big>** : 将字符串str按字符串delimiter拆分为一个切片并对该数组的每个元素调用Trim。忽略Trim后为空的元素。
[[play](https://go.dev/play/p/Y0ilP0NRV3j)]
- **<big>SplitAndTrim</big>** : 将字符串 str 按字符串 delimiter 拆分为一个切片,并对该数组的每个元素调用 Trim。忽略 Trim 后为空的元素。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#SplitAndTrim)]
[[play](https://go.dev/play/p/ZNL6o4SkYQ7)]
- **<big>HideString</big>** : 隐藏源字符串中的一些字符。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#HideString)]
[[play](https://go.dev/play/p/pzbaIVCTreZ)]
- **<big>RemoveWhiteSpace</big>** : 删除字符串中的空格。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#RemoveWhiteSpace)]
### 21. system 包含 os, runtime, shell command 的相关函数。
<h3 id="System"> 22. system 包含 os, runtime, shell command 的相关函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/system"
@@ -1402,7 +1512,88 @@ import "github.com/duke-git/lancet/v2/system"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN#GetOsBits)]
[[play](https://go.dev/play/p/ml-_XH3gJbW)]
### 22. validator 验证器包,包含常用字符串格式验证函数。
<h3 id="Tuple"> 23. Tuple 包实现一个元组数据类型。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/tuple"
```
#### 函数列表:
- **<big>Tuple2</big>** : 2 元元组
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple2)]
- **<big>Tuple2_Unbox</big>** : 返回 2 元元组的字段值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple2_Unbox)]
- **<big>Zip2</big>** : 创建一个 Tuple2 元组切片, 其中元组的元素和传入切片元素相对应。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Zip2)]
- **<big>Unzip2</big>** : 根据传入的Tuple2切片创建一组和Tuple2元素相对应的切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Unzip2)]
- **<big>Tuple3</big>** : 3 元元组
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple3)]
- **<big>Tuple3_Unbox</big>** : 返回 3 元元组的字段值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple3_Unbox)]
- **<big>Zip3</big>** : 创建一个 Tuple3 元组切片, 其中元组的元素和传入切片元素相对应。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Zip3)]
- **<big>Unzip3</big>** : 根据传入的Tuple3切片创建一组和Tuple3元素相对应的切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Unzip3)]
- **<big>Tuple4</big>** : 4 元元组
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple4)]
- **<big>Tuple4_Unbox</big>** : 返回 4 元元组的字段值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple4_Unbox)]
- **<big>Zip4</big>** : 创建一个 Tuple4 元组切片, 其中元组的元素和传入切片元素相对应。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Zip4)]
- **<big>Unzip4</big>** : 根据传入的Tuple4切片创建一组和Tuple4元素相对应的切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Unzip4)]
- **<big>Tuple5</big>** : 5 元元组
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple5)]
- **<big>Tuple5_Unbox</big>** : 返回 5 元元组的字段值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple5_Unbox)]
- **<big>Zip5</big>** : 创建一个 Tuple5 元组切片, 其中元组的元素和传入切片元素相对应。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Zip5)]
- **<big>Unzip5</big>** : 根据传入的Tuple5切片创建一组和Tuple5元素相对应的切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Unzip5)]
- **<big>Tuple6</big>** : 6 元元组
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple6)]
- **<big>Tuple6_Unbox</big>** : 返回 6 元元组的字段值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple6_Unbox)]
- **<big>Zip6</big>** : 创建一个 Tuple6 元组切片, 其中元组的元素和传入切片元素相对应。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Zip6)]
- **<big>Unzip6</big>** : 根据传入的Tuple6切片创建一组和Tuple6元素相对应的切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Unzip6)]
- **<big>Tuple7</big>** : 7 元元组
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple7)]
- **<big>Tuple7_Unbox</big>** : 返回 7 元元组的字段值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple7_Unbox)]
- **<big>Zip7</big>** : 创建一个 Tuple7 元组切片, 其中元组的元素和传入切片元素相对应。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Zip7)]
- **<big>Unzip7</big>** : 根据传入的Tuple7切片创建一组和Tuple7元素相对应的切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Unzip7)]
- **<big>Tuple8</big>** : 8 元元组
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple8)]
- **<big>Tuple8_Unbox</big>** : 返回 8 元元组的字段值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple8_Unbox)]
- **<big>Zip8</big>** : 创建一个 Tuple8 元组切片, 其中元组的元素和传入切片元素相对应。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Zip8)]
- **<big>Unzip8</big>** : 根据传入的Tuple8切片创建一组和Tuple8元素相对应的切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Unzip8)]
- **<big>Tuple9</big>** : 9 元元组
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple9)]
- **<big>Tuple9_Unbox</big>** : 返回 9 元元组的字段值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple9_Unbox)]
- **<big>Zip9</big>** : 创建一个 Tuple9 元组切片, 其中元组的元素和传入切片元素相对应。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Zip9)]
- **<big>Unzip9</big>** : 根据传入的Tuple9切片创建一组和Tuple9元素相对应的切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Unzip9)]
- **<big>Tuple10</big>** : 10 元元组
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple10)]
- **<big>Tuple10_Unbox</big>** : 返回 10 元元组的字段值。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Tuple10_Unbox)]
- **<big>Zip10</big>** : 创建一个 Tuple10 元组切片, 其中元组的元素和传入切片元素相对应。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Zip10)]
- **<big>Unzip10</big>** : 根据传入的Tuple10切片创建一组和Tuple10元素相对应的切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/tuple_zh-CN.md#Unzip10)]
<h3 id="Validator"> 24. validator 验证器包,包含常用字符串格式验证函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/validator"
@@ -1510,7 +1701,7 @@ import "github.com/duke-git/lancet/v2/validator"
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsPrintable)]
[[play](https://go.dev/play/p/Pe1FE2gdtTP)]
### 23. xerror 包实现一些错误处理函数
<h3 id="Xerror"> 25. xerror 包实现一些错误处理函数。&nbsp; &nbsp; &nbsp; &nbsp;<a href="#index">回到目录</a></h3>
```go
import "github.com/duke-git/lancet/v2/xerror"

View File

@@ -7,6 +7,7 @@ import (
)
func TestLRUCache(t *testing.T) {
t.Parallel()
asssert := internal.NewAssert(t, "TestLRUCache")
cache := NewLRUCache[int, int](3)

View File

@@ -7,6 +7,7 @@ import (
)
func TestLinearSearch(t *testing.T) {
t.Parallel()
asssert := internal.NewAssert(t, "TestLinearSearch")
numbers := []int{3, 4, 5, 3, 2, 1}
@@ -19,6 +20,7 @@ func TestLinearSearch(t *testing.T) {
}
func TestBinarySearch(t *testing.T) {
t.Parallel()
asssert := internal.NewAssert(t, "TestBinarySearch")
sortedNumbers := []int{1, 2, 3, 4, 5, 6, 7, 8}

View File

@@ -46,6 +46,7 @@ func (c *intComparator) Compare(v1 any, v2 any) int {
}
func TestBubbleSortForStructSlice(t *testing.T) {
t.Parallel()
asssert := internal.NewAssert(t, "TestBubbleSortForStructSlice")
peoples := []people{
@@ -65,6 +66,7 @@ func TestBubbleSortForStructSlice(t *testing.T) {
}
func TestBubbleSortForIntSlice(t *testing.T) {
t.Parallel()
asssert := internal.NewAssert(t, "TestBubbleSortForIntSlice")
numbers := []int{2, 1, 5, 3, 6, 4}
@@ -75,6 +77,7 @@ func TestBubbleSortForIntSlice(t *testing.T) {
}
func TestInsertionSort(t *testing.T) {
t.Parallel()
asssert := internal.NewAssert(t, "TestInsertionSort")
peoples := []people{
@@ -94,6 +97,7 @@ func TestInsertionSort(t *testing.T) {
}
func TestSelectionSort(t *testing.T) {
t.Parallel()
asssert := internal.NewAssert(t, "TestSelectionSort")
peoples := []people{
@@ -113,6 +117,7 @@ func TestSelectionSort(t *testing.T) {
}
func TestShellSort(t *testing.T) {
t.Parallel()
asssert := internal.NewAssert(t, "TestShellSort")
peoples := []people{
@@ -132,6 +137,7 @@ func TestShellSort(t *testing.T) {
}
func TestQuickSort(t *testing.T) {
t.Parallel()
asssert := internal.NewAssert(t, "TestQuickSort")
peoples := []people{
@@ -151,6 +157,7 @@ func TestQuickSort(t *testing.T) {
}
func TestHeapSort(t *testing.T) {
t.Parallel()
asssert := internal.NewAssert(t, "TestHeapSort")
peoples := []people{
@@ -170,6 +177,7 @@ func TestHeapSort(t *testing.T) {
}
func TestMergeSort(t *testing.T) {
t.Parallel()
asssert := internal.NewAssert(t, "TestMergeSort")
peoples := []people{
@@ -189,6 +197,7 @@ func TestMergeSort(t *testing.T) {
}
func TestCountSort(t *testing.T) {
t.Parallel()
asssert := internal.NewAssert(t, "TestCountSort")
peoples := []people{

View File

@@ -8,6 +8,7 @@ import (
)
func TestEqual(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestEqual")
assert.Equal(true, Equal(1, 1))
@@ -60,6 +61,7 @@ func TestEqual(t *testing.T) {
}
func TestEqualValue(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestEqualValue")
assert.Equal(true, EqualValue(1, 1))
@@ -70,6 +72,7 @@ func TestEqualValue(t *testing.T) {
}
func TestLessThan(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLessThan")
assert.Equal(true, LessThan(1, 2))
@@ -85,6 +88,7 @@ func TestLessThan(t *testing.T) {
}
func TestGreaterThan(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestGreaterThan")
assert.Equal(true, GreaterThan(2, 1))
@@ -101,6 +105,7 @@ func TestGreaterThan(t *testing.T) {
}
func TestLessOrEqual(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLessOrEqual")
assert.Equal(true, LessOrEqual(1, 2))
@@ -117,6 +122,7 @@ func TestLessOrEqual(t *testing.T) {
}
func TestGreaterOrEqual(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestGreaterThan")
assert.Equal(true, GreaterOrEqual(2, 1))

View File

@@ -9,6 +9,7 @@ import (
)
func TestGenerate(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestGenerate")
ctx, cancel := context.WithCancel(context.Background())
@@ -23,6 +24,7 @@ func TestGenerate(t *testing.T) {
}
func TestRepeat(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestRepeat")
ctx, cancel := context.WithCancel(context.Background())
@@ -39,6 +41,7 @@ func TestRepeat(t *testing.T) {
}
func TestRepeatFn(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestRepeatFn")
ctx, cancel := context.WithCancel(context.Background())
@@ -57,6 +60,7 @@ func TestRepeatFn(t *testing.T) {
}
func TestTake(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestTake")
ctx, cancel := context.WithCancel(context.Background())
@@ -79,6 +83,7 @@ func TestTake(t *testing.T) {
}
func TestFanIn(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestFanIn")
ctx, cancel := context.WithCancel(context.Background())
@@ -101,6 +106,7 @@ func TestFanIn(t *testing.T) {
}
func TestOr(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestOr")
sig := func(after time.Duration) <-chan any {
@@ -127,6 +133,7 @@ func TestOr(t *testing.T) {
}
func TestOrDone(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestOrDone")
ctx, cancel := context.WithCancel(context.Background())
@@ -141,6 +148,7 @@ func TestOrDone(t *testing.T) {
}
func TestTee(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestTee")
ctx, cancel := context.WithCancel(context.Background())
@@ -159,6 +167,7 @@ func TestTee(t *testing.T) {
}
func TestBridge(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBridge")
ctx, cancel := context.WithCancel(context.Background())

View File

@@ -11,6 +11,8 @@ import (
type TestStruct struct{}
func TestBool(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBool")
// bool
@@ -63,6 +65,8 @@ func TestBool(t *testing.T) {
}
func TestAnd(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestAnd")
assert.Equal(false, And(0, 1))
assert.Equal(false, And(0, ""))
@@ -71,6 +75,8 @@ func TestAnd(t *testing.T) {
}
func TestOr(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestOr")
assert.Equal(false, Or(0, ""))
assert.Equal(true, Or(0, 1))
@@ -79,6 +85,8 @@ func TestOr(t *testing.T) {
}
func TestXor(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestOr")
assert.Equal(false, Xor(0, 0))
assert.Equal(true, Xor(0, 1))
@@ -87,6 +95,8 @@ func TestXor(t *testing.T) {
}
func TestNor(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestNor")
assert.Equal(true, Nor(0, 0))
assert.Equal(false, Nor(0, 1))
@@ -95,6 +105,8 @@ func TestNor(t *testing.T) {
}
func TestXnor(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestXnor")
assert.Equal(true, Xnor(0, 0))
assert.Equal(false, Xnor(0, 1))
@@ -103,6 +115,8 @@ func TestXnor(t *testing.T) {
}
func TestNand(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestNand")
assert.Equal(true, Nand(0, 0))
assert.Equal(true, Nand(0, 1))
@@ -111,7 +125,10 @@ func TestNand(t *testing.T) {
}
func TestTernaryOperator(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TernaryOperator")
trueValue := "1"
falseValue := "0"

View File

@@ -11,12 +11,15 @@ import (
"encoding/json"
"errors"
"fmt"
"io"
"math"
"reflect"
"strconv"
"strings"
"github.com/duke-git/lancet/v2/structs"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"
)
// ToBool convert string to boolean.
@@ -349,7 +352,7 @@ func CopyProperties[T, U any](dst T, src U) error {
}
// ToInterface converts reflect value to its interface type.
// Play: todo
// Play: https://go.dev/play/p/syqw0-WG7Xd
func ToInterface(v reflect.Value) (value interface{}, ok bool) {
if v.IsValid() && v.CanInterface() {
return v.Interface(), true
@@ -375,3 +378,19 @@ func ToInterface(v reflect.Value) (value interface{}, ok bool) {
return nil, false
}
}
// Utf8ToGbk convert utf8 encoding data to GBK encoding data.
// Play: https://go.dev/play/p/9FlIaFLArIL
func Utf8ToGbk(bs []byte) ([]byte, error) {
r := transform.NewReader(bytes.NewReader(bs), simplifiedchinese.GBK.NewEncoder())
b, err := io.ReadAll(r)
return b, err
}
// GbkToUtf8 convert GBK encoding data to utf8 encoding data.
// Play: https://go.dev/play/p/OphmHCN_9u8
func GbkToUtf8(bs []byte) ([]byte, error) {
r := transform.NewReader(bytes.NewReader(bs), simplifiedchinese.GBK.NewDecoder())
b, err := io.ReadAll(r)
return b, err
}

View File

@@ -4,6 +4,9 @@ import (
"fmt"
"reflect"
"strconv"
"unicode/utf8"
"github.com/duke-git/lancet/v2/validator"
)
func ExampleToBool() {
@@ -364,3 +367,27 @@ func ExampleToInterface() {
// abc
// true
}
func ExampleUtf8ToGbk() {
utf8Data := []byte("hello")
gbkData, _ := Utf8ToGbk(utf8Data)
fmt.Println(utf8.Valid(utf8Data))
fmt.Println(validator.IsGBK(gbkData))
// Output:
// true
// true
}
func ExampleGbkToUtf8() {
gbkData, _ := Utf8ToGbk([]byte("hello"))
utf8Data, _ := GbkToUtf8(gbkData)
fmt.Println(utf8.Valid(utf8Data))
fmt.Println(string(utf8Data))
// Output:
// true
// hello
}

View File

@@ -5,12 +5,16 @@ import (
"reflect"
"strconv"
"testing"
"unicode/utf8"
"github.com/duke-git/lancet/v2/internal"
"github.com/duke-git/lancet/v2/slice"
"github.com/duke-git/lancet/v2/validator"
)
func TestToChar(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToChar")
cases := []string{"", "abc", "1 2#3"}
@@ -25,6 +29,8 @@ func TestToChar(t *testing.T) {
}
func TestToChannel(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToChannel")
ch := ToChannel([]int{1, 2, 3})
@@ -37,6 +43,8 @@ func TestToChannel(t *testing.T) {
}
func TestToBool(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToBool")
cases := []string{"1", "true", "True", "false", "False", "0", "123", "0.0", "abc"}
@@ -49,6 +57,8 @@ func TestToBool(t *testing.T) {
}
func TestToBytes(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToBytes")
cases := []any{
@@ -75,6 +85,8 @@ func TestToBytes(t *testing.T) {
}
func TestToInt(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToInt")
cases := []any{"123", "-123", 123,
@@ -91,6 +103,8 @@ func TestToInt(t *testing.T) {
}
func TestToFloat(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToFloat")
cases := []any{
@@ -109,6 +123,8 @@ func TestToFloat(t *testing.T) {
}
func TestToString(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToString")
aMap := make(map[string]int)
@@ -144,6 +160,8 @@ func TestToString(t *testing.T) {
}
}
func TestToJson(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToJson")
var aMap = map[string]int{"a": 1, "b": 2, "c": 3}
@@ -159,6 +177,8 @@ func TestToJson(t *testing.T) {
}
func TestToMap(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToMap")
type Message struct {
@@ -178,6 +198,8 @@ func TestToMap(t *testing.T) {
}
func TestStructToMap(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestStructToMap")
t.Run("StructToMap", func(_ *testing.T) {
@@ -213,6 +235,8 @@ func TestStructToMap(t *testing.T) {
}
func TestMapToSlice(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMapToSlice")
aMap := map[string]int{"a": 1, "b": 2, "c": 3}
@@ -227,6 +251,8 @@ func TestMapToSlice(t *testing.T) {
}
func TestColorHexToRGB(t *testing.T) {
t.Parallel()
colorHex := "#003366"
r, g, b := ColorHexToRGB(colorHex)
colorRGB := fmt.Sprintf("%d,%d,%d", r, g, b)
@@ -237,6 +263,8 @@ func TestColorHexToRGB(t *testing.T) {
}
func TestColorRGBToHex(t *testing.T) {
t.Parallel()
r := 0
g := 51
b := 102
@@ -248,6 +276,8 @@ func TestColorRGBToHex(t *testing.T) {
}
func TestToPointer(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToPointer")
result := ToPointer(123)
@@ -255,6 +285,8 @@ func TestToPointer(t *testing.T) {
}
func TestEncodeByte(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestEncodeByte")
byteData, _ := EncodeByte("abc")
@@ -264,6 +296,8 @@ func TestEncodeByte(t *testing.T) {
}
func TestDecodeByte(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDecodeByte")
var obj string
@@ -274,6 +308,8 @@ func TestDecodeByte(t *testing.T) {
}
func TestDeepClone(t *testing.T) {
t.Parallel()
// assert := internal.NewAssert(t, "TestDeepClone")
type Struct struct {
@@ -317,6 +353,8 @@ func TestDeepClone(t *testing.T) {
}
func TestCopyProperties(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestCopyProperties")
type Disk struct {
@@ -369,6 +407,8 @@ func TestCopyProperties(t *testing.T) {
}
func TestToInterface(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToInterface")
cases := []reflect.Value{
@@ -396,3 +436,27 @@ func TestToInterface(t *testing.T) {
assert.EqualValues(nil, nilVal)
assert.Equal(false, ok)
}
func TestUtf8ToGbk(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestUtf8ToGbk")
utf8Data := []byte("hello")
gbkData, err := Utf8ToGbk(utf8Data)
assert.Equal(true, utf8.Valid(utf8Data))
assert.Equal(true, validator.IsGBK(gbkData))
assert.IsNil(err)
}
func TestGbkToUtf8(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestGbkToUtf8")
gbkData, err := Utf8ToGbk([]byte("hello"))
utf8Data, err := GbkToUtf8(gbkData)
assert.IsNil(err)
assert.Equal(true, utf8.Valid(utf8Data))
assert.Equal("hello", string(utf8Data))
}

View File

@@ -40,6 +40,14 @@ func Md5String(s string) string {
return hex.EncodeToString(h.Sum(nil))
}
// Md5String return the md5 string of byte slice.
// Play: todo
func Md5Byte(data []byte) string {
h := md5.New()
h.Write(data)
return hex.EncodeToString(h.Sum(nil))
}
// Md5File return the md5 value of file.
func Md5File(filename string) (string, error) {
if fileInfo, err := os.Stat(filename); err != nil {

View File

@@ -7,21 +7,37 @@ import (
)
func TestBase64StdEncode(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBase64StdEncode")
assert.Equal("aGVsbG8gd29ybGQ=", Base64StdEncode("hello world"))
}
func TestBase64StdDecode(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBase64StdDecode")
assert.Equal("hello world", Base64StdDecode("aGVsbG8gd29ybGQ="))
}
func TestMd5String(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMd5String")
assert.Equal("5d41402abc4b2a76b9719d911017c592", Md5String("hello"))
}
func TestMd5Byte(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMd5Byte")
data := []byte{'a'}
assert.Equal("0cc175b9c0f1b6a831c399e269772661", Md5Byte(data))
}
func TestMd5File(t *testing.T) {
t.Parallel()
fileMd5, err := Md5File("./basic.go")
assert := internal.NewAssert(t, "TestMd5File")
assert.IsNotNil(fileMd5)
@@ -29,11 +45,15 @@ func TestMd5File(t *testing.T) {
}
func TestHmacMd5(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestHmacMd5")
assert.Equal("5f4c9faaff0a1ad3007d9ddc06abe36d", HmacMd5("hello world", "12345"))
}
func TestHmacSha1(t *testing.T) {
t.Parallel()
s := "hello world"
key := "12345"
hmacSha1 := HmacSha1(s, key)
@@ -44,6 +64,8 @@ func TestHmacSha1(t *testing.T) {
}
func TestHmacSha256(t *testing.T) {
t.Parallel()
s := "hello world"
key := "12345"
hmacSha256 := HmacSha256(s, key)
@@ -54,6 +76,8 @@ func TestHmacSha256(t *testing.T) {
}
func TestHmacSha512(t *testing.T) {
t.Parallel()
s := "hello world"
key := "12345"
hmacSha512 := HmacSha512(s, key)
@@ -64,6 +88,8 @@ func TestHmacSha512(t *testing.T) {
}
func TestSha1(t *testing.T) {
t.Parallel()
s := "hello world"
sha1 := Sha1(s)
expected := "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed"
@@ -73,6 +99,8 @@ func TestSha1(t *testing.T) {
}
func TestSha256(t *testing.T) {
t.Parallel()
s := "hello world"
sha256 := Sha256(s)
expected := "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
@@ -82,6 +110,8 @@ func TestSha256(t *testing.T) {
}
func TestSha512(t *testing.T) {
t.Parallel()
s := "hello world"
sha512 := Sha512(s)
expected := "309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f"

View File

@@ -366,21 +366,22 @@ func ExampleHmacSha512() {
}
func ExampleMd5String() {
str := "hello"
md5Str := Md5String(str)
md5Str := Md5String("hello")
fmt.Println(md5Str)
// Output:
// 5d41402abc4b2a76b9719d911017c592
}
func ExampleMd5Byte() {
md5Str := Md5Byte([]byte{'a'})
fmt.Println(md5Str)
// Output:
// 0cc175b9c0f1b6a831c399e269772661
}
func ExampleSha1() {
str := "hello"
result := Sha1(str)
result := Sha1("hello")
fmt.Println(result)
// Output:
@@ -388,10 +389,7 @@ func ExampleSha1() {
}
func ExampleSha256() {
str := "hello"
result := Sha256(str)
result := Sha256("hello")
fmt.Println(result)
// Output:
@@ -399,10 +397,7 @@ func ExampleSha256() {
}
func ExampleSha512() {
str := "hello"
result := Sha512(str)
result := Sha512("hello")
fmt.Println(result)
// Output:

View File

@@ -7,6 +7,8 @@ import (
)
func TestAesEcbEncrypt(t *testing.T) {
t.Parallel()
data := "hello world"
key := "abcdefghijklmnop"
@@ -18,6 +20,8 @@ func TestAesEcbEncrypt(t *testing.T) {
}
func TestAesCbcEncrypt(t *testing.T) {
t.Parallel()
data := "hello world"
key := "abcdefghijklmnop"
@@ -29,6 +33,8 @@ func TestAesCbcEncrypt(t *testing.T) {
}
func TestAesCtrCrypt(t *testing.T) {
t.Parallel()
data := "hello world"
key := "abcdefghijklmnop"
@@ -40,6 +46,8 @@ func TestAesCtrCrypt(t *testing.T) {
}
func TestAesCfbEncrypt(t *testing.T) {
t.Parallel()
data := "hello world"
key := "abcdefghijklmnop"
@@ -51,6 +59,8 @@ func TestAesCfbEncrypt(t *testing.T) {
}
func TestAesOfbEncrypt(t *testing.T) {
t.Parallel()
data := "hello world"
key := "abcdefghijklmnop"
@@ -62,6 +72,8 @@ func TestAesOfbEncrypt(t *testing.T) {
}
func TestDesEcbEncrypt(t *testing.T) {
t.Parallel()
data := "hello world"
key := "abcdefgh"
@@ -73,6 +85,8 @@ func TestDesEcbEncrypt(t *testing.T) {
}
func TestDesCbcEncrypt(t *testing.T) {
t.Parallel()
data := "hello world"
key := "abcdefgh"
@@ -84,6 +98,8 @@ func TestDesCbcEncrypt(t *testing.T) {
}
func TestDesCtrCrypt(t *testing.T) {
t.Parallel()
data := "hello world"
key := "abcdefgh"
@@ -95,6 +111,8 @@ func TestDesCtrCrypt(t *testing.T) {
}
func TestDesCfbEncrypt(t *testing.T) {
t.Parallel()
data := "hello world"
key := "abcdefgh"
@@ -106,6 +124,8 @@ func TestDesCfbEncrypt(t *testing.T) {
}
func TestDesOfbEncrypt(t *testing.T) {
t.Parallel()
data := "hello world"
key := "abcdefgh"
@@ -117,6 +137,8 @@ func TestDesOfbEncrypt(t *testing.T) {
}
func TestRsaEncrypt(t *testing.T) {
t.Parallel()
err := GenerateRsaKey(4096, "rsa_private.pem", "rsa_public.pem")
if err != nil {
t.FailNow()

View File

@@ -1,7 +1,7 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure implements some data structure. eg. list, linklist, stack, queue, tree, graph.
// Package datastructure implements some data structure. hashmap structure.
package datastructure
import (

View File

@@ -32,6 +32,8 @@ func TestHashMap_Resize(t *testing.T) {
}
func TestHashMap_Delete(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestHashMap_Delete")
hm := NewHashMap()
@@ -44,6 +46,8 @@ func TestHashMap_Delete(t *testing.T) {
}
func TestHashMap_Contains(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestHashMap_Contains")
hm := NewHashMap()
@@ -54,6 +58,8 @@ func TestHashMap_Contains(t *testing.T) {
}
func TestHashMap_KeysValues(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestHashMap_KeysValues")
hm := NewHashMap()

View File

@@ -1,7 +1,7 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure implements some data structure. eg. list, linklist, stack, queue, tree, graph.
// Package datastructure implements some data structure. MaxHeap is a binary max heap.
package datastructure
import (

View File

@@ -21,6 +21,8 @@ func (c *intComparator) Compare(v1, v2 any) int {
}
func TestMaxHeap_BuildMaxHeap(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMaxHeap_BuildMaxHeap")
values := []int{6, 5, 2, 4, 7, 10, 12, 1, 3, 8, 9, 11}
@@ -33,6 +35,8 @@ func TestMaxHeap_BuildMaxHeap(t *testing.T) {
}
func TestMaxHeap_Push(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMaxHeap_Push")
heap := NewMaxHeap[int](&intComparator{})
@@ -51,6 +55,8 @@ func TestMaxHeap_Push(t *testing.T) {
}
func TestMaxHeap_Pop(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMaxHeap_Pop")
heap := NewMaxHeap[int](&intComparator{})
@@ -70,6 +76,8 @@ func TestMaxHeap_Pop(t *testing.T) {
}
func TestMaxHeap_Peek(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMaxHeap_Peek")
heap := NewMaxHeap[int](&intComparator{})

View File

@@ -1,3 +1,7 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure contains some data structure. Link structure contains SinglyLink and DoublyLink.
package datastructure
import (

View File

@@ -7,6 +7,8 @@ import (
)
func TestDoublyLink_InsertAtFirst(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDoublyLink_InsertAtFirst")
link := NewDoublyLink[int]()
@@ -22,6 +24,8 @@ func TestDoublyLink_InsertAtFirst(t *testing.T) {
}
func TestDoublyLink_InsertAtTail(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDoublyLink_InsertAtTail")
link := NewDoublyLink[int]()
@@ -37,12 +41,12 @@ func TestDoublyLink_InsertAtTail(t *testing.T) {
}
func TestDoublyLink_InsertAt(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDoublyLink_InsertAt")
link := NewDoublyLink[int]()
link.InsertAt(1, 1) //do nothing
link.InsertAt(0, 1)
link.InsertAt(1, 2)
link.InsertAt(2, 4)
@@ -55,6 +59,8 @@ func TestDoublyLink_InsertAt(t *testing.T) {
}
func TestDoublyLink_DeleteAtHead(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAtHead")
link := NewDoublyLink[int]()
@@ -74,6 +80,8 @@ func TestDoublyLink_DeleteAtHead(t *testing.T) {
}
func TestDoublyLink_DeleteAtTail(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAtTail")
link := NewDoublyLink[int]()
@@ -93,6 +101,8 @@ func TestDoublyLink_DeleteAtTail(t *testing.T) {
}
func TestDoublyLink_DeleteAt(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDoublyLink_DeleteAt")
link := NewDoublyLink[int]()
@@ -116,6 +126,8 @@ func TestDoublyLink_DeleteAt(t *testing.T) {
}
func TestDoublyLink_Reverse(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDoublyLink_Reverse")
link := NewDoublyLink[int]()
@@ -130,6 +142,8 @@ func TestDoublyLink_Reverse(t *testing.T) {
}
func TestDoublyLink_GetMiddleNode(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDoublyLink_GetMiddleNode")
link := NewDoublyLink[int]()
@@ -149,10 +163,11 @@ func TestDoublyLink_GetMiddleNode(t *testing.T) {
}
func TestDoublyLink_Clear(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDoublyLink_Clear")
link := NewDoublyLink[int]()
assert.Equal(true, link.IsEmpty())
assert.Equal(0, link.Size())

View File

@@ -1,3 +1,7 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure contains some data structure. Link structure contains SinglyLink and DoublyLink.
package datastructure
import (

View File

@@ -7,6 +7,8 @@ import (
)
func TestSinglyLink_InsertAtFirst(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSinglyLink_InsertAtFirst")
link := NewSinglyLink[int]()
@@ -22,6 +24,8 @@ func TestSinglyLink_InsertAtFirst(t *testing.T) {
}
func TestSinglyLink_InsertAtTail(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSinglyLink_InsertAtTail")
link := NewSinglyLink[int]()
@@ -37,6 +41,8 @@ func TestSinglyLink_InsertAtTail(t *testing.T) {
}
func TestSinglyLink_InsertAt(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSinglyLink_InsertAt")
link := NewSinglyLink[int]()
@@ -57,6 +63,8 @@ func TestSinglyLink_InsertAt(t *testing.T) {
}
func TestSinglyLink_DeleteAtHead(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAtHead")
link := NewSinglyLink[int]()
@@ -78,10 +86,11 @@ func TestSinglyLink_DeleteAtHead(t *testing.T) {
}
func TestSinglyLink_DeleteAtTail(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAtTail")
link := NewSinglyLink[int]()
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
@@ -96,10 +105,11 @@ func TestSinglyLink_DeleteAtTail(t *testing.T) {
}
func TestSinglyLink_DeleteValue(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSinglyLink_DeleteValue")
link := NewSinglyLink[int]()
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(2)
@@ -114,10 +124,11 @@ func TestSinglyLink_DeleteValue(t *testing.T) {
}
func TestSinglyLink_DeleteAt(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSinglyLink_DeleteAt")
link := NewSinglyLink[int]()
link.InsertAtTail(1)
link.InsertAtTail(2)
link.InsertAtTail(3)
@@ -136,6 +147,8 @@ func TestSinglyLink_DeleteAt(t *testing.T) {
}
func TestSinglyLink_Reverse(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSinglyLink_Reverse")
link := NewSinglyLink[int]()
@@ -149,6 +162,8 @@ func TestSinglyLink_Reverse(t *testing.T) {
}
func TestSinglyLink_GetMiddleNode(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSinglyLink_GetMiddleNode")
link := NewSinglyLink[int]()
@@ -163,6 +178,7 @@ func TestSinglyLink_GetMiddleNode(t *testing.T) {
link.InsertAtTail(5)
link.InsertAtTail(6)
link.InsertAtTail(7)
middle2 := link.GetMiddleNode()
assert.Equal(4, middle2.Value)
}

View File

@@ -1,7 +1,7 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure implements some data structure. eg. list, linklist, stack, queue, tree, graph.
// Package datastructure contains some data structure. list is a linear table, implemented with slice.
package datastructure
import (

View File

@@ -7,6 +7,8 @@ import (
)
func TestListData(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestListData")
list := NewList([]int{1, 2, 3})
@@ -14,6 +16,8 @@ func TestListData(t *testing.T) {
}
func TestValueOf(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestValueOf")
list := NewList([]int{1, 2, 3})
@@ -26,6 +30,8 @@ func TestValueOf(t *testing.T) {
}
func TestIndexOf(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIndexOf")
list := NewList([]int{1, 2, 3})
@@ -37,6 +43,8 @@ func TestIndexOf(t *testing.T) {
}
func TestIndexOfFunc(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIndexOf")
list := NewList([]int{1, 2, 3})
@@ -48,6 +56,8 @@ func TestIndexOfFunc(t *testing.T) {
}
func TestLastIndexOf(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIndexOf")
list := NewList([]int{1, 2, 3, 3, 3, 3, 4, 5, 6, 9})
@@ -65,6 +75,8 @@ func TestLastIndexOf(t *testing.T) {
}
func TestLastIndexOfFunc(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIndexOf")
list := NewList([]int{1, 2, 3, 3, 3, 3, 4, 5, 6, 9})
@@ -82,6 +94,8 @@ func TestLastIndexOfFunc(t *testing.T) {
}
func TestContain(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestContain")
list := NewList([]int{1, 2, 3})
@@ -90,6 +104,8 @@ func TestContain(t *testing.T) {
}
func TestPush(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestPush")
list := NewList([]int{1, 2, 3})
@@ -99,6 +115,8 @@ func TestPush(t *testing.T) {
}
func TestInsertAtFirst(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestInsertAtFirst")
list := NewList([]int{1, 2, 3})
@@ -108,6 +126,8 @@ func TestInsertAtFirst(t *testing.T) {
}
func TestInsertAtLast(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestInsertAtLast")
list := NewList([]int{1, 2, 3})
@@ -117,6 +137,8 @@ func TestInsertAtLast(t *testing.T) {
}
func TestInsertAt(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestInsertAt")
list := NewList([]int{1, 2, 3})
@@ -135,6 +157,8 @@ func TestInsertAt(t *testing.T) {
}
func TestPopFirst(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestPopFirst")
list := NewList([]int{1, 2, 3})
@@ -150,6 +174,8 @@ func TestPopFirst(t *testing.T) {
}
func TestPopLast(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestPopLast")
list := NewList([]int{1, 2, 3})
@@ -165,6 +191,8 @@ func TestPopLast(t *testing.T) {
}
func TestDeleteAt(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDeleteAt")
list := NewList([]int{1, 2, 3, 4})
@@ -183,6 +211,8 @@ func TestDeleteAt(t *testing.T) {
}
func TestUpdateAt(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestUpdateAt")
list := NewList([]int{1, 2, 3, 4})
@@ -201,6 +231,8 @@ func TestUpdateAt(t *testing.T) {
}
func TestEqual(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestEqual")
list1 := NewList([]int{1, 2, 3, 4})
@@ -212,6 +244,8 @@ func TestEqual(t *testing.T) {
}
func TestIsEmpty(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIsEmpty")
list1 := NewList([]int{1, 2, 3, 4})
@@ -222,6 +256,8 @@ func TestIsEmpty(t *testing.T) {
}
func TestIsClear(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIsClear")
list1 := NewList([]int{1, 2, 3, 4})
@@ -232,6 +268,8 @@ func TestIsClear(t *testing.T) {
}
func TestClone(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestClone")
list1 := NewList([]int{1, 2, 3, 4})
@@ -241,6 +279,8 @@ func TestClone(t *testing.T) {
}
func TestMerge(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMerge")
list1 := NewList([]int{1, 2, 3, 4})
@@ -252,6 +292,8 @@ func TestMerge(t *testing.T) {
}
func TestSize(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSize")
list := NewList([]int{1, 2, 3, 4})
@@ -262,6 +304,8 @@ func TestSize(t *testing.T) {
}
func TestCap(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestCap")
data := make([]int, 0, 100)
@@ -274,6 +318,8 @@ func TestCap(t *testing.T) {
}
func TestSwap(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSwap")
list := NewList([]int{1, 2, 3, 4})
@@ -285,6 +331,8 @@ func TestSwap(t *testing.T) {
}
func TestReverse(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestReverse")
list := NewList([]int{1, 2, 3, 4})
@@ -296,6 +344,8 @@ func TestReverse(t *testing.T) {
}
func TestUnique(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestUnique")
list := NewList([]int{1, 2, 2, 3, 4})
@@ -307,6 +357,8 @@ func TestUnique(t *testing.T) {
}
func TestUnion(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestUnion")
list1 := NewList([]int{1, 2, 3, 4})
@@ -318,6 +370,8 @@ func TestUnion(t *testing.T) {
}
func TestIntersection(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIntersection")
list1 := NewList([]int{1, 2, 3, 4})
@@ -329,6 +383,8 @@ func TestIntersection(t *testing.T) {
}
func TestDifference(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDifference")
list1 := NewList([]int{1, 2, 3})
@@ -340,6 +396,8 @@ func TestDifference(t *testing.T) {
}
func TestSymmetricDifference(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSymmetricDifference")
list1 := NewList([]int{1, 2, 3})
@@ -351,6 +409,8 @@ func TestSymmetricDifference(t *testing.T) {
}
func TestSubSlice(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSubSlice")
list := NewList([]int{1, 2, 3, 4, 5, 8})
@@ -367,6 +427,8 @@ func BenchmarkSubSlice(b *testing.B) {
}
func TestDeleteIf(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDeleteIf")
list := NewList([]int{1, 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 1, 1, 1, 1})
@@ -381,10 +443,11 @@ func TestDeleteIf(t *testing.T) {
}
func TestForEach(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestForEach")
list := NewList([]int{1, 2, 3, 4})
rs := make([]int, 0)
list.ForEach(func(i int) {
rs = append(rs, i)
@@ -394,6 +457,8 @@ func TestForEach(t *testing.T) {
}
func TestRetainAll(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestRetainAll")
list := NewList([]int{1, 2, 3, 4})
@@ -414,6 +479,8 @@ func TestRetainAll(t *testing.T) {
}
func TestDeleteAll(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDeleteAll")
list := NewList([]int{1, 2, 3, 4})
@@ -433,10 +500,11 @@ func TestDeleteAll(t *testing.T) {
}
func TestIterator(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIterator")
list := NewList([]int{1, 2, 3, 4})
iterator := list.Iterator()
rs := make([]int, 0)
@@ -449,14 +517,15 @@ func TestIterator(t *testing.T) {
}
func TestListToMap(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "ListToMap")
list := NewList([]int{1, 2, 3, 4})
result := ListToMap(list, func(n int) (int, bool) {
return n, n > 1
})
expected := map[int]bool{1: false, 2: true, 3: true, 4: true}
expected := map[int]bool{1: false, 2: true, 3: true, 4: true}
assert.Equal(expected, result)
}

View File

@@ -1,7 +1,7 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure implements some data structure. eg. list, linklist, stack, queue, tree, graph.
// Package datastructure implements some data structure.
package datastructure
// LinkNode is a linkedlist node, which have a Value and Pre points to previous node, Next points to a next node of the link.

View File

@@ -1,3 +1,8 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure contains some data structure.
// Queue structure contains ArrayQueue, LinkedQueue, CircularQueue, and PriorityQueue.
package datastructure
import (

View File

@@ -7,6 +7,8 @@ import (
)
func TestArrayQueue_Enqueue(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestArrayQueue_Enqueue")
queue := NewArrayQueue[int](5)
@@ -14,15 +16,16 @@ func TestArrayQueue_Enqueue(t *testing.T) {
queue.Enqueue(2)
queue.Enqueue(3)
expected := []int{1, 2, 3}
data := queue.Data()
size := queue.Size()
assert.Equal(expected, data)
assert.Equal([]int{1, 2, 3}, data)
assert.Equal(3, size)
}
func TestArrayQueue_Dequeue(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestArrayQueue_Dequeue")
queue := NewArrayQueue[int](4)
@@ -38,6 +41,8 @@ func TestArrayQueue_Dequeue(t *testing.T) {
}
func TestArrayQueue_Front(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestArrayQueue_Front")
queue := NewArrayQueue[int](4)
@@ -52,6 +57,8 @@ func TestArrayQueue_Front(t *testing.T) {
}
func TestArrayQueue_Back(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestArrayQueue_Back")
queue := NewArrayQueue[int](4)
@@ -66,6 +73,8 @@ func TestArrayQueue_Back(t *testing.T) {
}
func TestArrayQueue_Contain(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestArrayQueue_Contain")
queue := NewArrayQueue[int](4)
@@ -78,6 +87,8 @@ func TestArrayQueue_Contain(t *testing.T) {
}
func TestArrayQueue_Clear(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestArrayQueue_Clear")
queue := NewArrayQueue[int](4)
@@ -95,6 +106,8 @@ func TestArrayQueue_Clear(t *testing.T) {
}
func TestArrayQueue_IsFull(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestArrayQueue_IsFull")
queue := NewArrayQueue[int](3)

View File

@@ -1,3 +1,8 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure contains some data structure.
// Queue structure contains ArrayQueue, LinkedQueue, CircularQueue, and PriorityQueue.
package datastructure
import (

View File

@@ -7,6 +7,8 @@ import (
)
func TestCircularQueue_Enqueue(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestCircularQueue_Enqueue")
queue := NewCircularQueue[int](6)
@@ -34,6 +36,8 @@ func TestCircularQueue_Enqueue(t *testing.T) {
}
func TestCircularQueue_Dequeue(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestCircularQueue_DeQueue")
queue := NewCircularQueue[int](4)
@@ -60,6 +64,8 @@ func TestCircularQueue_Dequeue(t *testing.T) {
}
func TestCircularQueue_Front(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestCircularQueue_Front")
queue := NewCircularQueue[int](6)
@@ -80,6 +86,8 @@ func TestCircularQueue_Front(t *testing.T) {
}
func TestCircularQueue_Back(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestCircularQueue_Back")
queue := NewCircularQueue[int](3)
@@ -103,6 +111,8 @@ func TestCircularQueue_Back(t *testing.T) {
}
func TestCircularQueue_Contain(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestCircularQueue_Contain")
queue := NewCircularQueue[int](2)
@@ -114,6 +124,8 @@ func TestCircularQueue_Contain(t *testing.T) {
}
func TestCircularQueue_Clear(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestCircularQueue_Clear")
queue := NewCircularQueue[int](3)
@@ -132,6 +144,8 @@ func TestCircularQueue_Clear(t *testing.T) {
}
func TestCircularQueue_Data(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestCircularQueue_Data")
queue := NewCircularQueue[int](3)

View File

@@ -1,3 +1,8 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure contains some data structure.
// Queue structure contains ArrayQueue, LinkedQueue, CircularQueue, and PriorityQueue.
package datastructure
import (

View File

@@ -7,6 +7,8 @@ import (
)
func TestLinkedQueue_Enqueue(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLinkedQueue_Enqueue")
queue := NewLinkedQueue[int]()
@@ -19,6 +21,8 @@ func TestLinkedQueue_Enqueue(t *testing.T) {
}
func TestLinkedQueue_Dequeue(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLinkedQueue_DeQueue")
queue := NewLinkedQueue[int]()
@@ -35,6 +39,8 @@ func TestLinkedQueue_Dequeue(t *testing.T) {
}
func TestLinkedQueue_Front(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLinkedQueue_Front")
queue := NewLinkedQueue[int]()
@@ -51,6 +57,8 @@ func TestLinkedQueue_Front(t *testing.T) {
}
func TestLinkedQueue_Back(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLinkedQueue_Back")
queue := NewLinkedQueue[int]()
@@ -67,6 +75,8 @@ func TestLinkedQueue_Back(t *testing.T) {
}
func TestLinkedQueue_Clear(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLinkedQueue_Back")
queue := NewLinkedQueue[int]()
@@ -82,10 +92,11 @@ func TestLinkedQueue_Clear(t *testing.T) {
}
func TestLinkedQueue_Contain(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLinkedQueue_Contain")
queue := NewLinkedQueue[int]()
queue.Enqueue(1)
queue.Enqueue(2)
queue.Enqueue(3)

View File

@@ -1,3 +1,8 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure contains some data structure.
// Queue structure contains ArrayQueue, LinkedQueue, CircularQueue, and PriorityQueue.
package datastructure
import (

View File

@@ -20,6 +20,8 @@ func (c *intComparator) Compare(v1, v2 any) int {
return 0
}
func TestPriorityQueue_Enqueue(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestPriorityQueue_Enqueue")
comparator := &intComparator{}
@@ -45,6 +47,8 @@ func TestPriorityQueue_Enqueue(t *testing.T) {
}
func TestPriorityQueue_Dequeue(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestPriorityQueue_Dequeue")
comparator := &intComparator{}

View File

@@ -1,6 +1,10 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure contains some data structure. Set is a data container, like slice, but element of set is not duplicate.
package datastructure
// Set is a data container, like slice, but element of set is not duplicate
// Set is a data container, like slice, but element of set is not duplicate.
type Set[T comparable] map[T]struct{}
// NewSet return a instance of set

View File

@@ -7,6 +7,8 @@ import (
)
func TestSet_NewSetFromSlice(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_NewSetFromSlice")
s1 := NewSetFromSlice([]int{1, 2, 2, 3})
@@ -20,17 +22,21 @@ func TestSet_NewSetFromSlice(t *testing.T) {
}
func TestSet_Add(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_Add")
set := NewSet[int]()
set.Add(1, 2, 3)
expected := NewSet(1, 2, 3)
cmpSet := NewSet(1, 2, 3)
assert.Equal(true, set.Equal(expected))
assert.Equal(true, set.Equal(cmpSet))
}
func TestSet_AddIfNotExist(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_AddIfNotExist")
set := NewSet[int]()
@@ -42,6 +48,8 @@ func TestSet_AddIfNotExist(t *testing.T) {
}
func TestSet_AddIfNotExistBy(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_AddIfNotExistBy")
set := NewSet[int]()
@@ -63,6 +71,8 @@ func TestSet_AddIfNotExistBy(t *testing.T) {
}
func TestSet_Contain(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_Contain")
set := NewSet[int]()
@@ -73,6 +83,8 @@ func TestSet_Contain(t *testing.T) {
}
func TestSet_ContainAll(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_ContainAll")
set1 := NewSet(1, 2, 3)
@@ -84,6 +96,8 @@ func TestSet_ContainAll(t *testing.T) {
}
func TestSet_Clone(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_Clone")
set1 := NewSet(1, 2, 3)
@@ -94,18 +108,20 @@ func TestSet_Clone(t *testing.T) {
}
func TestSet_Delete(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_Delete")
set := NewSet[int]()
set.Add(1, 2, 3)
set.Delete(3)
expected := NewSet(1, 2)
assert.Equal(true, set.Equal(expected))
assert.Equal(true, set.Equal(NewSet(1, 2)))
}
func TestSet_Equal(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_Equal")
set1 := NewSet(1, 2, 3)
@@ -117,6 +133,8 @@ func TestSet_Equal(t *testing.T) {
}
func TestSet_Iterate(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_Iterate")
set := NewSet(1, 2, 3)
@@ -129,6 +147,8 @@ func TestSet_Iterate(t *testing.T) {
}
func TestSet_IsEmpty(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_IsEmpty")
set := NewSet[int]()
@@ -136,6 +156,8 @@ func TestSet_IsEmpty(t *testing.T) {
}
func TestSet_Size(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_Size")
set := NewSet(1, 2, 3)
@@ -143,6 +165,8 @@ func TestSet_Size(t *testing.T) {
}
func TestSet_Values(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_Values")
set := NewSet(1, 2, 3)
@@ -152,28 +176,33 @@ func TestSet_Values(t *testing.T) {
}
func TestSet_Union(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_Union")
set1 := NewSet(1, 2, 3)
set2 := NewSet(2, 3, 4, 5)
expected := NewSet(1, 2, 3, 4, 5)
unionSet := set1.Union(set2)
assert.Equal(expected, unionSet)
assert.Equal(NewSet(1, 2, 3, 4, 5), unionSet)
}
func TestSet_Intersection(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_Intersection")
set1 := NewSet(1, 2, 3)
set2 := NewSet(2, 3, 4, 5)
expected := NewSet(2, 3)
intersectionSet := set1.Intersection(set2)
assert.Equal(expected, intersectionSet)
assert.Equal(NewSet(2, 3), intersectionSet)
}
func TestSet_SymmetricDifference(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_SymmetricDifference")
set1 := NewSet(1, 2, 3)
@@ -183,6 +212,8 @@ func TestSet_SymmetricDifference(t *testing.T) {
}
func TestSet_Minus(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSet_Minus")
set1 := NewSet(1, 2, 3)

View File

@@ -1,3 +1,7 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure contains some data structure. Stack structure contains ArrayStack and LinkedStack.
package datastructure
import "errors"

View File

@@ -7,6 +7,8 @@ import (
)
func TestArrayStack_Push(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestArrayStack_Push")
stack := NewArrayStack[int]()
@@ -14,15 +16,16 @@ func TestArrayStack_Push(t *testing.T) {
stack.Push(2)
stack.Push(3)
expected := []int{3, 2, 1}
values := stack.Data()
length := stack.Size()
assert.Equal(expected, values)
assert.Equal([]int{3, 2, 1}, values)
assert.Equal(3, length)
}
func TestArrayStack_Pop(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestArrayStack_Pop")
stack := NewArrayStack[int]()
@@ -37,11 +40,12 @@ func TestArrayStack_Pop(t *testing.T) {
assert.IsNil(err)
assert.Equal(3, *topItem)
expected := []int{2, 1}
assert.Equal(expected, stack.Data())
assert.Equal([]int{2, 1}, stack.Data())
}
func TestArrayStack_Peak(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestArrayStack_Peak")
stack := NewArrayStack[int]()
@@ -56,11 +60,12 @@ func TestArrayStack_Peak(t *testing.T) {
assert.IsNil(err)
assert.Equal(3, *topItem)
expected := []int{3, 2, 1}
assert.Equal(expected, stack.Data())
assert.Equal([]int{3, 2, 1}, stack.Data())
}
func TestArrayStack_Clear(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestArrayStack_Clear")
stack := NewArrayStack[int]()

View File

@@ -1,3 +1,7 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure contains some data structure. Stack structure contains ArrayStack and LinkedStack.
package datastructure
import (

View File

@@ -7,6 +7,8 @@ import (
)
func TestLinkedStack_Push(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLinkedStack_Push")
stack := NewLinkedStack[int]()
@@ -14,15 +16,16 @@ func TestLinkedStack_Push(t *testing.T) {
stack.Push(2)
stack.Push(3)
expected := []int{3, 2, 1}
values := stack.Data()
size := stack.Size()
assert.Equal(expected, values)
assert.Equal([]int{3, 2, 1}, values)
assert.Equal(3, size)
}
func TestLinkedStack_Pop(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLinkedStack_Pop")
stack := NewLinkedStack[int]()
@@ -37,12 +40,13 @@ func TestLinkedStack_Pop(t *testing.T) {
assert.IsNil(err)
assert.Equal(3, *topItem)
expected := []int{2, 1}
stack.Print()
assert.Equal(expected, stack.Data())
assert.Equal([]int{2, 1}, stack.Data())
}
func TestLinkedStack_Peak(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLinkedStack_Peak")
stack := NewLinkedStack[int]()
@@ -57,11 +61,12 @@ func TestLinkedStack_Peak(t *testing.T) {
assert.IsNil(err)
assert.Equal(3, *topItem)
expected := []int{3, 2, 1}
assert.Equal(expected, stack.Data())
assert.Equal([]int{3, 2, 1}, stack.Data())
}
func TestLinkedStack_Empty(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLinkedStack_Empty")
stack := NewLinkedStack[int]()

View File

@@ -1,3 +1,7 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package datastructure contains some data structure. BSTree is binary search tree.
package datastructure
import (

View File

@@ -20,16 +20,9 @@ func (c *intComparator) Compare(v1, v2 any) int {
return 0
}
func TestBSTree_Insert(t *testing.T) {
bstree := NewBSTree(6, &intComparator{})
bstree.Insert(7)
bstree.Insert(5)
bstree.Insert(2)
bstree.Insert(4)
}
func TestBSTree_PreOrderTraverse(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBSTree_PreOrderTraverse")
bstree := NewBSTree(6, &intComparator{})
@@ -44,6 +37,8 @@ func TestBSTree_PreOrderTraverse(t *testing.T) {
}
func TestBSTree_PostOrderTraverse(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBSTree_PostOrderTraverse")
bstree := NewBSTree(6, &intComparator{})
@@ -58,6 +53,8 @@ func TestBSTree_PostOrderTraverse(t *testing.T) {
}
func TestBSTree_InOrderTraverse(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBSTree_InOrderTraverse")
bstree := NewBSTree(6, &intComparator{})
@@ -72,6 +69,8 @@ func TestBSTree_InOrderTraverse(t *testing.T) {
}
func TestBSTree_LevelOrderTraverse(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBSTree_LevelOrderTraverse")
bstree := NewBSTree(6, &intComparator{})
@@ -86,6 +85,8 @@ func TestBSTree_LevelOrderTraverse(t *testing.T) {
}
func TestBSTree_Delete(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBSTree_Delete")
bstree := NewBSTree(6, &intComparator{})
@@ -108,6 +109,8 @@ func TestBSTree_Delete(t *testing.T) {
}
func TestBSTree_Depth(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBSTree_Depth")
bstree := NewBSTree(6, &intComparator{})
@@ -121,6 +124,8 @@ func TestBSTree_Depth(t *testing.T) {
}
func TestBSTree_IsSubTree(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBSTree_IsSubTree")
superTree := NewBSTree(8, &intComparator{})

View File

@@ -7,6 +7,8 @@ import (
)
func TestToUnix(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToUnix")
tm1 := NewUnixNow()
@@ -17,6 +19,8 @@ func TestToUnix(t *testing.T) {
}
func TestToFormat(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToFormat")
tm, err := NewFormat("2022-03-18 17:04:05")
@@ -25,18 +29,21 @@ func TestToFormat(t *testing.T) {
}
func TestToFormatForTpl(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToFormatForTpl")
_, err := NewFormat("2022/03/18 17:04:05")
assert.IsNotNil(err)
tm, err := NewFormat("2022-03-18 17:04:05")
// assert.Equal("2022/03/18 17:04:05", tm.ToFormatForTpl("2006/01/02 15:04:05"))
t.Log("TestToFormatForTpl", tm.ToFormatForTpl("2006/01/02 15:04:05"))
assert.IsNil(err)
}
func TestToIso8601(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestToIso8601")
_, err := NewISO8601("2022-03-18 17:04:05")
@@ -44,6 +51,5 @@ func TestToIso8601(t *testing.T) {
tm, err := NewISO8601("2006-01-02T15:04:05.999Z")
t.Log("TestToIso8601", tm.ToIso8601())
// assert.Equal("2006-01-02T23:04:05+08:00", tm.ToIso8601())
assert.IsNil(err)
}

View File

@@ -35,7 +35,7 @@ func init() {
timeFormat = map[string]string{
"yyyy-mm-dd hh:mm:ss": "2006-01-02 15:04:05",
"yyyy-mm-dd hh:mm": "2006-01-02 15:04",
"yyyy-mm-dd hh": "2006-01-02 15:04",
"yyyy-mm-dd hh": "2006-01-02 15",
"yyyy-mm-dd": "2006-01-02",
"yyyy-mm": "2006-01",
"mm-dd": "01-02",
@@ -73,7 +73,7 @@ func AddDay(t time.Time, day int64) time.Time {
}
// AddYear add or sub year to the time.
// Play: todo
// Play: https://go.dev/play/p/MqW2ujnBx10
func AddYear(t time.Time, year int64) time.Time {
return t.Add(365 * 24 * time.Hour * time.Duration(year))
}
@@ -96,6 +96,18 @@ func GetNowDateTime() string {
return time.Now().Format("2006-01-02 15:04:05")
}
// GetTodayStartTime return the start time of today, format: yyyy-mm-dd 00:00:00.
// Play: todo
func GetTodayStartTime() string {
return time.Now().Format("2006-01-02") + " 00:00:00"
}
// GetTodayEndTime return the end time of today, format: yyyy-mm-dd 23:59:59.
// Play: todo
func GetTodayEndTime() string {
return time.Now().Format("2006-01-02") + " 23:59:59"
}
// GetZeroHourTimestamp return timestamp of zero hour (timestamp of 00:00).
// Play: https://go.dev/play/p/QmL2oIaGE3q
func GetZeroHourTimestamp() int64 {
@@ -226,7 +238,30 @@ func EndOfYear(t time.Time) time.Time {
}
// IsLeapYear check if param year is leap year or not.
// Play: todo
// Play: https://go.dev/play/p/xS1eS2ejGew
func IsLeapYear(year int) bool {
return year%4 == 0 && (year%100 != 0 || year%400 == 0)
}
// BetweenSeconds returns the number of seconds between two times.
// Play: https://go.dev/play/p/n3YDRyfyXJu
func BetweenSeconds(t1 time.Time, t2 time.Time) int64 {
index := t2.Unix() - t1.Unix()
return index
}
// DayOfYear returns which day of the year the parameter date `t` is.
// Play: https://go.dev/play/p/0hjqhTwFNlH
func DayOfYear(t time.Time) int {
y, m, d := t.Date()
firstDay := time.Date(y, 1, 1, 0, 0, 0, 0, t.Location())
nowDate := time.Date(y, m, d, 0, 0, 0, 0, t.Location())
return int(nowDate.Sub(firstDay).Hours() / 24)
}
// IsWeekend checks if passed time is weekend or not.
// Play: https://go.dev/play/p/cupRM5aZOIY
func IsWeekend(t time.Time) bool {
return time.Saturday == t.Weekday() || time.Sunday == t.Weekday()
}

View File

@@ -131,15 +131,18 @@ func ExampleFormatTimeToStr() {
result1 := FormatTimeToStr(datetime, "yyyy-mm-dd hh:mm:ss")
result2 := FormatTimeToStr(datetime, "yyyy-mm-dd")
result3 := FormatTimeToStr(datetime, "dd-mm-yy hh:mm:ss")
result4 := FormatTimeToStr(datetime, "yyyy-mm-dd hh")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// 2021-01-02 16:04:08
// 2021-01-02
// 02-01-21 16:04:08
// 2021-01-02 16
}
func ExampleFormatStrToTime() {
@@ -350,3 +353,58 @@ func ExampleIsLeapYear() {
// true
// false
}
func ExampleBetweenSeconds() {
today := time.Now()
tomorrow := AddDay(today, 1)
yesterday := AddDay(today, -1)
result1 := BetweenSeconds(today, tomorrow)
result2 := BetweenSeconds(today, yesterday)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 86400
// -86400
}
func ExampleDayOfYear() {
date1 := time.Date(2023, 02, 01, 1, 1, 1, 0, time.Local)
result1 := DayOfYear(date1)
date2 := time.Date(2023, 01, 02, 1, 1, 1, 0, time.Local)
result2 := DayOfYear(date2)
date3 := time.Date(2023, 01, 01, 1, 1, 1, 0, time.Local)
result3 := DayOfYear(date3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 31
// 1
// 0
}
func ExampleIsWeekend() {
date1 := time.Date(2023, 06, 03, 0, 0, 0, 0, time.Local)
date2 := time.Date(2023, 06, 04, 0, 0, 0, 0, time.Local)
date3 := time.Date(2023, 06, 02, 0, 0, 0, 0, time.Local)
result1 := IsWeekend(date1)
result2 := IsWeekend(date2)
result3 := IsWeekend(date3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// true
// true
// false
}

View File

@@ -8,6 +8,8 @@ import (
)
func TestAddYear(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestAddDay")
now := time.Now()
@@ -20,7 +22,25 @@ func TestAddYear(t *testing.T) {
assert.Equal(float64(-8760), diff2.Hours())
}
func TestBetweenSeconds(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBetweenSeconds")
today := time.Now()
tomorrow := AddDay(today, 1)
yesterday := AddDay(today, -1)
result1 := BetweenSeconds(today, tomorrow)
result2 := BetweenSeconds(today, yesterday)
assert.Equal(int64(86400), result1)
assert.Equal(int64(-86400), result2)
}
func TestAddDay(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestAddDay")
now := time.Now()
@@ -34,6 +54,8 @@ func TestAddDay(t *testing.T) {
}
func TestAddHour(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestAddHour")
now := time.Now()
@@ -47,6 +69,8 @@ func TestAddHour(t *testing.T) {
}
func TestAddMinute(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestAddMinute")
now := time.Now()
@@ -60,36 +84,64 @@ func TestAddMinute(t *testing.T) {
}
func TestGetNowDate(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestGetNowDate")
expected := time.Now().Format("2006-01-02")
assert.Equal(expected, GetNowDate())
}
func TestGetNowTime(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestGetNowTime")
expected := time.Now().Format("15:04:05")
assert.Equal(expected, GetNowTime())
}
func TestGetNowDateTime(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestGetNowDateTime")
expected := time.Now().Format("2006-01-02 15:04:05")
assert.Equal(expected, GetNowDateTime())
}
func TestGetTodayStartTime(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestGetTodayStartTime")
expected := time.Now().Format("2006-01-02") + " 00:00:00"
assert.Equal(expected, GetTodayStartTime())
}
func TestGetTodayEndTime(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestGetTodayEndTime")
expected := time.Now().Format("2006-01-02") + " 23:59:59"
assert.Equal(expected, GetTodayEndTime())
}
func TestFormatTimeToStr(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestFormatTimeToStr")
datetime, _ := time.Parse("2006-01-02 15:04:05", "2021-01-02 16:04:08")
cases := []string{
"yyyy-mm-dd hh:mm:ss", "yyyy-mm-dd",
"dd-mm-yy hh:mm:ss", "yyyy/mm/dd hh:mm:ss",
"hh:mm:ss", "yyyy/mm"}
"hh:mm:ss", "yyyy/mm",
"yyyy-mm-dd hh",
}
expected := []string{
"2021-01-02 16:04:08", "2021-01-02",
"02-01-21 16:04:08", "2021/01/02 16:04:08",
"16:04:08", "2021/01"}
"16:04:08", "2021/01",
"2021-01-02 16",
}
for i := 0; i < len(cases); i++ {
actual := FormatTimeToStr(datetime, cases[i])
@@ -98,6 +150,8 @@ func TestFormatTimeToStr(t *testing.T) {
}
func TestFormatStrToTime(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestFormatStrToTime")
formats := []string{
@@ -125,6 +179,8 @@ func TestFormatStrToTime(t *testing.T) {
}
func TestBeginOfMinute(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBeginOfMinute")
expected := time.Date(2022, 2, 15, 15, 48, 0, 0, time.Local)
@@ -135,6 +191,8 @@ func TestBeginOfMinute(t *testing.T) {
}
func TestEndOfMinute(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestEndOfMinute")
expected := time.Date(2022, 2, 15, 15, 48, 59, 999999999, time.Local)
@@ -145,6 +203,8 @@ func TestEndOfMinute(t *testing.T) {
}
func TestBeginOfHour(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBeginOfHour")
expected := time.Date(2022, 2, 15, 15, 0, 0, 0, time.Local)
@@ -155,6 +215,8 @@ func TestBeginOfHour(t *testing.T) {
}
func TestEndOfHour(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestEndOfHour")
expected := time.Date(2022, 2, 15, 15, 59, 59, 999999999, time.Local)
@@ -165,6 +227,8 @@ func TestEndOfHour(t *testing.T) {
}
func TestBeginOfDay(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBeginOfDay")
expected := time.Date(2022, 2, 15, 0, 0, 0, 0, time.Local)
@@ -175,6 +239,8 @@ func TestBeginOfDay(t *testing.T) {
}
func TestEndOfDay(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestEndOfDay")
expected := time.Date(2022, 2, 15, 23, 59, 59, 999999999, time.Local)
@@ -185,6 +251,8 @@ func TestEndOfDay(t *testing.T) {
}
func TestBeginOfWeek(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBeginOfWeek")
expected := time.Date(2022, 2, 13, 0, 0, 0, 0, time.Local)
@@ -195,6 +263,8 @@ func TestBeginOfWeek(t *testing.T) {
}
func TestEndOfWeek(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestEndOfWeek")
expected := time.Date(2022, 2, 19, 23, 59, 59, 999999999, time.Local)
@@ -205,6 +275,8 @@ func TestEndOfWeek(t *testing.T) {
}
func TestBeginOfMonth(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBeginOfMonth")
expected := time.Date(2022, 2, 1, 0, 0, 0, 0, time.Local)
@@ -215,6 +287,8 @@ func TestBeginOfMonth(t *testing.T) {
}
func TestEndOfMonth(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestEndOfMonth")
expected := time.Date(2022, 2, 28, 23, 59, 59, 999999999, time.Local)
@@ -225,6 +299,8 @@ func TestEndOfMonth(t *testing.T) {
}
func TestBeginOfYear(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBeginOfYear")
expected := time.Date(2022, 1, 1, 0, 0, 0, 0, time.Local)
@@ -235,6 +311,8 @@ func TestBeginOfYear(t *testing.T) {
}
func TestEndOfYear(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestEndOfYear")
expected := time.Date(2022, 12, 31, 23, 59, 59, 999999999, time.Local)
@@ -245,6 +323,8 @@ func TestEndOfYear(t *testing.T) {
}
func TestIsLeapYear(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestEndOfYear")
result1 := IsLeapYear(2000)
@@ -253,3 +333,38 @@ func TestIsLeapYear(t *testing.T) {
assert.Equal(true, result1)
assert.Equal(false, result2)
}
func TestDayOfYear(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDayOfYear")
date1 := time.Date(2023, 02, 01, 1, 1, 1, 0, time.Local)
result1 := DayOfYear(date1)
assert.Equal(31, result1)
date2 := time.Date(2023, 01, 02, 1, 1, 1, 0, time.Local)
result2 := DayOfYear(date2)
assert.Equal(1, result2)
date3 := time.Date(2023, 01, 01, 1, 1, 1, 0, time.Local)
result3 := DayOfYear(date3)
assert.Equal(0, result3)
}
func TestIsWeekend(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIsWeekend")
date := time.Date(2023, 06, 03, 0, 0, 0, 0, time.Local)
result := IsWeekend(date)
assert.Equal(true, result)
date1 := time.Date(2023, 06, 04, 0, 0, 0, 0, time.Local)
result1 := IsWeekend(date1)
assert.Equal(true, result1)
date2 := time.Date(2023, 06, 02, 0, 0, 0, 0, time.Local)
result2 := IsWeekend(date2)
assert.Equal(false, result2)
}

View File

@@ -41,6 +41,8 @@ import (
- [DeepClone](#DeepClone)
- [CopyProperties](#CopyProperties)
- [ToInterface](#ToInterface)
- [Utf8ToGbk](#Utf8ToGbk)
- [GbkToUtf8](#GbkToUtf8)
<div STYLE="page-break-after: always;"></div>
@@ -795,15 +797,82 @@ import (
func main() {
val := reflect.ValueOf("abc")
iVal, ok := convertor.ToInterface(val)
iVal, ok := convertor.ToInterface(val)
fmt.Printf("%T\n", iVal)
fmt.Printf("%v\n", iVal)
fmt.Println(ok)
fmt.Printf("%T\n", iVal)
fmt.Printf("%v\n", iVal)
fmt.Println(ok)
// Output:
// string
// abc
// true
// Output:
// string
// abc
// true
}
```
### <span id="Utf8ToGbk">Utf8ToGbk</span>
<p>Converts utf8 encoding data to GBK encoding data.</p>
<b>Signature:</b>
```go
func Utf8ToGbk(bs []byte) ([]byte, error)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
utf8Data := []byte("hello")
gbkData, _ := convertor.Utf8ToGbk(utf8Data)
fmt.Println(utf8.Valid(utf8Data))
fmt.Println(validator.IsGBK(gbkData))
// Output:
// true
// true
}
```
### <span id="GbkToUtf8">GbkToUtf8</span>
<p>Converts GBK encoding data to utf8 encoding data.</p>
<b>Signature:</b>
```go
func GbkToUtf8(bs []byte) ([]byte, error)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
gbkData, _ := convertor.Utf8ToGbk([]byte("hello"))
utf8Data, _ := convertor.GbkToUtf8(gbkData)
fmt.Println(utf8.Valid(utf8Data))
fmt.Println(string(utf8Data))
// Output:
// true
// hello
}
```

View File

@@ -41,6 +41,8 @@ import (
- [DeepClone](#DeepClone)
- [CopyProperties](#CopyProperties)
- [ToInterface](#ToInterface)
- [Utf8ToGbk](#Utf8ToGbk)
- [GbkToUtf8](#GbkToUtf8)
<div STYLE="page-break-after: always;"></div>
@@ -795,15 +797,82 @@ import (
func main() {
val := reflect.ValueOf("abc")
iVal, ok := convertor.ToInterface(val)
iVal, ok := convertor.ToInterface(val)
fmt.Printf("%T\n", iVal)
fmt.Printf("%v\n", iVal)
fmt.Println(ok)
fmt.Printf("%T\n", iVal)
fmt.Printf("%v\n", iVal)
fmt.Println(ok)
// Output:
// string
// abc
// true
// Output:
// string
// abc
// true
}
```
### <span id="Utf8ToGbk">Utf8ToGbk</span>
<p>utf8编码转GBK编码。</p>
<b>函数签名:</b>
```go
func Utf8ToGbk(bs []byte) ([]byte, error)
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
"github.com/duke-git/lancet/v2/validator"
)
func main() {
utf8Data := []byte("hello")
gbkData, _ := convertor.Utf8ToGbk(utf8Data)
fmt.Println(utf8.Valid(utf8Data))
fmt.Println(validator.IsGBK(gbkData))
// Output:
// true
// true
}
```
### <span id="GbkToUtf8">GbkToUtf8</span>
<p>GBK编码转utf8编码。</p>
<b>函数签名:</b>
```go
func GbkToUtf8(bs []byte) ([]byte, error)
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
gbkData, _ := convertor.Utf8ToGbk([]byte("hello"))
utf8Data, _ := convertor.GbkToUtf8(gbkData)
fmt.Println(utf8.Valid(utf8Data))
fmt.Println(string(utf8Data))
// Output:
// true
// hello
}
```

View File

@@ -48,6 +48,7 @@ import (
- [HmacSha256](#HmacSha256)
- [HmacSha512](#HmacSha512)
- [Md5String](#Md5String)
- [Md5Byte](#Md5Byte)
- [Md5File](#Md5File)
- [Sha1](#Sha1)
- [Sha256](#Sha256)
@@ -880,6 +881,35 @@ func main() {
}
```
### <span id="Md5Byte">Md5Byte</span>
<p>Return the md5 string of byte slice.</p>
<b>Signature:</b>
```go
func Md5Byte(data []byte) string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
md5Str := cryptor.Md5Byte([]byte{'a'})
fmt.Println(md5Str)
// Output:
// 0cc175b9c0f1b6a831c399e269772661
}
```
### <span id="Md5File">Md5File</span>
<p>Get the md5 value of file.</p>

View File

@@ -45,6 +45,7 @@ import (
- [HmacSha256](#HmacSha256)
- [HmacSha512](#HmacSha512)
- [Md5String](#Md5String)
- [Md5Byte](#Md5Byte)
- [Md5File](#Md5File)
- [Sha1](#Sha1)
- [Sha256](#Sha256)
@@ -879,6 +880,35 @@ func main() {
}
```
### <span id="Md5Byte">Md5Byte</span>
<p>获取byte slice的md5至。</p>
<b>函数签名:</b>
```go
func Md5Byte(data []byte) string
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/cryptor"
)
func main() {
md5Str := cryptor.Md5Byte([]byte{'a'})
fmt.Println(md5Str)
// Output:
// 0cc175b9c0f1b6a831c399e269772661
}
```
### <span id="Md5File">Md5File</span>
<p>获取文件md5值。</p>

View File

@@ -42,6 +42,8 @@ import (
- [GetNowDate](#GetNowDate)
- [GetNowTime](#GetNowTime)
- [GetNowDateTime](#GetNowDateTime)
- [GetTodayStartTime](#GetTodayStartTime)
- [GetTodayEndTime](#GetTodayEndTime)
- [GetZeroHourTimestamp](#GetZeroHourTimestamp)
- [GetNightTimestamp](#GetNightTimestamp)
- [FormatTimeToStr](#FormatTimeToStr)
@@ -55,6 +57,9 @@ import (
- [ToFormatForTpl](#ToFormatForTpl)
- [ToIso8601](#ToIso8601)
- [IsLeapYear](#IsLeapYear)
- [BetweenSeconds](#BetweenSeconds)
- [DayOfYear](#DayOfYear)
- [IsWeekend](#IsWeekend)
<div STYLE="page-break-after: always;"></div>
@@ -224,18 +229,18 @@ import (
func main() {
now := time.Now()
after1Year := AddYear(now, 1)
diff1 := after1Year.Sub(now)
after1Year := datetime.AddYear(now, 1)
diff1 := after1Year.Sub(now)
before1Year := AddYear(now, -1)
diff2 := before1Year.Sub(now)
before1Year := datetime.AddYear(now, -1)
diff2 := before1Year.Sub(now)
fmt.Println(diff1)
fmt.Println(diff2)
fmt.Println(diff1)
fmt.Println(diff2)
// Output:
// 8760h0m0s
// -8760h0m0s
// Output:
// 8760h0m0s
// -8760h0m0s
}
```
@@ -640,14 +645,11 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
now := time.Now()
currentDate := datetime.GetNowDate()
fmt.Println(currentDate)
// Output:
@@ -672,14 +674,11 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
now := time.Now()
currentTime := datetime.GetNowTime()
fmt.Println(currentTime) // 15:57:33
// Output:
@@ -704,14 +703,11 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
now := time.Now()
current := datetime.GetNowDateTime()
fmt.Println(current)
// Output:
@@ -719,6 +715,64 @@ func main() {
}
```
### <span id="GetTodayStartTime">GetTodayStartTime</span>
<p>Return the start time of today, format: yyyy-mm-dd 00:00:00.</p>
<b>Signature:</b>
```go
func GetTodayStartTime() string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
startTime := datetime.GetTodayStartTime()
fmt.Println(startTime)
// Output:
// 2023-06-29 00:00:00
}
```
### <span id="GetTodayEndTime">GetTodayEndTime</span>
<p>Return the end time of today, format: yyyy-mm-dd 23:59:59.</p>
<b>Signature:</b>
```go
func GetTodayEndTime() string
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
endTime := datetime.GetTodayEndTime()
fmt.Println(endTime)
// Output:
// 2023-06-29 23:59:59
}
```
### <span id="GetZeroHourTimestamp">GetZeroHourTimestamp</span>
<p>Return timestamp of zero hour (timestamp of 00:00).</p>
@@ -736,14 +790,11 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
now := time.Now()
zeroTime := datetime.GetZeroHourTimestamp()
fmt.Println(zeroTime)
// Output:
@@ -768,14 +819,11 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
now := time.Now()
nightTime := datetime.GetNightTimestamp()
fmt.Println(nightTime)
// Output:
@@ -1136,3 +1184,124 @@ func main() {
// false
}
```
### <span id="BetweenSeconds">BetweenSeconds</span>
<p>Return the number of seconds between two times.</p>
<b>Signature:</b>
```go
func BetweenSeconds(t1 time.Time, t2 time.Time) int64
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
today := time.Now()
tomorrow := datetime.AddDay(today, 1)
yesterday := datetime.AddDay(today, -1)
result1 := datetime.BetweenSeconds(today, tomorrow)
result2 := datetime.BetweenSeconds(today, yesterday)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 86400
// -86400
}
```
### <span id="DayOfYear">DayOfYear</span>
<p>Returns which day of the year the parameter date `t` is.</p>
<b>Signature:</b>
```go
func DayOfYear(t time.Time) int
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
date1 := time.Date(2023, 02, 01, 1, 1, 1, 0, time.Local)
result1 := datetime.DayOfYear(date1)
date2 := time.Date(2023, 01, 02, 1, 1, 1, 0, time.Local)
result2 := datetime.DayOfYear(date2)
date3 := time.Date(2023, 01, 01, 1, 1, 1, 0, time.Local)
result3 := datetime.DayOfYear(date3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 31
// 1
// 0
}
```
### <span id="IsWeekend">IsWeekend</span>
<p>Checks if passed time is weekend or not.</p>
<b>Signature:</b>
```go
func IsWeekend(t time.Time) bool
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
date1 := time.Date(2023, 06, 03, 0, 0, 0, 0, time.Local)
date2 := time.Date(2023, 06, 04, 0, 0, 0, 0, time.Local)
date3 := time.Date(2023, 06, 02, 0, 0, 0, 0, time.Local)
result1 := datetime.IsWeekend(date1)
result2 := datetime.IsWeekend(date2)
result3 := datetime.IsWeekend(date3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// true
// true
// false
}
```

View File

@@ -41,6 +41,8 @@ import (
- [GetNowDate](#GetNowDate)
- [GetNowTime](#GetNowTime)
- [GetNowDateTime](#GetNowDateTime)
- [GetTodayStartTime](#GetTodayStartTime)
- [GetTodayEndTime](#GetTodayEndTime)
- [GetZeroHourTimestamp](#GetZeroHourTimestamp)
- [GetNightTimestamp](#GetNightTimestamp)
- [FormatTimeToStr](#FormatTimeToStr)
@@ -54,6 +56,10 @@ import (
- [ToFormatForTpl](#ToFormatForTpl)
- [ToIso8601](#ToIso8601)
- [IsLeapYear](#IsLeapYear)
- [BetweenSeconds](#BetweenSeconds)
- [DayOfYear](#DayOfYear)
- [IsWeekend](#IsWeekend)
<div STYLE="page-break-after: always;"></div>
@@ -223,18 +229,18 @@ import (
func main() {
now := time.Now()
after1Year := AddYear(now, 1)
diff1 := after1Year.Sub(now)
after1Year := datetime.AddYear(now, 1)
diff1 := after1Year.Sub(now)
before1Year := AddYear(now, -1)
diff2 := before1Year.Sub(now)
before1Year := datetime.AddYear(now, -1)
diff2 := before1Year.Sub(now)
fmt.Println(diff1)
fmt.Println(diff2)
fmt.Println(diff1)
fmt.Println(diff2)
// Output:
// 8760h0m0s
// -8760h0m0s
// Output:
// 8760h0m0s
// -8760h0m0s
}
```
@@ -639,14 +645,11 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
now := time.Now()
currentDate := datetime.GetNowDate()
fmt.Println(currentDate)
// Output:
@@ -671,15 +674,12 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
now := time.Now()
currentTime := datetime.GetNowTime()
fmt.Println(currentTime) // 15:57:33
fmt.Println(currentTime)
// Output:
// 15:57:33
@@ -703,14 +703,11 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
now := time.Now()
current := datetime.GetNowDateTime()
fmt.Println(current)
// Output:
@@ -718,6 +715,64 @@ func main() {
}
```
### <span id="GetTodayStartTime">GetTodayStartTime</span>
<p>返回当天开始时间, 格式: yyyy-mm-dd 00:00:00.</p>
<b>函数签名:</b>
```go
func GetTodayStartTime() string
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
startTime := datetime.GetTodayStartTime()
fmt.Println(startTime)
// Output:
// 2023-06-29 00:00:00
}
```
### <span id="GetTodayEndTime">GetTodayEndTime</span>
<p>返回当天结束时间,格式: yyyy-mm-dd 23:59:59.</p>
<b>函数签名:</b>
```go
func GetTodayEndTime() string
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
endTime := datetime.GetTodayEndTime()
fmt.Println(endTime)
// Output:
// 2023-06-29 23:59:59
}
```
### <span id="GetZeroHourTimestamp">GetZeroHourTimestamp</span>
<p>获取零点时间戳(timestamp of 00:00)</p>
@@ -735,14 +790,11 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
now := time.Now()
zeroTime := datetime.GetZeroHourTimestamp()
fmt.Println(zeroTime)
// Output:
@@ -767,14 +819,11 @@ package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
now := time.Now()
nightTime := datetime.GetNightTimestamp()
fmt.Println(nightTime)
// Output:
@@ -1103,7 +1152,6 @@ func main() {
}
```
### <span id="IsLeapYear">IsLeapYear</span>
<p>验证是否是闰年。</p>
@@ -1136,3 +1184,121 @@ func main() {
// false
}
```
### <span id="BetweenSeconds">BetweenSeconds</span>
<p>返回两个时间的间隔秒数。</p>
<b>函数签名:</b>
```go
func BetweenSeconds(t1 time.Time, t2 time.Time) int64
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
today := time.Now()
tomorrow := datetime.AddDay(today, 1)
yesterday := datetime.AddDay(today, -1)
result1 := datetime.BetweenSeconds(today, tomorrow)
result2 := datetime.BetweenSeconds(today, yesterday)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 86400
// -86400
}
```
### <span id="DayOfYear">DayOfYear</span>
<p>返回参数日期是一年中的第几天。</p>
<b>函数签名:</b>
```go
func DayOfYear(t time.Time) int
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
date1 := time.Date(2023, 02, 01, 1, 1, 1, 0, time.Local)
result1 := datetime.DayOfYear(date1)
date2 := time.Date(2023, 01, 02, 1, 1, 1, 0, time.Local)
result2 := datetime.DayOfYear(date2)
date3 := time.Date(2023, 01, 01, 1, 1, 1, 0, time.Local)
result3 := datetime.DayOfYear(date3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 31
// 1
// 0
}
```
### <span id="IsWeekend">IsWeekend</span>
<p>判断日期是否是周末。</p>
<b>函数签名:</b>
```go
func IsWeekend(t time.Time) bool
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
date1 := time.Date(2023, 06, 03, 0, 0, 0, 0, time.Local)
date2 := time.Date(2023, 06, 04, 0, 0, 0, 0, time.Local)
date3 := time.Date(2023, 06, 02, 0, 0, 0, 0, time.Local)
result1 := datetime.IsWeekend(date1)
result2 := datetime.IsWeekend(date2)
result3 := datetime.IsWeekend(date3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// true
// true
// false
}
```

View File

@@ -37,12 +37,16 @@ import (
- [ReadFileToString](#ReadFileToString)
- [ReadFileByLine](#ReadFileByLine)
- [Zip](#Zip)
- [ZipAppendEntry](#ZipAppendEntry)
- [UnZip](#UnZip)
- [IsZipFile](#IsZipFile)
- [FileSize](#FileSize)
- [MTime](#MTime)
- [Sha](#Sha)
- [ReadCsvFile](#ReadCsvFile)
- [WriteCsvFile](#WriteCsvFile)
- [WriteStringToFile](#WriteStringToFile)
- [WriteBytesToFile](#WriteBytesToFile)
<div STYLE="page-break-after: always;"></div>
@@ -473,6 +477,34 @@ func main() {
}
```
### <span id="ZipAppendEntry">ZipAppendEntry</span>
<p>Append a single file or directory by fpath to an existing zip file.</p>
<b>Signature:</b>
```go
func ZipAppendEntry(fpath string, destPath string) error
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
err := fileutil.ZipAppendEntry("./test.txt", "./test.zip")
if err != nil {
fmt.Println(err)
}
}
```
### <span id="UnZip">UnZip</span>
<p>Unzip the file and save it to dest path.</p>
@@ -660,3 +692,150 @@ func main() {
// <nil>
}
```
### <span id="WriteCsvFile">WriteCsvFile</span>
<p>Write content to target csv file.</p>
<b>Signature:</b>
```go
func WriteCsvFile(filepath string, records [][]string, append bool) error
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
fpath := "./test.csv"
fileutil.CreateFile(fpath)
f, _ := os.OpenFile(fpath, os.O_WRONLY|os.O_TRUNC, 0777)
defer f.Close()
data := [][]string{
{"Lili", "22", "female"},
{"Jim", "21", "male"},
}
err := fileutil.WriteCsvFile(fpath, data, false)
if err != nil {
return
}
content, err := fileutil.ReadCsvFile(fpath)
if err != nil {
return
}
fmt.Println(content)
// Output:
// [[Lili 22 female] [Jim 21 male]]
}
```
### <span id="WriteBytesToFile">WriteBytesToFile</span>
<p>Writes bytes to target file.</p>
<b>Signature:</b>
```go
func WriteBytesToFile(filepath string, content []byte) error
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
filepath := "./bytes.txt"
file, err := os.Create(filepath)
if err != nil {
return
}
defer file.Close()
err = fileutil.WriteBytesToFile(filepath, []byte("hello"))
if err != nil {
return
}
content, err := fileutil.ReadFileToString(filepath)
if err != nil {
return
}
os.Remove(filepath)
fmt.Println(content)
// Output:
// hello
}
```
### <span id="WriteStringToFile">WriteStringToFile</span>
<p>Writes string to target file.</p>
<b>Signature:</b>
```go
func WriteStringToFile(filepath string, content string, append bool) error
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
filepath := "./test.txt"
file, err := os.Create(filepath)
if err != nil {
return
}
defer file.Close()
err = fileutil.WriteStringToFile(filepath, "hello", true)
if err != nil {
return
}
content, err := fileutil.ReadFileToString(filepath)
if err != nil {
return
}
os.Remove(filepath)
fmt.Println(content)
// Output:
// hello
}
```

View File

@@ -37,12 +37,16 @@ import (
- [ReadFileToString](#ReadFileToString)
- [ReadFileByLine](#ReadFileByLine)
- [Zip](#Zip)
- [ZipAppendEntry](#ZipAppendEntry)
- [UnZip](#UnZip)
- [IsZipFile](#IsZipFile)
- [FileSize](#FileSize)
- [MTime](#MTime)
- [Sha](#Sha)
- [ReadCsvFile](#ReadCsvFile)
- [WriteCsvFile](#WriteCsvFile)
- [WriteStringToFile](#WriteStringToFile)
- [WriteBytesToFile](#WriteBytesToFile)
<div STYLE="page-break-after: always;"></div>
@@ -473,6 +477,34 @@ func main() {
}
```
### <span id="ZipAppendEntry">ZipAppendEntry</span>
<p>通过将单个文件或目录追加到现有的zip文件</p>
<b>函数签名:</b>
```go
func ZipAppendEntry(fpath string, destPath string) error
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
err := fileutil.ZipAppendEntry("./test.txt", "./test.zip")
if err != nil {
fmt.Println(err)
}
}
```
### <span id="UnZip">UnZip</span>
<p>zip解压缩文件并保存在目录中</p>
@@ -660,3 +692,150 @@ func main() {
// <nil>
}
```
### <span id="WriteCsvFile">WriteCsvFile</span>
<p>向csv文件写入内容。</p>
<b>函数签名:</b>
```go
func WriteCsvFile(filepath string, records [][]string, append bool) error
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
fpath := "./test.csv"
fileutil.CreateFile(fpath)
f, _ := os.OpenFile(fpath, os.O_WRONLY|os.O_TRUNC, 0777)
defer f.Close()
data := [][]string{
{"Lili", "22", "female"},
{"Jim", "21", "male"},
}
err := fileutil.WriteCsvFile(fpath, data, false)
if err != nil {
return
}
content, err := fileutil.ReadCsvFile(fpath)
if err != nil {
return
}
fmt.Println(content)
// Output:
// [[Lili 22 female] [Jim 21 male]]
}
```
### <span id="WriteBytesToFile">WriteBytesToFile</span>
<p>将bytes写入文件。</p>
<b>函数签名:</b>
```go
func WriteBytesToFile(filepath string, content []byte) error
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
filepath := "./bytes.txt"
file, err := os.Create(filepath)
if err != nil {
return
}
defer file.Close()
err = fileutil.WriteBytesToFile(filepath, []byte("hello"))
if err != nil {
return
}
content, err := fileutil.ReadFileToString(filepath)
if err != nil {
return
}
os.Remove(filepath)
fmt.Println(content)
// Output:
// hello
}
```
### <span id="WriteStringToFile">WriteStringToFile</span>
<p>将字符串写入文件。</p>
<b>函数签名:</b>
```go
func WriteStringToFile(filepath string, content string, append bool) error
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/fileutil"
)
func main() {
filepath := "./test.txt"
file, err := os.Create(filepath)
if err != nil {
return
}
defer file.Close()
err = fileutil.WriteStringToFile(filepath, "hello", true)
if err != nil {
return
}
content, err := fileutil.ReadFileToString(filepath)
if err != nil {
return
}
os.Remove(filepath)
fmt.Println(content)
// Output:
// hello
}
```

View File

@@ -42,6 +42,12 @@ import (
- [IsPrime](#IsPrime)
- [GCD](#GCD)
- [LCM](#LCM)
- [Cos](#Cos)
- [Sin](#Sin)
- [Log](#Log)
- [Sum](#Sum)
- [Abs](#Abs)
<div STYLE="page-break-after: always;"></div>
@@ -365,18 +371,18 @@ import (
)
func main() {
result1 := Percent(1, 2, 2)
result2 := Percent(0.1, 0.3, 2)
result3 := Percent(-30305, 408420, 2)
result1 := mathutil.Percent(1, 2, 2)
result2 := mathutil.Percent(0.1, 0.3, 2)
result3 := mathutil.Percent(-30305, 408420, 2)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 50
// 33.33
// -7.42
// Output:
// 50
// 33.33
// -7.42
}
```
@@ -602,7 +608,6 @@ func main() {
}
```
### <span id="RadianToAngle">RadianToAngle</span>
<p>Converts radian value to angle value.</p>
@@ -669,7 +674,6 @@ func main() {
}
```
### <span id="IsPrime">IsPrime</span>
<p>Checks if number is prime number.</p>
@@ -692,20 +696,20 @@ import (
func main() {
result1 := mathutil.IsPrime(-1)
result2 := mathutil.IsPrime(0)
result3 := mathutil.IsPrime(1)
result4 := mathutil.IsPrime(2)
result2 := mathutil.IsPrime(0)
result3 := mathutil.IsPrime(1)
result4 := mathutil.IsPrime(2)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// false
// false
// false
// true
// Output:
// false
// false
// false
// true
}
```
@@ -731,27 +735,26 @@ import (
func main() {
result1 := mathutil.GCD(1, 1)
result2 := mathutil.GCD(1, -1)
result3 := mathutil.GCD(-1, 1)
result4 := mathutil.GCD(-1, -1)
result5 := mathutil.GCD(3, 6, 9)
result2 := mathutil.GCD(1, -1)
result3 := mathutil.GCD(-1, 1)
result4 := mathutil.GCD(-1, -1)
result5 := mathutil.GCD(3, 6, 9)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// 1
// 1
// -1
// -1
// 3
// Output:
// 1
// 1
// -1
// -1
// 3
}
```
### <span id="LCM">LCM</span>
<p>Return Least Common Multiple (LCM) of integers.</p>
@@ -774,8 +777,199 @@ import (
func main() {
result1 := mathutil.LCM(1, 1)
result2 := mathutil.LCM(1, 2)
result3 := mathutil.LCM(3, 6, 9)
result2 := mathutil.LCM(1, 2)
result3 := mathutil.LCM(3, 6, 9)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 1
// 2
// 18
}
```
### <span id="Cos">Cos</span>
<p>Returns the cosine of the radian argument.</p>
<b>Signature:</b>
```go
func Cos(radian float64, precision ...int) float64
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.Cos(0)
result2 := mathutil.Cos(90)
result3 := mathutil.Cos(180)
result4 := mathutil.Cos(math.Pi)
result5 := mathutil.Cos(math.Pi / 2)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// 1
// -0.447
// -0.598
// -1
// 0
}
```
### <span id="Sin">Sin</span>
<p>Returns the sine of the radian argument.</p>
<b>Signature:</b>
```go
func Sin(radian float64, precision ...int) float64
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.Sin(0)
result2 := mathutil.Sin(90)
result3 := mathutil.Sin(180)
result4 := mathutil.Sin(math.Pi)
result5 := mathutil.Sin(math.Pi / 2)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// 0
// 0.894
// -0.801
// 0
// 1
}
```
### <span id="Log">Log</span>
<p>Returns the logarithm of base n.</p>
<b>Signature:</b>
```go
func Log(n, base float64) float64
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.Log(8, 2)
result2 := mathutil.TruncRound(mathutil.Log(5, 2), 2)
result3 := mathutil.TruncRound(mathutil.Log(27, 3), 0)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 3
// 2.32
// 3
}
```
### <span id="Sum">Sum</span>
<p>Returns sum of passed numbers.</p>
<b>Signature:</b>
```go
func Sum[T constraints.Integer | constraints.Float](numbers ...T) T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.Sum(1, 2)
result2 := mathutil.Sum(0.1, float64(1))
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 3
// 1.1
}
```
### <span id="Abs">Abs</span>
<p>Returns the absolute value of x.</p>
<b>Signature:</b>
```go
func Abs[T constraints.Integer | constraints.Float](x T) T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := Abs(-1)
result2 := Abs(-0.1)
result3 := Abs(float32(0.2))
fmt.Println(result1)
fmt.Println(result2)
@@ -783,7 +977,7 @@ func main() {
// Output:
// 1
// 2
// 18
// 0.1
// 0.2
}
```

View File

@@ -42,6 +42,11 @@ import (
- [IsPrime](#IsPrime)
- [GCD](#GCD)
- [LCM](#LCM)
- [Cos](#Cos)
- [Sin](#Sin)
- [Log](#Log)
- [Sum](#Sum)
- [Abs](#Abs)
<div STYLE="page-break-after: always;"></div>
@@ -365,18 +370,18 @@ import (
)
func main() {
result1 := Percent(1, 2, 2)
result2 := Percent(0.1, 0.3, 2)
result3 := Percent(-30305, 408420, 2)
result1 := mathutil.Percent(1, 2, 2)
result2 := mathutil.Percent(0.1, 0.3, 2)
result3 := mathutil.Percent(-30305, 408420, 2)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 50
// 33.33
// -7.42
// Output:
// 50
// 33.33
// -7.42
}
```
@@ -668,8 +673,6 @@ func main() {
}
```
### <span id="IsPrime">IsPrime</span>
<p>判断质数。</p>
@@ -692,20 +695,20 @@ import (
func main() {
result1 := mathutil.IsPrime(-1)
result2 := mathutil.IsPrime(0)
result3 := mathutil.IsPrime(1)
result4 := mathutil.IsPrime(2)
result2 := mathutil.IsPrime(0)
result3 := mathutil.IsPrime(1)
result4 := mathutil.IsPrime(2)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// false
// false
// false
// true
// Output:
// false
// false
// false
// true
}
```
@@ -731,27 +734,26 @@ import (
func main() {
result1 := mathutil.GCD(1, 1)
result2 := mathutil.GCD(1, -1)
result3 := mathutil.GCD(-1, 1)
result4 := mathutil.GCD(-1, -1)
result5 := mathutil.GCD(3, 6, 9)
result2 := mathutil.GCD(1, -1)
result3 := mathutil.GCD(-1, 1)
result4 := mathutil.GCD(-1, -1)
result5 := mathutil.GCD(3, 6, 9)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// 1
// 1
// -1
// -1
// 3
// Output:
// 1
// 1
// -1
// -1
// 3
}
```
### <span id="LCM">LCM</span>
<p>计算最小公倍数。</p>
@@ -774,8 +776,197 @@ import (
func main() {
result1 := mathutil.LCM(1, 1)
result2 := mathutil.LCM(1, 2)
result3 := mathutil.LCM(3, 6, 9)
result2 := mathutil.LCM(1, 2)
result3 := mathutil.LCM(3, 6, 9)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 1
// 2
// 18
}
```
### <span id="Cos">Cos</span>
<p>计算弧度的余弦值</p>
<b>函数签名:</b>
```go
func Cos(radian float64, precision ...int) float64
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.Cos(0)
result2 := mathutil.Cos(90)
result3 := mathutil.Cos(180)
result4 := mathutil.Cos(math.Pi)
result5 := mathutil.Cos(math.Pi / 2)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// 1
// -0.447
// -0.598
// -1
// 0
}
```
### <span id="Sin">Sin</span>
<p>计算弧度的正弦值</p>
<b>函数签名:</b>
```go
func Sin(radian float64, precision ...int) float64
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.Sin(0)
result2 := mathutil.Sin(90)
result3 := mathutil.Sin(180)
result4 := mathutil.Sin(math.Pi)
result5 := mathutil.Sin(math.Pi / 2)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// 0
// 0.894
// -0.801
// 0
// 1
}
```
### <span id="Log">Log</span>
<p>计算以base为底n的对数。</p>
<b>函数签名:</b>
```go
func Log(n, base float64) float64
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.Log(8, 2)
result2 := mathutil.TruncRound(mathutil.Log(5, 2), 2)
result3 := mathutil.TruncRound(mathutil.Log(27, 3), 0)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 3
// 2.32
// 3
}
```
### <span id="Sum">Sum</span>
<p>求传入参数之和。</p>
<b>函数签名:</b>
```go
func Sum[T constraints.Integer | constraints.Float](numbers ...T) T
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := mathutil.Sum(1, 2)
result2 := mathutil.Sum(0.1, float64(1))
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 3
// 1.1
}
```
### <span id="Abs">Abs</span>
<p>求绝对值。</p>
<b>函数签名:</b>
```go
func Abs[T constraints.Integer | constraints.Float](x T) T
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/mathutil"
)
func main() {
result1 := Abs(-1)
result2 := Abs(-0.1)
result3 := Abs(float32(0.2))
fmt.Println(result1)
fmt.Println(result2)
@@ -783,7 +974,7 @@ func main() {
// Output:
// 1
// 2
// 18
// 0.1
// 0.2
}
```
```

View File

@@ -620,9 +620,9 @@ func main() {
}
```
### <span id="HttpGet">HttpGet (Deprecated: use SendRequest for replacement)</span>
### <span id="HttpGet">HttpGet</span>
<p>Send http get request.</p>
<p>Send http get request. (Deprecated: use SendRequest for replacement)</p>
<b>Signature:</b>
@@ -662,9 +662,9 @@ func main() {
}
```
### <span id="HttpPost">HttpPost (Deprecated: use SendRequest for replacement)</span>
### <span id="HttpPost">HttpPost</span>
<p>Send http post request.</p>
<p>Send http post request.(Deprecated: use SendRequest for replacement)</p>
<b>Signature:</b>
@@ -692,16 +692,14 @@ import (
func main() {
url := "https://jsonplaceholder.typicode.com/todos"
header := map[string]string{
"Content-Type": "application/json",
"Content-Type": "application/x-www-form-urlencoded",
}
type Todo struct {
UserId int `json:"userId"`
Title string `json:"title"`
}
todo := Todo{1, "TestAddToDo"}
bodyParams, _ := json.Marshal(todo)
resp, err := netutil.HttpPost(url, header, nil, bodyParams)
postData := url.Values{}
postData.Add("userId", "1")
postData.Add("title", "TestToDo")
resp, err := netutil.HttpPost(apiUrl, header, nil, postData)
if err != nil {
log.Fatal(err)
}
@@ -711,9 +709,9 @@ func main() {
}
```
### <span id="HttpPut">HttpPut (Deprecated: use SendRequest for replacement)</span>
### <span id="HttpPut">HttpPut</span>
<p>Send http put request.</p>
<p>Send http put request. (Deprecated: use SendRequest for replacement)</p>
<b>Signature:</b>
@@ -761,9 +759,9 @@ func main() {
}
```
### <span id="HttpDelete">HttpDelete (Deprecated: use SendRequest for replacement)</span>
### <span id="HttpDelete">HttpDelete</span>
<p>Send http delete request.</p>
<p>Send http delete request. (Deprecated: use SendRequest for replacement)</p>
<b>Signature:</b>
@@ -800,9 +798,9 @@ func main() {
}
```
### <span id="HttpPatch">HttpPatch (Deprecated: use SendRequest for replacement)</span>
### <span id="HttpPatch">HttpPatch</span>
<p>Send http patch request.</p>
<p>Send http patch request. (Deprecated: use SendRequest for replacement)</p>
<b>Signature:</b>

View File

@@ -622,9 +622,9 @@ func main() {
}
```
### <span id="HttpGet">HttpGet (Deprecated: use SendRequest for replacement)</span>
### <span id="HttpGet">HttpGet</span>
<p>发送http get请求</p>
<p>发送http get请求。(已废弃:使用SendRequest)</p>
<b>函数签名:</b>
@@ -664,9 +664,9 @@ func main() {
}
```
### <span id="HttpPost">HttpPost (Deprecated: use SendRequest for replacement)</span>
### <span id="HttpPost">HttpPost</span>
<p>发送http post请求</p>
<p>发送http post请求。(已废弃:使用SendRequest)</p>
<b>函数签名:</b>
@@ -694,16 +694,14 @@ import (
func main() {
url := "https://jsonplaceholder.typicode.com/todos"
header := map[string]string{
"Content-Type": "application/json",
"Content-Type": "application/x-www-form-urlencoded",
}
type Todo struct {
UserId int `json:"userId"`
Title string `json:"title"`
}
todo := Todo{1, "TestAddToDo"}
bodyParams, _ := json.Marshal(todo)
resp, err := netutil.HttpPost(url, header, nil, bodyParams)
postData := url.Values{}
postData.Add("userId", "1")
postData.Add("title", "TestToDo")
resp, err := netutil.HttpPost(apiUrl, header, nil, postData)
if err != nil {
log.Fatal(err)
}
@@ -713,9 +711,9 @@ func main() {
}
```
### <span id="HttpPut">HttpPut (Deprecated: use SendRequest for replacement)</span>
### <span id="HttpPut">HttpPut</span>
<p>发送http put请求</p>
<p>发送http put请求。(已废弃:使用SendRequest)</p>
<b>函数签名:</b>
@@ -763,9 +761,9 @@ func main() {
}
```
### <span id="HttpDelete">HttpDelete (Deprecated: use SendRequest for replacement)</span>
### <span id="HttpDelete">HttpDelete</span>
<p>发送http delete请求</p>
<p>发送http delete请求。(已废弃:使用SendRequest)</p>
<b>函数签名:</b>
@@ -802,9 +800,9 @@ func main() {
}
```
### <span id="HttpPatch">HttpPatch (Deprecated: use SendRequest for replacement)</span>
### <span id="HttpPatch">HttpPatch</span>
<p>发送http patch请求</p>
<p>发送http patch请求。(已废弃:使用SendRequest)</p>
<b>函数签名:</b>

136
docs/pointer.md Normal file
View File

@@ -0,0 +1,136 @@
# Pointer
pointer contains some util functions to operate go pointer.
<div STYLE="page-break-after: always;"></div>
## Source:
- [https://github.com/duke-git/lancet/blob/main/pointer/pointer.go](https://github.com/duke-git/lancet/blob/main/pointer/pointer.go)
<div STYLE="page-break-after: always;"></div>
## Usage:
```go
import (
"github.com/duke-git/lancet/v2/pointer"
)
```
<div STYLE="page-break-after: always;"></div>
## Index
- [Of](#Of)
- [Unwrap](#Unwrap)
- [ExtractPointer](#ExtractPointer)
<div STYLE="page-break-after: always;"></div>
## Documentation
### <span id="Of">Of</span>
<p>Returns a pointer to the pass value `v`.</p>
<b>Signature:</b>
```go
func Of[T any](v T) *T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/pointer"
)
func main() {
result1 := pointer.Of(123)
result2 := pointer.Of("abc")
fmt.Println(*result1)
fmt.Println(*result2)
// Output:
// 123
// abc
}
```
### <span id="Unwrap">Unwrap</span>
<p>Returns the value from the pointer.</p>
<b>Signature:</b>
```go
func Unwrap[T any](p *T) T
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/pointer"
)
func main() {
a := 123
b := "abc"
result1 := pointer.Unwrap(&a)
result2 := pointer.Unwrap(&b)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 123
// abc
}
```
### <span id="ExtractPointer">ExtractPointer</span>
<p>Returns the underlying value by the given interface type</p>
<b>Signature:</b>
```go
func ExtractPointer(value any) any
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/pointer"
)
func main() {
a := 1
b := &a
c := &b
d := &c
result := pointer.ExtractPointer(d)
fmt.Println(result)
// Output:
// 1
}
```

136
docs/pointer_zh-CN.md Normal file
View File

@@ -0,0 +1,136 @@
# Pointer
pointer包支持一些指针类型的操作。
<div STYLE="page-break-after: always;"></div>
## 源码:
- [https://github.com/duke-git/lancet/blob/main/pointer/pointer.go](https://github.com/duke-git/lancet/blob/main/pointer/pointer.go)
<div STYLE="page-break-after: always;"></div>
## 用法:
```go
import (
"github.com/duke-git/lancet/v2/pointer"
)
```
<div STYLE="page-break-after: always;"></div>
## 目录
- [Of](#Of)
- [Unwrap](#Unwrap)
- [ExtractPointer](#ExtractPointer)
<div STYLE="page-break-after: always;"></div>
## 文档
### <span id="Of">Of</span>
<p>返回传入参数的指针值。</p>
<b>函数签名:</b>
```go
func Of[T any](v T) *T
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/pointer"
)
func main() {
result1 := pointer.Of(123)
result2 := pointer.Of("abc")
fmt.Println(*result1)
fmt.Println(*result2)
// Output:
// 123
// abc
}
```
### <span id="Unwrap">Unwrap</span>
<p>返回传入指针指向的值。</p>
<b>函数签名:</b>
```go
func Unwrap[T any](p *T) T
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/pointer"
)
func main() {
a := 123
b := "abc"
result1 := pointer.Unwrap(&a)
result2 := pointer.Unwrap(&b)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 123
// abc
}
```
### <span id="ExtractPointer">ExtractPointer</span>
<p>返回传入interface的底层值。</p>
<b>函数签名:</b>
```go
func ExtractPointer(value any) any
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/pointer"
)
func main() {
a := 1
b := &a
c := &b
d := &c
result := pointer.ExtractPointer(d)
fmt.Println(result)
// Output:
// 1
}
```

View File

@@ -30,6 +30,7 @@ import (
- [RandNumeral](#RandNumeral)
- [RandNumeralOrLetter](#RandNumeralOrLetter)
- [UUIdV4](#UUIdV4)
- [RandUniqueIntSlice](#RandUniqueIntSlice)
<div STYLE="page-break-after: always;"></div>
@@ -245,3 +246,30 @@ func main() {
fmt.Println(uuid)
}
```
### <span id="RandUniqueIntSlice">RandUniqueIntSlice</span>
<p>Generate a slice of random int of length n that do not repeat.</p>
<b>Signature:</b>
```go
func RandUniqueIntSlice(n, min, max int) []int
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/random"
)
func main() {
result := random.RandUniqueIntSlice(5, 0, 10)
fmt.Println(result) //[0 4 7 1 5] (random)
}
```

View File

@@ -30,6 +30,7 @@ import (
- [RandNumeral](#RandNumeral)
- [RandNumeralOrLetter](#RandNumeralOrLetter)
- [UUIdV4](#UUIdV4)
- [RandUniqueIntSlice](#RandUniqueIntSlice)
<div STYLE="page-break-after: always;"></div>
@@ -245,3 +246,29 @@ func main() {
fmt.Println(uuid)
}
```
### <span id="RandUniqueIntSlice">RandUniqueIntSlice</span>
<p>生成一个不重复的长度为n的随机int切片。</p>
<b>函数签名:</b>
```go
func RandUniqueIntSlice(n, min, max int) []int
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/random"
)
func main() {
result := random.RandUniqueIntSlice(5, 0, 10)
fmt.Println(result) //[0 4 7 1 5] (random)
}
```

View File

@@ -896,18 +896,18 @@ import (
func main() {
nums := []int{1, 2, 3, 4, 5}
isEven := func(i, num int) bool {
return num%2 == 0
}
isEven := func(i, num int) bool {
return num%2 == 0
}
result, ok := slice.FindBy(nums, isEven)
result, ok := slice.FindBy(nums, isEven)
fmt.Println(result)
fmt.Println(ok)
fmt.Println(result)
fmt.Println(ok)
// Output:
// 2
// true
// Output:
// 2
// true
}
```
@@ -968,18 +968,18 @@ import (
func main() {
nums := []int{1, 2, 3, 4, 5}
isEven := func(i, num int) bool {
return num%2 == 0
}
isEven := func(i, num int) bool {
return num%2 == 0
}
result, ok := slice.FindLastBy(nums, isEven)
result, ok := slice.FindLastBy(nums, isEven)
fmt.Println(result)
fmt.Println(ok)
fmt.Println(result)
fmt.Println(ok)
// Output:
// 4
// true
// Output:
// 4
// true
}
```

View File

@@ -897,18 +897,18 @@ import (
func main() {
nums := []int{1, 2, 3, 4, 5}
isEven := func(i, num int) bool {
return num%2 == 0
}
isEven := func(i, num int) bool {
return num%2 == 0
}
result, ok := slice.FindBy(nums, isEven)
result, ok := slice.FindBy(nums, isEven)
fmt.Println(result)
fmt.Println(ok)
fmt.Println(result)
fmt.Println(ok)
// Output:
// 2
// true
// Output:
// 2
// true
}
```
@@ -969,18 +969,18 @@ import (
func main() {
nums := []int{1, 2, 3, 4, 5}
isEven := func(i, num int) bool {
return num%2 == 0
}
isEven := func(i, num int) bool {
return num%2 == 0
}
result, ok := slice.FindLastBy(nums, isEven)
result, ok := slice.FindLastBy(nums, isEven)
fmt.Println(result)
fmt.Println(ok)
fmt.Println(result)
fmt.Println(ok)
// Output:
// 4
// true
// Output:
// 4
// true
}
```

View File

@@ -687,16 +687,16 @@ import (
)
func main() {
original := FromSlice([]int{3, 2, 1})
original := stream.FromSlice([]int{3, 2, 1})
result, ok := original.FindLast()
result, ok := original.FindLast()
fmt.Println(result)
fmt.Println(ok)
fmt.Println(result)
fmt.Println(ok)
// Output:
// 1
// true
// Output:
// 1
// true
}
```

View File

@@ -687,16 +687,16 @@ import (
)
func main() {
original := FromSlice([]int{3, 2, 1})
original := stream.FromSlice([]int{3, 2, 1})
result, ok := original.FindLast()
result, ok := original.FindLast()
fmt.Println(result)
fmt.Println(ok)
fmt.Println(result)
fmt.Println(ok)
// Output:
// 1
// true
// Output:
// 1
// true
}
```

View File

@@ -21,6 +21,7 @@ import (
<div STYLE="page-break-after: always;"></div>
## Index:
- [Tag](#Tag)
- [Name](#Name)
- [Value](#Value)
@@ -57,24 +58,24 @@ func (f *Field) Tag() *Tag
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type Parent struct {
Name string `json:"name,omitempty"`
}
p1 := &Parent{"111"}
type Parent struct {
Name string `json:"name,omitempty"`
}
p1 := &Parent{"111"}
s := structs.New(p1)
n, _ := s.Field("Name")
tag := n.Tag()
s := structs.New(p1)
n, _ := s.Field("Name")
tag := n.Tag()
fmt.Println(tag.Name)
// Output:
// name
fmt.Println(tag.Name)
// Output:
// name
}
```
@@ -94,23 +95,23 @@ func (f *Field) Value() any
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type Parent struct {
Name string `json:"name,omitempty"`
}
p1 := &Parent{"111"}
type Parent struct {
Name string `json:"name,omitempty"`
}
p1 := &Parent{"111"}
s := structs.New(p1)
n, _ := s.Field("Name")
fmt.Println(n.Value())
// Output:
// 111
s := structs.New(p1)
n, _ := s.Field("Name")
fmt.Println(n.Value())
// Output:
// 111
}
```
@@ -130,32 +131,32 @@ func (f *Field) IsEmbedded() bool
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type Parent struct {
Name string
}
type Child struct {
Parent
Age int
}
c1 := &Child{}
c1.Name = "111"
c1.Age = 11
type Parent struct {
Name string
}
type Child struct {
Parent
Age int
}
c1 := &Child{}
c1.Name = "111"
c1.Age = 11
s := structs.New(c1)
n, _ := s.Field("Name")
a, _ := s.Field("Age")
fmt.Println(n.IsEmbedded())
fmt.Println(a.IsEmbedded())
// Output:
// true
// false
s := structs.New(c1)
n, _ := s.Field("Name")
a, _ := s.Field("Age")
fmt.Println(n.IsEmbedded())
fmt.Println(a.IsEmbedded())
// Output:
// true
// false
}
```
@@ -175,26 +176,26 @@ func (f *Field) IsExported() bool
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type Parent struct {
Name string
age int
}
p1 := &Parent{Name: "11", age: 11}
s := structs.New(p1)
n, _ := s.Field("Name")
a, _ := s.Field("age")
fmt.Println(n.IsExported())
fmt.Println(a.IsExported())
// Output:
// true
// false
type Parent struct {
Name string
age int
}
p1 := &Parent{Name: "11", age: 11}
s := structs.New(p1)
n, _ := s.Field("Name")
a, _ := s.Field("age")
fmt.Println(n.IsExported())
fmt.Println(a.IsExported())
// Output:
// true
// false
}
```
@@ -214,26 +215,26 @@ func (f *Field) IsZero() bool
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type Parent struct {
Name string
Age int
}
p1 := &Parent{Age: 11}
s := structs.New(p1)
n, _ := s.Field("Name")
a, _ := s.Field("Age")
fmt.Println(n.IsZero())
fmt.Println(a.IsZero())
// Output:
// true
// false
type Parent struct {
Name string
Age int
}
p1 := &Parent{Age: 11}
s := structs.New(p1)
n, _ := s.Field("Name")
a, _ := s.Field("Age")
fmt.Println(n.IsZero())
fmt.Println(a.IsZero())
// Output:
// true
// false
}
```
@@ -253,26 +254,26 @@ func (f *Field) Name() string
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type Parent struct {
Name string
Age int
}
p1 := &Parent{Age: 11}
s := structs.New(p1)
n, _ := s.Field("Name")
a, _ := s.Field("Age")
fmt.Println(n.Name())
fmt.Println(a.Name())
// Output:
// Name
// Age
type Parent struct {
Name string
Age int
}
p1 := &Parent{Age: 11}
s := structs.New(p1)
n, _ := s.Field("Name")
a, _ := s.Field("Age")
fmt.Println(n.Name())
fmt.Println(a.Name())
// Output:
// Name
// Age
}
```
@@ -292,26 +293,26 @@ func (f *Field) Kind() reflect.Kind
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type Parent struct {
Name string
Age int
}
p1 := &Parent{Age: 11}
s := structs.New(p1)
n, _ := s.Field("Name")
a, _ := s.Field("Age")
fmt.Println(n.Kind())
fmt.Println(a.Kind())
// Output:
// string
// int
type Parent struct {
Name string
Age int
}
p1 := &Parent{Age: 11}
s := structs.New(p1)
n, _ := s.Field("Name")
a, _ := s.Field("Age")
fmt.Println(n.Kind())
fmt.Println(a.Kind())
// Output:
// string
// int
}
```
@@ -331,23 +332,23 @@ func (f *Field) IsSlice() bool
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type Parent struct {
Name string
arr []int
}
type Parent struct {
Name string
arr []int
}
p1 := &Parent{arr: []int{1, 2, 3}}
s := structs.New(p1)
a, _ := s.Field("arr")
fmt.Println(a.IsSlice())
// Output:
// true
p1 := &Parent{arr: []int{1, 2, 3}}
s := structs.New(p1)
a, _ := s.Field("arr")
fmt.Println(a.IsSlice())
// Output:
// true
}
```
```

View File

@@ -57,24 +57,24 @@ func (f *Field) Tag() *Tag
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type Parent struct {
Name string `json:"name,omitempty"`
}
p1 := &Parent{"111"}
type Parent struct {
Name string `json:"name,omitempty"`
}
p1 := &Parent{"111"}
s := structs.New(p1)
n, _ := s.Field("Name")
tag := n.Tag()
s := structs.New(p1)
n, _ := s.Field("Name")
tag := n.Tag()
fmt.Println(tag.Name)
// Output:
// name
fmt.Println(tag.Name)
// Output:
// name
}
```
@@ -94,23 +94,23 @@ func (f *Field) Value() any
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type Parent struct {
Name string `json:"name,omitempty"`
}
p1 := &Parent{"111"}
type Parent struct {
Name string `json:"name,omitempty"`
}
p1 := &Parent{"111"}
s := structs.New(p1)
n, _ := s.Field("Name")
fmt.Println(n.Value())
// Output:
// 111
s := structs.New(p1)
n, _ := s.Field("Name")
fmt.Println(n.Value())
// Output:
// 111
}
```
@@ -130,32 +130,32 @@ func (f *Field) IsEmbedded() bool
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type Parent struct {
Name string
}
type Child struct {
Parent
Age int
}
c1 := &Child{}
c1.Name = "111"
c1.Age = 11
type Parent struct {
Name string
}
type Child struct {
Parent
Age int
}
c1 := &Child{}
c1.Name = "111"
c1.Age = 11
s := structs.New(c1)
n, _ := s.Field("Name")
a, _ := s.Field("Age")
fmt.Println(n.IsEmbedded())
fmt.Println(a.IsEmbedded())
// Output:
// true
// false
s := structs.New(c1)
n, _ := s.Field("Name")
a, _ := s.Field("Age")
fmt.Println(n.IsEmbedded())
fmt.Println(a.IsEmbedded())
// Output:
// true
// false
}
```
@@ -175,26 +175,26 @@ func (f *Field) IsExported() bool
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type Parent struct {
Name string
age int
}
p1 := &Parent{Name: "11", age: 11}
s := structs.New(p1)
n, _ := s.Field("Name")
a, _ := s.Field("age")
fmt.Println(n.IsExported())
fmt.Println(a.IsExported())
// Output:
// true
// false
type Parent struct {
Name string
age int
}
p1 := &Parent{Name: "11", age: 11}
s := structs.New(p1)
n, _ := s.Field("Name")
a, _ := s.Field("age")
fmt.Println(n.IsExported())
fmt.Println(a.IsExported())
// Output:
// true
// false
}
```
@@ -214,26 +214,26 @@ func (f *Field) IsZero() bool
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type Parent struct {
Name string
Age int
}
p1 := &Parent{Age: 11}
s := structs.New(p1)
n, _ := s.Field("Name")
a, _ := s.Field("Age")
fmt.Println(n.IsZero())
fmt.Println(a.IsZero())
// Output:
// true
// false
type Parent struct {
Name string
Age int
}
p1 := &Parent{Age: 11}
s := structs.New(p1)
n, _ := s.Field("Name")
a, _ := s.Field("Age")
fmt.Println(n.IsZero())
fmt.Println(a.IsZero())
// Output:
// true
// false
}
```
@@ -253,26 +253,26 @@ func (f *Field) Name() string
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type Parent struct {
Name string
Age int
}
p1 := &Parent{Age: 11}
s := structs.New(p1)
n, _ := s.Field("Name")
a, _ := s.Field("Age")
fmt.Println(n.Name())
fmt.Println(a.Name())
// Output:
// Name
// Age
type Parent struct {
Name string
Age int
}
p1 := &Parent{Age: 11}
s := structs.New(p1)
n, _ := s.Field("Name")
a, _ := s.Field("Age")
fmt.Println(n.Name())
fmt.Println(a.Name())
// Output:
// Name
// Age
}
```
@@ -292,26 +292,26 @@ func (f *Field) Kind() reflect.Kind
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type Parent struct {
Name string
Age int
}
p1 := &Parent{Age: 11}
s := structs.New(p1)
n, _ := s.Field("Name")
a, _ := s.Field("Age")
fmt.Println(n.Kind())
fmt.Println(a.Kind())
// Output:
// string
// int
type Parent struct {
Name string
Age int
}
p1 := &Parent{Age: 11}
s := structs.New(p1)
n, _ := s.Field("Name")
a, _ := s.Field("Age")
fmt.Println(n.Kind())
fmt.Println(a.Kind())
// Output:
// string
// int
}
```
@@ -331,23 +331,23 @@ func (f *Field) IsSlice() bool
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type Parent struct {
Name string
arr []int
}
type Parent struct {
Name string
arr []int
}
p1 := &Parent{arr: []int{1, 2, 3}}
s := structs.New(p1)
a, _ := s.Field("arr")
fmt.Println(a.IsSlice())
// Output:
// true
p1 := &Parent{arr: []int{1, 2, 3}}
s := structs.New(p1)
a, _ := s.Field("arr")
fmt.Println(a.IsSlice())
// Output:
// true
}
```

View File

@@ -21,6 +21,7 @@ import (
<div STYLE="page-break-after: always;"></div>
## Index:
- [New](#New)
- [ToMap](#ToMap)
- [Fields](#Fields)
@@ -47,16 +48,16 @@ func New(value any, tagName ...string) *Struct
package main
import (
"github.com/duke-git/lancet/v2/structs"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type People struct {
Name string `json:"name"`
}
p1 := &People{Name: "11"}
s := structs.New(p1)
// to do something
type People struct {
Name string `json:"name"`
}
p1 := &People{Name: "11"}
s := structs.New(p1)
// to do something
}
```
@@ -82,29 +83,29 @@ func ToMap(v any) (map[string]any, error)
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type People struct {
Name string `json:"name"`
}
p1 := &People{Name: "11"}
// use constructor function
s1 := structs.New(p1)
m1, _ := s1.ToMap()
type People struct {
Name string `json:"name"`
}
p1 := &People{Name: "11"}
// use constructor function
s1 := structs.New(p1)
m1, _ := s1.ToMap()
fmt.Println(m1)
// use static function
m2, _ := structs.ToMap(p1)
fmt.Println(m2)
// Output:
// map[name:11]
// map[name:11]
fmt.Println(m1)
// use static function
m2, _ := structs.ToMap(p1)
fmt.Println(m2)
// Output:
// map[name:11]
// map[name:11]
}
```
@@ -124,22 +125,22 @@ func (s *Struct) Fields() []*Field
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type People struct {
Name string `json:"name"`
}
p1 := &People{Name: "11"}
s := structs.New(p1)
fields := s.Fields()
type People struct {
Name string `json:"name"`
}
p1 := &People{Name: "11"}
s := structs.New(p1)
fields := s.Fields()
fmt.Println(len(fields))
// Output:
// 1
fmt.Println(len(fields))
// Output:
// 1
}
```
@@ -159,22 +160,22 @@ func (s *Struct) Field(name string) *Field
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type People struct {
Name string `json:"name"`
}
p1 := &People{Name: "11"}
s := structs.New(p1)
f := s.Field("Name")
type People struct {
Name string `json:"name"`
}
p1 := &People{Name: "11"}
s := structs.New(p1)
f := s.Field("Name")
fmt.Println(f.Value())
// Output:
// 11
fmt.Println(f.Value())
// Output:
// 11
}
```
@@ -194,20 +195,20 @@ func (s *Struct) IsStruct() bool
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type People struct {
Name string `json:"name"`
}
p1 := &People{Name: "11"}
s := structs.New(p1)
type People struct {
Name string `json:"name"`
}
p1 := &People{Name: "11"}
s := structs.New(p1)
fmt.Println(s.IsStruct())
// Output:
// true
fmt.Println(s.IsStruct())
// Output:
// true
}
```

View File

@@ -21,6 +21,7 @@ import (
<div STYLE="page-break-after: always;"></div>
## 目录:
- [New](#New)
- [ToMap](#ToMap)
- [Fields](#Fields)
@@ -47,16 +48,16 @@ func New(value any, tagName ...string) *Struct
package main
import (
"github.com/duke-git/lancet/v2/structs"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type People struct {
Name string `json:"name"`
}
p1 := &People{Name: "11"}
s := structs.New(p1)
// to do something
type People struct {
Name string `json:"name"`
}
p1 := &People{Name: "11"}
s := structs.New(p1)
// to do something
}
```
@@ -70,7 +71,7 @@ func main() {
func (s *Struct) ToMap() (map[string]any, error)
```
<b>除此之外提供一个便捷的静态方法ToMap</b>
<b>除此之外,提供一个便捷的静态方法 ToMap</b>
```go
func ToMap(v any) (map[string]any, error)
@@ -82,28 +83,28 @@ func ToMap(v any) (map[string]any, error)
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type People struct {
Name string `json:"name"`
}
p1 := &People{Name: "11"}
s1 := structs.New(p1)
m1, _ := s1.ToMap()
type People struct {
Name string `json:"name"`
}
p1 := &People{Name: "11"}
s1 := structs.New(p1)
m1, _ := s1.ToMap()
fmt.Println(m1)
// 如果不需要Struct更多的方法可以直接使用ToMap
m2, _ := structs.ToMap(p1)
fmt.Println(m2)
// Output:
// map[name:11]
// map[name:11]
fmt.Println(m1)
// 如果不需要Struct更多的方法可以直接使用ToMap
m2, _ := structs.ToMap(p1)
fmt.Println(m2)
// Output:
// map[name:11]
// map[name:11]
}
```
@@ -123,22 +124,22 @@ func (s *Struct) Fields() []*Field
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type People struct {
Name string `json:"name"`
}
p1 := &People{Name: "11"}
s := structs.New(p1)
fields := s.Fields()
type People struct {
Name string `json:"name"`
}
p1 := &People{Name: "11"}
s := structs.New(p1)
fields := s.Fields()
fmt.Println(len(fields))
// Output:
// 1
fmt.Println(len(fields))
// Output:
// 1
}
```
@@ -158,22 +159,22 @@ func (s *Struct) Field(name string) *Field
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type People struct {
Name string `json:"name"`
}
p1 := &People{Name: "11"}
s := structs.New(p1)
f := s.Field("Name")
type People struct {
Name string `json:"name"`
}
p1 := &People{Name: "11"}
s := structs.New(p1)
f := s.Field("Name")
fmt.Println(f.Value())
// Output:
// 11
fmt.Println(f.Value())
// Output:
// 11
}
```
@@ -193,20 +194,20 @@ func (s *Struct) IsStruct() bool
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/structs"
"fmt"
"github.com/duke-git/lancet/v2/structs"
)
func main() {
type People struct {
Name string `json:"name"`
}
p1 := &People{Name: "11"}
s := structs.New(p1)
type People struct {
Name string `json:"name"`
}
p1 := &People{Name: "11"}
s := structs.New(p1)
fmt.Println(s.IsStruct())
// Output:
// true
fmt.Println(s.IsStruct())
// Output:
// true
}
```

View File

@@ -55,6 +55,10 @@ import (
- [ReplaceWithMap](#ReplaceWithMap)
- [Trim](#Trim)
- [SplitAndTrim](#SplitAndTrim)
- [HideString](#HideString)
- [ContainsAll](#ContainsAll)
- [ContainsAny](#ContainsAny)
- [RemoveWhiteSpace](#RemoveWhiteSpace)
<div STYLE="page-break-after: always;"></div>
@@ -998,14 +1002,14 @@ import (
func main() {
result1 := strutil.StringToBytes("abc")
result2 := reflect.DeepEqual(result1, []byte{'a', 'b', 'c'})
result2 := reflect.DeepEqual(result1, []byte{'a', 'b', 'c'})
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// [97 98 99]
// true
// Output:
// [97 98 99]
// true
}
```
@@ -1029,12 +1033,12 @@ import (
func main() {
bytes := []byte{'a', 'b', 'c'}
result := strutil.BytesToString(bytes)
result := strutil.BytesToString(bytes)
fmt.Println(result)
fmt.Println(result)
// Output:
// abc
// Output:
// abc
}
```
@@ -1058,17 +1062,17 @@ import (
func main() {
result1 := strutil.IsBlank("")
result2 := strutil.IsBlank("\t\v\f\n")
result3 := strutil.IsBlank(" 中文")
result2 := strutil.IsBlank("\t\v\f\n")
result3 := strutil.IsBlank(" 中文")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// true
// true
// false
// Output:
// true
// true
// false
}
```
@@ -1092,14 +1096,14 @@ import (
func main() {
result1 := strutil.HasPrefixAny("foo bar", []string{"fo", "xyz", "hello"})
result2 := strutil.HasPrefixAny("foo bar", []string{"oom", "world"})
result2 := strutil.HasPrefixAny("foo bar", []string{"oom", "world"})
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
// Output:
// true
// false
}
```
@@ -1123,14 +1127,14 @@ import (
func main() {
result1 := strutil.HasSuffixAny("foo bar", []string{"bar", "xyz", "hello"})
result2 := strutil.HasSuffixAny("foo bar", []string{"oom", "world"})
result2 := strutil.HasSuffixAny("foo bar", []string{"oom", "world"})
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
// Output:
// true
// false
}
```
@@ -1155,24 +1159,24 @@ import (
func main() {
str := "foo bar hello world"
result1 := strutil.IndexOffset(str, "o", 5)
result2 := strutil.IndexOffset(str, "o", 0)
result3 := strutil.IndexOffset(str, "d", len(str)-1)
result4 := strutil.IndexOffset(str, "d", len(str))
result5 := strutil.IndexOffset(str, "f", -1)
result1 := strutil.IndexOffset(str, "o", 5)
result2 := strutil.IndexOffset(str, "o", 0)
result3 := strutil.IndexOffset(str, "d", len(str)-1)
result4 := strutil.IndexOffset(str, "d", len(str))
result5 := strutil.IndexOffset(str, "f", -1)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// 12
// 1
// 18
// -1
// -1
// Output:
// 12
// 1
// 18
// -1
// -1
}
```
@@ -1196,16 +1200,16 @@ import (
func main() {
str := "ac ab ab ac"
replaces := map[string]string{
"a": "1",
"b": "2",
}
replaces := map[string]string{
"a": "1",
"b": "2",
}
result := strutil.ReplaceWithMap(str, replaces)
result := strutil.ReplaceWithMap(str, replaces)
fmt.Println(result)
// Output:
// 1c 12 12 1c
fmt.Println(result)
// Output:
// 1c 12 12 1c
}
```
@@ -1230,23 +1234,22 @@ import (
func main() {
result1 := strutil.Trim("\nabcd")
str := "$ ab cd $ "
str := "$ ab cd $ "
result2 := strutil.Trim(str)
result3 := strutil.Trim(str, "$")
result2 := strutil.Trim(str)
result3 := strutil.Trim(str, "$")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// abcd
// $ ab cd $
// ab cd
// Output:
// abcd
// $ ab cd $
// ab cd
}
```
### <span id="SplitAndTrim">SplitAndTrim</span>
<p>Splits string `str` by a string `delimiter` to a slice, and calls Trim to every element of slice. It ignores the elements which are empty after Trim.</p>
@@ -1268,14 +1271,155 @@ import (
func main() {
str := " a,b, c,d,$1 "
result1 := strutil.SplitAndTrim(str, ",")
result2 := strutil.SplitAndTrim(str, ",", "$")
result1 := strutil.SplitAndTrim(str, ",")
result2 := strutil.SplitAndTrim(str, ",", "$")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// [a b c d $1]
// [a b c d 1]
// Output:
// [a b c d $1]
// [a b c d 1]
}
```
### <span id="HideString">HideString</span>
<p>Hide some chars in source string with param `replaceChar`. replace range is origin[start : end]. [start, end).</p>
<b>Signature:</b>
```go
func HideString(origin string, start, end int, replaceChar string) string
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
str := "13242658976"
result1 := strutil.HideString(str, 3, 3, "*")
result2 := strutil.HideString(str, 3, 4, "*")
result3 := strutil.HideString(str, 3, 7, "*")
result4 := strutil.HideString(str, 7, 11, "*")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// 13242658976
// 132*2658976
// 132****8976
// 1324265****
}
```
### <span id="ContainsAll">ContainsAll</span>
<p>Return true if target string contains all the substrings.</p>
<b>Signature:</b>
```go
func ContainsAll(str string, substrs []string) bool
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
str := "hello world"
result1 := strutil.ContainsAll(str, []string{"hello", "world"})
result2 := strutil.ContainsAll(str, []string{"hello", "abc"})
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
```
### <span id="ContainsAny">ContainsAny</span>
<p>Return true if target string contains any one of the substrings.</p>
<b>Signature:</b>
```go
func ContainsAny(str string, substrs []string) bool
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
str := "hello world"
result1 := strutil.ContainsAny(str, []string{"hello", "world"})
result2 := strutil.ContainsAny(str, []string{"hello", "abc"})
result3 := strutil.ContainsAny(str, []string{"123", "abc"})
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// true
// true
// false
}
```
### <span id="RemoveWhiteSpace">RemoveWhiteSpace</span>
<p>Remove whitespace characters from a string. when set repalceAll is true removes all whitespace, false only replaces consecutive whitespace characters with one space.</p>
<b>Signature:</b>
```go
func RemoveWhiteSpace(str string, repalceAll bool) string
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
str := " hello \r\n \t world"
result1 := strutil.RemoveWhiteSpace(str, true)
result2 := strutil.RemoveWhiteSpace(str, false)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// helloworld
// hello world
}
```

View File

@@ -55,6 +55,10 @@ import (
- [ReplaceWithMap](#ReplaceWithMap)
- [Trim](#Trim)
- [SplitAndTrim](#SplitAndTrim)
- [HideString](#HideString)
- [ContainsAll](#ContainsAll)
- [ContainsAny](#ContainsAny)
- [RemoveWhiteSpace](#RemoveWhiteSpace)
<div STYLE="page-break-after: always;"></div>
@@ -971,7 +975,7 @@ func main() {
fmt.Println(result1)
fmt.Println(result2)
// Output:
// hello world
// 你好😄
@@ -998,13 +1002,13 @@ import (
func main() {
result1 := strutil.StringToBytes("abc")
result2 := reflect.DeepEqual(result1, []byte{'a', 'b', 'c'})
result2 := reflect.DeepEqual(result1, []byte{'a', 'b', 'c'})
fmt.Println(result1)
fmt.Println(result2)
// Output:
// [97 98 99]
// true
fmt.Println(result1)
fmt.Println(result2)
// Output:
// [97 98 99]
// true
}
```
@@ -1028,12 +1032,12 @@ import (
func main() {
bytes := []byte{'a', 'b', 'c'}
result := strutil.BytesToString(bytes)
result := strutil.BytesToString(bytes)
fmt.Println(result)
fmt.Println(result)
// Output:
// abc
// Output:
// abc
}
```
@@ -1057,17 +1061,17 @@ import (
func main() {
result1 := strutil.IsBlank("")
result2 := strutil.IsBlank("\t\v\f\n")
result3 := strutil.IsBlank(" 中文")
result2 := strutil.IsBlank("\t\v\f\n")
result3 := strutil.IsBlank(" 中文")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// true
// true
// false
// Output:
// true
// true
// false
}
```
@@ -1091,14 +1095,14 @@ import (
func main() {
result1 := strutil.HasPrefixAny("foo bar", []string{"fo", "xyz", "hello"})
result2 := strutil.HasPrefixAny("foo bar", []string{"oom", "world"})
result2 := strutil.HasPrefixAny("foo bar", []string{"oom", "world"})
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
// Output:
// true
// false
}
```
@@ -1122,14 +1126,14 @@ import (
func main() {
result1 := strutil.HasSuffixAny("foo bar", []string{"bar", "xyz", "hello"})
result2 := strutil.HasSuffixAny("foo bar", []string{"oom", "world"})
result2 := strutil.HasSuffixAny("foo bar", []string{"oom", "world"})
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
// Output:
// true
// false
}
```
@@ -1154,28 +1158,27 @@ import (
func main() {
str := "foo bar hello world"
result1 := strutil.IndexOffset(str, "o", 5)
result2 := strutil.IndexOffset(str, "o", 0)
result3 := strutil.IndexOffset(str, "d", len(str)-1)
result4 := strutil.IndexOffset(str, "d", len(str))
result5 := strutil.IndexOffset(str, "f", -1)
result1 := strutil.IndexOffset(str, "o", 5)
result2 := strutil.IndexOffset(str, "o", 0)
result3 := strutil.IndexOffset(str, "d", len(str)-1)
result4 := strutil.IndexOffset(str, "d", len(str))
result5 := strutil.IndexOffset(str, "f", -1)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// 12
// 1
// 18
// -1
// -1
// Output:
// 12
// 1
// 18
// -1
// -1
}
```
### <span id="ReplaceWithMap">ReplaceWithMap</span>
<p>返回`str`的副本以无序的方式被map替换区分大小写。</p>
@@ -1196,16 +1199,16 @@ import (
func main() {
str := "ac ab ab ac"
replaces := map[string]string{
"a": "1",
"b": "2",
}
replaces := map[string]string{
"a": "1",
"b": "2",
}
result := strutil.ReplaceWithMap(str, replaces)
result := strutil.ReplaceWithMap(str, replaces)
fmt.Println(result)
// Output:
// 1c 12 12 1c
fmt.Println(result)
// Output:
// 1c 12 12 1c
}
```
@@ -1230,23 +1233,22 @@ import (
func main() {
result1 := strutil.Trim("\nabcd")
str := "$ ab cd $ "
str := "$ ab cd $ "
result2 := strutil.Trim(str)
result3 := strutil.Trim(str, "$")
result2 := strutil.Trim(str)
result3 := strutil.Trim(str, "$")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// abcd
// $ ab cd $
// ab cd
// Output:
// abcd
// $ ab cd $
// ab cd
}
```
### <span id="SplitAndTrim">SplitAndTrim</span>
<p>将字符串str按字符串delimiter拆分为一个切片并对该数组的每个元素调用Trim。忽略Trim后为空的元素。</p>
@@ -1268,14 +1270,155 @@ import (
func main() {
str := " a,b, c,d,$1 "
result1 := strutil.SplitAndTrim(str, ",")
result2 := strutil.SplitAndTrim(str, ",", "$")
result1 := strutil.SplitAndTrim(str, ",")
result2 := strutil.SplitAndTrim(str, ",", "$")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// [a b c d $1]
// [a b c d 1]
// Output:
// [a b c d $1]
// [a b c d 1]
}
```
### <span id="HideString">HideString</span>
<p>使用参数`replaceChar`隐藏源字符串中的一些字符。替换范围是 origin[start : end]。</p>
<b>函数签名:</b>
```go
func HideString(origin string, start, end int, replaceChar string) string
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
str := "13242658976"
result1 := strutil.HideString(str, 3, 3, "*")
result2 := strutil.HideString(str, 3, 4, "*")
result3 := strutil.HideString(str, 3, 7, "*")
result4 := strutil.HideString(str, 7, 11, "*")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
// Output:
// 13242658976
// 132*2658976
// 132****8976
// 1324265****
}
```
### <span id="ContainsAll">ContainsAll</span>
<p>判断字符串是否包括全部给定的子字符串切片。</p>
<b>函数签名:</b>
```go
func ContainsAll(str string, substrs []string) bool
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
str := "hello world"
result1 := strutil.ContainsAll(str, []string{"hello", "world"})
result2 := strutil.ContainsAll(str, []string{"hello", "abc"})
fmt.Println(result1)
fmt.Println(result2)
// Output:
// true
// false
}
```
### <span id="ContainsAny">ContainsAny</span>
<p>判断字符串是否包括给定的子字符串切片中任意一个子字符串。</p>
<b>函数签名:</b>
```go
func ContainsAny(str string, substrs []string) bool
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
str := "hello world"
result1 := strutil.ContainsAny(str, []string{"hello", "world"})
result2 := strutil.ContainsAny(str, []string{"hello", "abc"})
result3 := strutil.ContainsAny(str, []string{"123", "abc"})
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// true
// true
// false
}
```
### <span id="RemoveWhiteSpace">RemoveWhiteSpace</span>
<p>删除字符串中的空格当设置repalceAll为true时删除全部空格为false时替换多个空格为1个空格。</p>
<b>函数签名:</b>
```go
func RemoveWhiteSpace(str string, repalceAll bool) string
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
str := " hello \r\n \t world"
result1 := strutil.RemoveWhiteSpace(str, true)
result2 := strutil.RemoveWhiteSpace(str, false)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// helloworld
// hello world
}
```

View File

@@ -34,19 +34,19 @@ import (
<div STYLE="page-break-after: always;"></div>
## Documentation 文档
## 文档
### <span id="IsWindows">IsWindows</span>
<p>检查当前操作系统是否是windows</p>
<b>Signature:</b>
<b>函数签名:</b>
```go
func IsWindows() bool
```
<b>Example:</b>
<b>示例:</b>
```go
import (
@@ -64,13 +64,13 @@ func main() {
<p>检查当前操作系统是否是linux</p>
<b>Signature:</b>
<b>函数签名:</b>
```go
func IsLinux() bool
```
<b>Example:</b>
<b>示例:</b>
```go
import (
@@ -88,13 +88,13 @@ func main() {
<p>检查当前操作系统是否是macos</p>
<b>Signature:</b>
<b>函数签名:</b>
```go
func IsMac() bool
```
<b>Example:</b>
<b>示例:</b>
```go
import (
@@ -112,13 +112,13 @@ func main() {
<p>获取key命名的环境变量的值</p>
<b>Signature:</b>
<b>函数签名:</b>
```go
func GetOsEnv(key string) string
```
<b>Example:</b>
<b>示例:</b>
```go
import (
@@ -142,13 +142,13 @@ func main() {
<p>设置由key命名的环境变量的值</p>
<b>Signature:</b>
<b>函数签名:</b>
```go
func SetOsEnv(key, value string) error
```
<b>Example:</b>
<b>示例:</b>
```go
import (
@@ -172,13 +172,13 @@ func main() {
<p>删除单个环境变量</p>
<b>Signature:</b>
<b>函数签名:</b>
```go
func RemoveOsEnv(key string) error
```
<b>Example:</b>
<b>示例:</b>
```go
import (
@@ -210,13 +210,13 @@ func main() {
<p>获取key命名的环境变量值并与compareEnv进行比较</p>
<b>Signature:</b>
<b>函数签名:</b>
```go
func CompareOsEnv(key, comparedEnv string) bool
```
<b>Example:</b>
<b>示例:</b>
```go
import (
@@ -243,7 +243,7 @@ func main() {
<p>执行shell命令返回命令的stdout和stderr字符串如果出现错误则返回错误。参数`command`是一个完整的命令字符串如ls-alinuxdirwindowsping 127.0.0.1。在linux中使用/bin/bash-c执行命令在windows中使用powershell.exe执行命令。</p>
<b>Signature:</b>
<b>函数签名:</b>
```go
type (
@@ -252,7 +252,7 @@ type (
func ExecCommand(command string, opts ...Option) (stdout, stderr string, err error)
```
<b>Example:</b>
<b>示例:</b>
```go
import (

1199
docs/tuple.md Normal file

File diff suppressed because it is too large Load Diff

1199
docs/tuple_zh-CN.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -208,7 +208,11 @@ func Zip(fpath string, destPath string) error {
archive := zip.NewWriter(zipFile)
defer archive.Close()
err = filepath.Walk(fpath, func(path string, info os.FileInfo, err error) error {
return addFileToArchive(fpath, archive)
}
func addFileToArchive(fpath string, archive *zip.Writer) error {
err := filepath.Walk(fpath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
@@ -224,32 +228,22 @@ func Zip(fpath string, destPath string) error {
header.Name += "/"
} else {
header.Method = zip.Deflate
}
writer, err := archive.CreateHeader(header)
if err != nil {
return err
}
if !info.IsDir() {
writer, err := archive.CreateHeader(header)
if err != nil {
return err
}
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
_, err = io.Copy(writer, file)
if err != nil {
if _, err := io.Copy(writer, file); err != nil {
return err
}
}
return nil
})
if err != nil {
return err
}
return nil
return err
}
// UnZip unzip the file and save it to destPath.
@@ -302,6 +296,64 @@ func UnZip(zipFile string, destPath string) error {
return nil
}
// ZipAppendEntry append a single file or directory by fpath to an existing zip file.
// Play: https://go.dev/play/p/cxvaT8TRNQp
func ZipAppendEntry(fpath string, destPath string) error {
tempFile, err := os.CreateTemp("", "temp.zip")
if err != nil {
return err
}
defer os.Remove(tempFile.Name())
zipReader, err := zip.OpenReader(destPath)
if err != nil {
return err
}
archive := zip.NewWriter(tempFile)
for _, zipItem := range zipReader.File {
zipItemReader, err := zipItem.Open()
if err != nil {
return err
}
header, err := zip.FileInfoHeader(zipItem.FileInfo())
if err != nil {
return err
}
header.Name = zipItem.Name
targetItem, err := archive.CreateHeader(header)
if err != nil {
return err
}
_, err = io.Copy(targetItem, zipItemReader)
if err != nil {
return err
}
}
err = addFileToArchive(fpath, archive)
if err != nil {
return err
}
err = zipReader.Close()
if err != nil {
return err
}
err = archive.Close()
if err != nil {
return err
}
err = tempFile.Close()
if err != nil {
return err
}
return CopyFile(tempFile.Name(), destPath)
}
func safeFilepathJoin(path1, path2 string) (string, error) {
relPath, err := filepath.Rel(".", path2)
if err != nil || strings.HasPrefix(relPath, "..") {
@@ -402,7 +454,7 @@ func MTime(filepath string) (int64, error) {
return f.ModTime().Unix(), nil
}
// MTime returns file sha value, param `shaType` should be 1, 256 or 512.
// Sha returns file sha value, param `shaType` should be 1, 256 or 512.
// Play: https://go.dev/play/p/VfEEcO2MJYf
func Sha(filepath string, shaType ...int) (string, error) {
file, err := os.Open(filepath)
@@ -453,3 +505,57 @@ func ReadCsvFile(filepath string) ([][]string, error) {
return records, nil
}
// WriteCsvFile write content to target csv file.
// Play: https://go.dev/play/p/dAXm58Q5U1o
func WriteCsvFile(filepath string, records [][]string, append bool) error {
flag := os.O_RDWR | os.O_CREATE
if append {
flag = flag | os.O_APPEND
}
f, err := os.OpenFile(filepath, flag, 0644)
if err != nil {
return err
}
defer f.Close()
writer := csv.NewWriter(f)
writer.Comma = ','
return writer.WriteAll(records)
}
// WriteStringToFile write string to target file.
// Play: https://go.dev/play/p/GhLS6d8lH_g
func WriteStringToFile(filepath string, content string, append bool) error {
flag := os.O_RDWR | os.O_CREATE
if append {
flag = flag | os.O_APPEND
}
f, err := os.OpenFile(filepath, flag, 0644)
if err != nil {
return err
}
defer f.Close()
_, err = f.WriteString(content)
return err
}
// WriteBytesToFile write bytes to target file.
// Play: https://go.dev/play/p/s7QlDxMj3P8
func WriteBytesToFile(filepath string, content []byte) error {
f, err := os.OpenFile(filepath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
return err
}
defer f.Close()
_, err = f.Write(content)
return err
}

View File

@@ -175,11 +175,11 @@ func ExampleReadFileByLine() {
}
func ExampleListFileNames() {
fileList, _ := ListFileNames("./")
fileList, _ := ListFileNames("../internal")
fmt.Println(fileList)
// Output:
// [file.go file_example_test.go file_test.go]
// [assert.go assert_test.go error_join.go]
}
func ExampleZip() {
@@ -224,6 +224,28 @@ func ExampleUnZip() {
// application/octet-stream
}
func ExampleZipAppendEntry() {
zipFile := "./test.zip"
CopyFile("./testdata/file.go.zip", zipFile)
ZipAppendEntry("./testdata", zipFile)
unZipPath := "./unzip"
UnZip(zipFile, unZipPath)
fmt.Println(IsExist("./unzip/file.go"))
fmt.Println(IsExist("./unzip/testdata/file.go.zip"))
fmt.Println(IsExist("./unzip/testdata/test.txt"))
os.Remove(zipFile)
os.RemoveAll(unZipPath)
// Output:
// true
// true
// true
}
func ExampleIsZipFile() {
result1 := IsZipFile("./file.go")
result2 := IsZipFile("./testdata/file.go.zip")
@@ -276,7 +298,7 @@ func ExampleSha() {
}
func ExampleReadCsvFile() {
content, err := ReadCsvFile("./testdata/test.csv")
content, err := ReadCsvFile("./testdata/demo.csv")
fmt.Println(content)
fmt.Println(err)
@@ -285,3 +307,75 @@ func ExampleReadCsvFile() {
// [[Bob 12 male] [Duke 14 male] [Lucy 16 female]]
// <nil>
}
func ExampleWriteCsvFile() {
data := [][]string{
{"Lili", "22", "female"},
{"Jim", "21", "male"},
}
err := WriteCsvFile("./testdata/test2.csv", data, false)
fmt.Println(err)
content, _ := ReadCsvFile("./testdata/test2.csv")
fmt.Println(content)
// Output:
// <nil>
// [[Lili 22 female] [Jim 21 male]]
}
func ExampleWriteStringToFile() {
filepath := "./test.txt"
file, err := os.Create(filepath)
if err != nil {
return
}
defer file.Close()
err = WriteStringToFile(filepath, "hello", true)
if err != nil {
return
}
content, err := ReadFileToString(filepath)
if err != nil {
return
}
os.Remove(filepath)
fmt.Println(content)
// Output:
// hello
}
func ExampleWriteBytesToFile() {
filepath := "./bytes.txt"
file, err := os.Create(filepath)
if err != nil {
return
}
defer file.Close()
err = WriteBytesToFile(filepath, []byte("hello"))
if err != nil {
return
}
content, err := ReadFileToString(filepath)
if err != nil {
return
}
os.Remove(filepath)
fmt.Println(content)
// Output:
// hello
}

View File

@@ -8,6 +8,8 @@ import (
)
func TestIsExist(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIsExist")
cases := []string{"./", "./file.go", "./a.txt"}
@@ -20,6 +22,8 @@ func TestIsExist(t *testing.T) {
}
func TestCreateFile(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestCreateFile")
f := "./text.txt"
@@ -36,6 +40,8 @@ func TestCreateFile(t *testing.T) {
}
func TestCreateDir(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestCreateDir")
pwd, err := os.Getwd()
@@ -57,6 +63,8 @@ func TestCreateDir(t *testing.T) {
}
func TestIsDir(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIsDir")
cases := []string{"./", "./a.txt"}
@@ -69,6 +77,8 @@ func TestIsDir(t *testing.T) {
}
func TestRemoveFile(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestRemoveFile")
f := "./text.txt"
if !IsExist(f) {
@@ -191,6 +201,44 @@ func TestZipAndUnZip(t *testing.T) {
os.RemoveAll(unZipPath)
}
func TestZipAppendEntry(t *testing.T) {
assert := internal.NewAssert(t, "TestZipAppendEntry")
zipFile := "./text.zip"
err := CopyFile("./testdata/file.go.zip", zipFile)
assert.IsNil(err)
srcFile := "./text.txt"
CreateFile(srcFile)
file, _ := os.OpenFile(srcFile, os.O_WRONLY|os.O_TRUNC, os.ModePerm)
_, err = file.WriteString("hello\nworld")
if err != nil {
t.Fail()
}
file.Close()
err = ZipAppendEntry(srcFile, zipFile)
assert.IsNil(err)
err = ZipAppendEntry("./testdata", zipFile)
assert.IsNil(err)
unZipPath := "./unzip"
err = UnZip(zipFile, unZipPath)
assert.IsNil(err)
assert.Equal(true, IsExist("./unzip/text.txt"))
assert.Equal(true, IsExist("./unzip/file.go"))
assert.Equal(true, IsExist("./unzip/testdata/file.go.zip"))
assert.Equal(true, IsExist("./unzip/testdata/test.txt"))
os.Remove(srcFile)
os.Remove(zipFile)
os.RemoveAll(unZipPath)
}
func TestFileMode(t *testing.T) {
assert := internal.NewAssert(t, "TestFileMode")
@@ -235,10 +283,10 @@ func TestMiMeType(t *testing.T) {
func TestListFileNames(t *testing.T) {
assert := internal.NewAssert(t, "TestListFileNames")
filesInPath, err := ListFileNames("./")
filesInPath, err := ListFileNames("../internal")
assert.IsNil(err)
expected := []string{"file.go", "file_example_test.go", "file_test.go"}
expected := []string{"assert.go", "assert_test.go", "error_join.go"}
assert.Equal(expected, filesInPath)
}
@@ -288,7 +336,7 @@ func TestSha(t *testing.T) {
func TestReadCsvFile(t *testing.T) {
assert := internal.NewAssert(t, "TestReadCsvFile")
content, err := ReadCsvFile("./testdata/test.csv")
content, err := ReadCsvFile("./testdata/demo.csv")
assert.IsNil(err)
@@ -296,3 +344,91 @@ func TestReadCsvFile(t *testing.T) {
assert.Equal(3, len(content[0]))
assert.Equal("Bob", content[0][0])
}
func TestWriteCsvFile(t *testing.T) {
assert := internal.NewAssert(t, "TestWriteCsvFile")
csvFilePath := "./testdata/test1.csv"
content := [][]string{
{"Lili", "22", "female"},
{"Jim", "21", "male"},
}
err := WriteCsvFile(csvFilePath, content, false)
assert.IsNil(err)
readContent, err := ReadCsvFile(csvFilePath)
assert.IsNil(err)
assert.Equal(2, len(readContent))
assert.Equal(3, len(readContent[0]))
assert.Equal("Lili", content[0][0])
// RemoveFile(csvFilePath)
}
func TestWriteStringToFile(t *testing.T) {
assert := internal.NewAssert(t, "TestWriteStringToFile")
filepath := "./test.txt"
file, err := os.Create(filepath)
if err != nil {
t.Fail()
}
defer file.Close()
err = WriteStringToFile(filepath, "hello", false)
if err != nil {
t.Fail()
}
content1, err := ReadFileToString(filepath)
if err != nil {
t.Fail()
}
err = WriteStringToFile(filepath, " world", true)
if err != nil {
t.Fail()
}
content2, err := os.ReadFile(filepath)
if err != nil {
t.Fail()
}
assert.Equal("hello", content1)
assert.Equal("hello world", string(content2))
os.Remove(filepath)
}
func TestWriteBytesToFile(t *testing.T) {
assert := internal.NewAssert(t, "TestWriteBytesToFile")
filepath := "./bytes.txt"
file, err := os.Create(filepath)
if err != nil {
t.Fail()
}
defer file.Close()
err = WriteBytesToFile(filepath, []byte("hello"))
if err != nil {
t.Fail()
}
content, err := os.ReadFile(filepath)
if err != nil {
t.Fail()
}
assert.Equal("hello", string(content))
os.Remove(filepath)
}

View File

@@ -1,3 +1,3 @@
Bob, 12, male
Duke, 14, male
Lucy, 16, female
Lucy, 16, female
1 Bob 12 male
2 Duke 14 male
3 Lucy 16 female

2
fileutil/testdata/test1.csv vendored Normal file
View File

@@ -0,0 +1,2 @@
Lili,22,female
Jim,21,male
1 Lili 22 female
2 Jim 21 male

2
fileutil/testdata/test2.csv vendored Normal file
View File

@@ -0,0 +1,2 @@
Lili,22,female
Jim,21,male
1 Lili 22 female
2 Jim 21 male

View File

@@ -7,6 +7,8 @@ import (
)
func TestDecimalBytes(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestDecimalBytes")
assert.Equal("1KB", DecimalBytes(1000))
@@ -21,6 +23,8 @@ func TestDecimalBytes(t *testing.T) {
}
func TestBinaryBytes(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBinaryBytes")
assert.Equal("1KiB", BinaryBytes(1024))
@@ -30,6 +34,8 @@ func TestBinaryBytes(t *testing.T) {
}
func TestParseDecimalBytes(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestParseDecimalBytes")
cases := map[string]uint64{
@@ -58,6 +64,8 @@ func TestParseDecimalBytes(t *testing.T) {
}
func TestParseBinaryBytes(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestParseBinaryBytes")
cases := map[string]uint64{

View File

@@ -8,6 +8,8 @@ import (
)
func TestComma(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestComma")
assert.Equal("", Comma("", ""))
@@ -29,6 +31,8 @@ func TestComma(t *testing.T) {
}
func TestPretty(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestPretty")
cases := []any{
@@ -60,6 +64,8 @@ func TestPretty(t *testing.T) {
}
func TestPrettyToWriter(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestPrettyToWriter")
type User struct {

View File

@@ -11,6 +11,8 @@ import (
)
func TestAfter(t *testing.T) {
t.Parallel()
arr := []string{"a", "b"}
f := After(len(arr), func(i int) int {
fmt.Println("print done")
@@ -34,6 +36,8 @@ func TestAfter(t *testing.T) {
}
func TestBefore(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBefore")
arr := []string{"a", "b", "c", "d", "e"}
@@ -57,6 +61,8 @@ func TestBefore(t *testing.T) {
}
func TestCurry(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestCurry")
add := func(a, b int) int {
@@ -71,6 +77,8 @@ func TestCurry(t *testing.T) {
}
func TestCompose(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestCompose")
toUpper := func(strs ...string) string {

View File

@@ -7,6 +7,8 @@ import (
)
func TestWatcher(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestWatcher")
w := NewWatcher()

View File

@@ -12,6 +12,8 @@ import (
)
func TestSliceIterator(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSliceIterator")
// HashNext
@@ -60,6 +62,8 @@ func TestSliceIterator(t *testing.T) {
}
func TestRangeIterator(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestRangeIterator")
t.Run("range iterator: ", func(t *testing.T) {
@@ -85,6 +89,8 @@ func TestRangeIterator(t *testing.T) {
}
func TestChannelIterator(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestRangeIterator")
iter := FromSlice([]int{1, 2, 3, 4})

View File

@@ -17,6 +17,8 @@ import (
)
func TestMapIterator(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMapIterator")
iter := FromSlice([]int{1, 2, 3, 4})
@@ -28,6 +30,8 @@ func TestMapIterator(t *testing.T) {
}
func TestFilterIterator(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestFilterIterator")
iter := FromSlice([]int{1, 2, 3, 4})
@@ -39,6 +43,8 @@ func TestFilterIterator(t *testing.T) {
}
func TestJoinIterator(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestJoinIterator")
iter1 := FromSlice([]int{1, 2})
@@ -54,6 +60,8 @@ func TestJoinIterator(t *testing.T) {
}
func TestReduce(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestReduce")
iter := FromSlice([]int{1, 2, 3, 4})
@@ -62,6 +70,8 @@ func TestReduce(t *testing.T) {
}
func TestTakeIterator(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestTakeIterator")
iter := FromSlice([]int{1, 2, 3, 4, 5})

View File

@@ -9,6 +9,8 @@ import (
)
func TestKeys(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestKeys")
m := map[int]string{
@@ -26,6 +28,8 @@ func TestKeys(t *testing.T) {
}
func TestValues(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestValues")
m := map[int]string{
@@ -43,6 +47,8 @@ func TestValues(t *testing.T) {
}
func TestKeysBy(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestKeysBy")
m := map[int]string{
@@ -61,6 +67,8 @@ func TestKeysBy(t *testing.T) {
}
func TestValuesBy(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestValuesBy")
m := map[int]string{
@@ -88,6 +96,8 @@ func TestValuesBy(t *testing.T) {
}
func TestMerge(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMerge")
m1 := map[int]string{
@@ -110,6 +120,8 @@ func TestMerge(t *testing.T) {
}
func TestForEach(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestForEach")
m := map[string]int{
@@ -129,6 +141,8 @@ func TestForEach(t *testing.T) {
}
func TestFilter(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestFilter")
m := map[string]int{
@@ -151,6 +165,8 @@ func TestFilter(t *testing.T) {
}
func TestFilterByKeys(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestFilterByKeys")
m := map[string]int{
@@ -170,6 +186,8 @@ func TestFilterByKeys(t *testing.T) {
}
func TestFilterByValues(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestFilterByValues")
m := map[string]int{
@@ -189,6 +207,8 @@ func TestFilterByValues(t *testing.T) {
}
func TestOmitBy(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestOmitBy")
m := map[string]int{
@@ -212,6 +232,8 @@ func TestOmitBy(t *testing.T) {
}
func TestOmitByKeys(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestOmitByKeys")
m := map[string]int{
@@ -232,6 +254,8 @@ func TestOmitByKeys(t *testing.T) {
}
func TestOmitByValues(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestOmitByValues")
m := map[string]int{
@@ -252,6 +276,8 @@ func TestOmitByValues(t *testing.T) {
}
func TestIntersect(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIntersect")
m1 := map[string]int{
@@ -279,6 +305,8 @@ func TestIntersect(t *testing.T) {
}
func TestMinus(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMinus")
m1 := map[string]int{
@@ -297,6 +325,8 @@ func TestMinus(t *testing.T) {
}
func TestIsDisjoint(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMinus")
m1 := map[string]int{
@@ -319,6 +349,8 @@ func TestIsDisjoint(t *testing.T) {
}
func TestEntries(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestEntries")
m := map[string]int{
@@ -339,6 +371,8 @@ func TestEntries(t *testing.T) {
}
func TestFromEntries(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestFromEntries")
result := FromEntries([]Entry[string, int]{
@@ -354,6 +388,8 @@ func TestFromEntries(t *testing.T) {
}
func TestTransform(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestTransform")
m := map[string]int{
@@ -376,6 +412,8 @@ func TestTransform(t *testing.T) {
}
func TestMapKeys(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMapKeys")
m := map[int]string{
@@ -398,6 +436,8 @@ func TestMapKeys(t *testing.T) {
}
func TestMapValues(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMapKeys")
m := map[int]string{

View File

@@ -21,6 +21,8 @@ type (
)
func TestStructType(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestStructType")
src := map[string]interface{}{
@@ -44,6 +46,8 @@ func TestStructType(t *testing.T) {
}
func TestBaseType(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestBaseType")
tc := map[string]interface{}{
@@ -90,22 +94,31 @@ func TestBaseType(t *testing.T) {
MapTo(tc["i"], &number)
assert.EqualValues(-1, number)
MapTo(tc["i8"], &number)
assert.EqualValues(-8, number)
MapTo(tc["i16"], &number)
assert.EqualValues(-16, number)
MapTo(tc["i32"], &number)
assert.EqualValues(-32, number)
MapTo(tc["i64"], &number)
assert.EqualValues(-64, number)
MapTo(tc["u"], &number)
assert.EqualValues(1, number)
MapTo(tc["u8"], &number)
assert.EqualValues(8, number)
MapTo(tc["u16"], &number)
assert.EqualValues(16, number)
MapTo(tc["u32"], &number)
assert.EqualValues(32, number)
MapTo(tc["u64"], &number)
assert.EqualValues(64, number)
}

View File

@@ -55,7 +55,7 @@ func Factorial(x uint) uint {
}
// Percent calculate the percentage of value to total.
// Play: https://go.dev/play/p/QQM9B13coSP
// Play: https://go.dev/play/p/s0NdFCtwuyd
func Percent(val, total float64, n int) float64 {
if total == 0 {
return float64(0)
@@ -172,6 +172,18 @@ func MinBy[T any](slice []T, comparator func(T, T) bool) T {
return min
}
// Sum return sum of passed numbers.
// Play: https://go.dev/play/p/1To2ImAMJA7
func Sum[T constraints.Integer | constraints.Float](numbers ...T) T {
var sum T
for _, v := range numbers {
sum += v
}
return sum
}
// Average return average value of numbers.
// Play: https://go.dev/play/p/Vv7LBwER-pz
func Average[T constraints.Integer | constraints.Float](numbers ...T) T {
@@ -258,7 +270,7 @@ func IsPrime(n int) bool {
}
// GCD return greatest common divisor (GCD) of integers.
// Play: todo
// Play: https://go.dev/play/p/CiEceLSoAKB
func GCD[T constraints.Integer](integers ...T) T {
result := integers[0]
@@ -283,7 +295,7 @@ func gcd[T constraints.Integer](a, b T) T {
}
// LCM return Least Common Multiple (LCM) of integers.
// Play: todo
// Play: https://go.dev/play/p/EjcZxfY7G_g
func LCM[T constraints.Integer](integers ...T) T {
result := integers[0]
@@ -301,3 +313,41 @@ func lcm[T constraints.Integer](a, b T) T {
}
return a * b / gcd(a, b)
}
// Cos returns the cosine of the radian argument.
// Play: https://go.dev/play/p/Sm89LoIfvFq
func Cos(radian float64, precision ...int) float64 {
t := 1.0 / (2.0 * math.Pi)
radian *= t
radian -= 0.25 + math.Floor(radian+0.25)
radian *= 16.0 * (math.Abs(radian) - 0.5)
radian += 0.225 * radian * (math.Abs(radian) - 1.0)
if len(precision) == 1 {
return TruncRound(radian, precision[0])
}
return TruncRound(radian, 3)
}
// Cos returns the sine of the radian argument.
// Play: https://go.dev/play/p/TWMQlMywDsP
func Sin(radian float64, precision ...int) float64 {
return Cos((math.Pi / 2) - radian)
}
// Log returns the logarithm of base n.
// Play: https://go.dev/play/p/_d4bi8oyhat
func Log(n, base float64) float64 {
return math.Log(n) / math.Log(base)
}
// Abs returns the absolute value of x.
// Play: todo
func Abs[T constraints.Integer | constraints.Float](x T) T {
if x < 0 {
return (-x)
}
return x
}

View File

@@ -122,6 +122,18 @@ func ExampleAverage() {
// 1.3
}
func ExampleSum() {
result1 := Sum(1, 2)
result2 := Sum(0.1, float64(1))
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 3
// 1.1
}
func ExampleMax() {
result1 := Max(1, 2, 3)
result2 := Max(1.2, 1.4, 1.1, 1.4)
@@ -320,3 +332,75 @@ func ExampleLCM() {
// 2
// 18
}
func ExampleCos() {
result1 := Cos(0)
result2 := Cos(90)
result3 := Cos(180)
result4 := Cos(math.Pi)
result5 := Cos(math.Pi / 2)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// 1
// -0.447
// -0.598
// -1
// 0
}
func ExampleSin() {
result1 := Sin(0)
result2 := Sin(90)
result3 := Sin(180)
result4 := Sin(math.Pi)
result5 := Sin(math.Pi / 2)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
fmt.Println(result4)
fmt.Println(result5)
// Output:
// 0
// 0.894
// -0.801
// 0
// 1
}
func ExampleLog() {
result1 := Log(8, 2)
result2 := TruncRound(Log(5, 2), 2)
result3 := TruncRound(Log(27, 3), 0)
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 3
// 2.32
// 3
}
func ExampleAbs() {
result1 := Abs(-1)
result2 := Abs(-0.1)
result3 := Abs(float32(0.2))
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// 1
// 0.1
// 0.2
}

View File

@@ -8,6 +8,8 @@ import (
)
func TestExponent(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestExponent")
assert.Equal(int64(1), Exponent(10, 0))
@@ -16,6 +18,8 @@ func TestExponent(t *testing.T) {
}
func TestFibonacci(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestFibonacci")
assert.Equal(0, Fibonacci(1, 1, 0))
@@ -25,6 +29,8 @@ func TestFibonacci(t *testing.T) {
}
func TestFactorial(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestFactorial")
assert.Equal(uint(1), Factorial(0))
@@ -34,6 +40,8 @@ func TestFactorial(t *testing.T) {
}
func TestPercent(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestPercent")
assert.EqualValues(50, Percent(1, 2, 2))
@@ -42,58 +50,80 @@ func TestPercent(t *testing.T) {
}
func TestRoundToFloat(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestRoundToFloat")
assert.Equal(RoundToFloat(0, 0), float64(0))
assert.Equal(RoundToFloat(0, 1), float64(0))
assert.Equal(RoundToFloat(0.124, 2), float64(0.12))
assert.Equal(RoundToFloat(0.125, 2), float64(0.13))
assert.Equal(RoundToFloat(0.125, 3), float64(0.125))
assert.Equal(RoundToFloat(33.33333, 2), float64(33.33))
assert.Equal(float64(0), RoundToFloat(0, 0))
assert.Equal(float64(0), RoundToFloat(0, 1))
assert.Equal(0.12, RoundToFloat(0.124, 2))
assert.Equal(0.13, RoundToFloat(0.125, 2))
assert.Equal(0.125, RoundToFloat(0.125, 3))
assert.Equal(33.33, RoundToFloat(33.33333, 2))
}
func TestRoundToString(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestRoundToString")
assert.Equal(RoundToString(0, 0), "0")
assert.Equal(RoundToString(0, 1), "0.0")
assert.Equal(RoundToString(0.124, 2), "0.12")
assert.Equal(RoundToString(0.125, 2), "0.13")
assert.Equal(RoundToString(0.125, 3), "0.125")
assert.Equal("0", RoundToString(0, 0))
assert.Equal("0.0", RoundToString(0, 1))
assert.Equal("0.12", RoundToString(0.124, 2))
assert.Equal("0.13", RoundToString(0.125, 2))
assert.Equal("0.125", RoundToString(0.125, 3))
}
func TestTruncRound(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestTruncRound")
assert.Equal(TruncRound(0, 0), float64(0))
assert.Equal(TruncRound(0, 1), float64(0))
assert.Equal(TruncRound(0.124, 2), float64(0.12))
assert.Equal(TruncRound(0.125, 2), float64(0.12))
assert.Equal(TruncRound(0.125, 3), float64(0.125))
assert.Equal(TruncRound(33.33333, 2), float64(33.33))
assert.Equal(float64(0), TruncRound(0, 0))
assert.Equal(float64(0), TruncRound(0, 1))
assert.Equal(0.12, TruncRound(0.124, 2))
assert.Equal(0.12, TruncRound(0.125, 2))
assert.Equal(0.125, TruncRound(0.125, 3))
assert.Equal(33.33, TruncRound(33.33333, 2))
}
func TestAverage(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestAverage")
assert.Equal(Average(0, 0), 0)
assert.Equal(Average(1, 1), 1)
assert.Equal(0, Average(0, 0))
assert.Equal(1, Average(1, 1))
avg := Average(1.2, 1.4)
assert.Equal(1.3, RoundToFloat(avg, 1))
}
func TestSum(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSum")
assert.Equal(1, Sum(0, 1))
assert.Equal(1.1, Sum(0.1, float64(1)))
}
func TestMax(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMax")
assert.Equal(Max(0, 0), 0)
assert.Equal(Max(1, 2, 3), 3)
assert.Equal(Max(1.2, 1.4, 1.1, 1.4), 1.4)
assert.Equal(0, Max(0, 0))
assert.Equal(3, Max(1, 2, 3))
assert.Equal(1.4, Max(1.2, 1.4, 1.1, 1.4))
type Integer int
assert.Equal(Max(Integer(1), Integer(0)), Integer(1))
assert.Equal(Integer(1), Max(Integer(1), Integer(0)))
}
func TestMaxBy(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "MaxBy")
res1 := MaxBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool {
@@ -113,14 +143,18 @@ func TestMaxBy(t *testing.T) {
}
func TestMin(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMin")
assert.Equal(Min(0, 0), 0)
assert.Equal(Min(1, 2, 3), 1)
assert.Equal(Min(1.2, 1.4, 1.1, 1.4), 1.1)
assert.Equal(0, Min(0, 0))
assert.Equal(1, Min(1, 2, 3))
assert.Equal(1.1, Min(1.2, 1.4, 1.1, 1.4))
}
func TestMinBy(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestMinBy")
res1 := MinBy([]string{"a", "ab", "abc"}, func(v1, v2 string) bool {
@@ -140,6 +174,8 @@ func TestMinBy(t *testing.T) {
}
func TestRange(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestRange")
result1 := Range(1, 4)
@@ -156,6 +192,8 @@ func TestRange(t *testing.T) {
}
func TestRangeWithStep(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestRangeWithStep")
result1 := RangeWithStep(1, 4, 1)
@@ -170,6 +208,8 @@ func TestRangeWithStep(t *testing.T) {
}
func TestAngleToRadian(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestAngleToRadian")
result1 := AngleToRadian(45)
@@ -182,6 +222,8 @@ func TestAngleToRadian(t *testing.T) {
}
func TestRadianToAngle(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestAngleToRadian")
result1 := RadianToAngle(math.Pi)
@@ -194,6 +236,8 @@ func TestRadianToAngle(t *testing.T) {
}
func TestPointDistance(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestPointDistance")
result1 := PointDistance(1, 1, 4, 5)
@@ -202,6 +246,8 @@ func TestPointDistance(t *testing.T) {
}
func TestIsPrime(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIsPrime")
assert.Equal(false, IsPrime(-1))
@@ -213,6 +259,8 @@ func TestIsPrime(t *testing.T) {
}
func TestGCD(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestGCD")
assert.Equal(1, GCD(1, 1))
@@ -238,6 +286,8 @@ func TestGCD(t *testing.T) {
}
func TestLCM(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLCM")
assert.Equal(1, LCM(1))
@@ -249,3 +299,51 @@ func TestLCM(t *testing.T) {
assert.Equal(2, LCM(1, 2))
assert.Equal(18, LCM(3, 6, 9))
}
func TestCos(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestCos")
assert.EqualValues(1, Cos(0))
assert.EqualValues(-0.447, Cos(90))
assert.EqualValues(-0.598, Cos(180))
assert.EqualValues(-1, Cos(math.Pi))
assert.EqualValues(0, Cos(math.Pi/2))
}
func TestSin(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestSin")
assert.EqualValues(0, Sin(0))
assert.EqualValues(0.894, Sin(90))
assert.EqualValues(-0.801, Sin(180))
assert.EqualValues(0, Sin(math.Pi))
assert.EqualValues(1, Sin(math.Pi/2))
}
func TestLog(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestLog")
assert.EqualValues(3, Log(8, 2))
assert.EqualValues(3, TruncRound(Log(27, 3), 0))
assert.EqualValues(2.32, TruncRound(Log(5, 2), 2))
}
func TestAbs(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestAbs")
assert.Equal(0, Abs(0))
assert.Equal(1, Abs(-1))
assert.Equal(0.1, Abs(-0.1))
assert.Equal(int64(1), Abs(int64(-1)))
assert.Equal(float32(1), Abs(float32(-1)))
}

View File

@@ -19,8 +19,10 @@ import (
"errors"
"fmt"
"io"
"mime/multipart"
"net/http"
"net/url"
"os"
"sort"
"strings"
"time"
@@ -94,6 +96,7 @@ type HttpRequest struct {
Headers http.Header
QueryParams url.Values
FormData url.Values
File *File
Body []byte
}
@@ -186,7 +189,11 @@ func (client *HttpClient) SendRequest(request *HttpRequest) (*http.Response, err
}
if request.FormData != nil {
client.setFormData(req, request.FormData)
if request.File != nil {
err = client.setFormData(req, request.FormData, setFile(request.File))
} else {
err = client.setFormData(req, request.FormData, nil)
}
}
client.Request = req
@@ -251,10 +258,80 @@ func (client *HttpClient) setQueryParam(req *http.Request, reqUrl string, queryP
return nil
}
func (client *HttpClient) setFormData(req *http.Request, values url.Values) {
formData := []byte(values.Encode())
req.Body = io.NopCloser(bytes.NewReader(formData))
req.ContentLength = int64(len(formData))
// setFormData set http request FormData param
func (client *HttpClient) setFormData(req *http.Request, values url.Values, setFile SetFileFunc) error {
if setFile != nil {
err := setFile(req, values)
if err != nil {
return err
}
} else {
formData := []byte(values.Encode())
req.Body = io.NopCloser(bytes.NewReader(formData))
req.ContentLength = int64(len(formData))
}
return nil
}
type SetFileFunc func(req *http.Request, values url.Values) error
// File struct is a combination of file attributes
type File struct {
Content []byte
Path string
FieldName string
FileName string
}
// setFile set parameters for http request formdata file upload
func setFile(f *File) SetFileFunc {
return func(req *http.Request, values url.Values) error {
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
for key, vals := range values {
for _, val := range vals {
err := writer.WriteField(key, val)
if err != nil {
return err
}
}
}
if f.Content != nil {
part, err := writer.CreateFormFile(f.FieldName, f.FileName)
if err != nil {
return err
}
part.Write(f.Content)
} else if f.Path != "" {
file, err := os.Open(f.Path)
if err != nil {
return err
}
defer file.Close()
part, err := writer.CreateFormFile(f.FieldName, f.FileName)
if err != nil {
return err
}
_, err = io.Copy(part, file)
if err != nil {
return err
}
}
err := writer.Close()
if err != nil {
return err
}
req.Body = io.NopCloser(body)
req.Header.Set("Content-Type", writer.FormDataContentType())
req.ContentLength = int64(body.Len())
return nil
}
}
// validateRequest check if a request has url, and valid method.

View File

@@ -1,11 +1,15 @@
package netutil
import (
"bytes"
"encoding/json"
"io"
"io/ioutil"
"log"
"net/http"
"net/http/httptest"
"net/url"
"os"
"testing"
"github.com/duke-git/lancet/v2/internal"
@@ -49,8 +53,8 @@ func TestHttpPost(t *testing.T) {
func TestHttpPostFormData(t *testing.T) {
apiUrl := "https://jsonplaceholder.typicode.com/todos"
header := map[string]string{
// "Content-Type": "application/x-www-form-urlencoded",
"Content-Type": "multipart/form-data",
"Content-Type": "application/x-www-form-urlencoded",
// "Content-Type": "multipart/form-data",
}
postData := url.Values{}
@@ -61,7 +65,7 @@ func TestHttpPostFormData(t *testing.T) {
// postData["userId"] = "1"
// postData["title"] = "title"
resp, err := HttpPost(apiUrl, header, postData, nil)
resp, err := HttpPost(apiUrl, header, nil, postData)
if err != nil {
log.Fatal(err)
}
@@ -122,6 +126,8 @@ func TestHttpDelete(t *testing.T) {
}
func TestConvertMapToQueryString(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestConvertMapToQueryString")
var m = map[string]any{
@@ -129,6 +135,7 @@ func TestConvertMapToQueryString(t *testing.T) {
"a": 1,
"b": 2,
}
assert.Equal("a=1&b=2&c=3", ConvertMapToQueryString(m))
}
@@ -159,6 +166,8 @@ func TestParseResponse(t *testing.T) {
}
func TestHttpClient_Get(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestHttpClient_Get")
request := &HttpRequest{
@@ -214,6 +223,8 @@ func TestHttpClent_Post(t *testing.T) {
}
func TestStructToUrlValues(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestStructToUrlValues")
type TodoQuery struct {
@@ -245,3 +256,108 @@ func TestStructToUrlValues(t *testing.T) {
assert.Equal("456", queryValues2.Get("userId"))
assert.Equal("", queryValues2.Get("name"))
}
func handleFileRequest(t *testing.T, w http.ResponseWriter, r *http.Request) {
err := r.ParseMultipartForm(1024)
if err != nil {
t.Fatal(err)
}
key1 := r.FormValue("key1")
expectedKey1 := "value1"
if key1 != expectedKey1 {
t.Fatalf("expected %s, got %s", expectedKey1, key1)
}
key2 := r.FormValue("key2")
expectedKey2 := "value2"
if key2 != expectedKey2 {
t.Fatalf("expected %s, got %s", expectedKey2, key2)
}
file, header, err := r.FormFile("image")
if err != nil {
t.Fatal(err)
}
expectedFileName := "testImage.jpg"
if header.Filename != expectedFileName {
t.Fatalf("expected %s, got %s", expectedFileName, header.Filename)
}
defer file.Close()
content, err := ioutil.ReadAll(file)
if err != nil {
t.Fatal(err)
}
expectedContent := []byte("file content")
if !bytes.Equal(content, expectedContent) {
t.Fatalf("expected %s, got %s", string(expectedContent), string(content))
}
}
func TestSendRequestWithFileContent(t *testing.T) {
handler := http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
handleFileRequest(t, writer, request)
})
server := httptest.NewServer(handler)
defer server.Close()
client := NewHttpClient()
request := &HttpRequest{
RawURL: server.URL,
Method: "POST",
File: &File{Content: []byte("file content"), FieldName: "image", FileName: "testImage.jpg"},
FormData: url.Values{"key1": {"value1"}, "key2": {"value2"}},
}
resp, err := client.SendRequest(request)
if err != nil {
t.Fatal(err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
t.Fatalf("expected %d, got %d", http.StatusOK, resp.StatusCode)
}
}
func TestSendRequestWithFilePath(t *testing.T) {
handler := http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
handleFileRequest(t, writer, request)
})
server := httptest.NewServer(handler)
defer server.Close()
tmpFile, err := ioutil.TempFile("", "testImage.jpg")
if err != nil {
t.Fatal(err)
}
defer os.Remove(tmpFile.Name())
tmpFile.Write([]byte("file content"))
tmpFile.Close()
client := NewHttpClient()
request := &HttpRequest{
RawURL: server.URL,
Method: "POST",
File: &File{Path: tmpFile.Name(), FieldName: "image", FileName: "testImage.jpg"},
FormData: url.Values{"key1": {"value1"}, "key2": {"value2"}},
}
resp, err := client.SendRequest(request)
if err != nil {
t.Fatal(err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
t.Fatalf("expected %d, got %d", http.StatusOK, resp.StatusCode)
}
}

View File

@@ -3,7 +3,9 @@ package netutil
import (
"bytes"
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"strings"
@@ -72,52 +74,34 @@ func setHeaderAndQueryParam(req *http.Request, reqUrl string, header, queryParam
}
func setHeaderAndQueryAndBody(req *http.Request, reqUrl string, header, queryParam, body any) error {
err := setHeader(req, header)
if err != nil {
if err := setHeader(req, header); err != nil {
return err
} else if err = setQueryParam(req, reqUrl, queryParam); err != nil {
return err
} else if err = setBodyByte(req, body); err != nil {
return err
}
err = setQueryParam(req, reqUrl, queryParam)
if err != nil {
return err
}
if strings.Contains(req.Header.Get("Content-Type"), "multipart/form-data") || req.Header.Get("Content-Type") == "application/x-www-form-urlencoded" {
if formData, ok := queryParam.(url.Values); ok {
err = setBodyByte(req, []byte(formData.Encode()))
}
if formData, ok := queryParam.(map[string]string); ok {
postData := url.Values{}
for k, v := range formData {
postData.Set(k, v)
}
err = setBodyByte(req, []byte(postData.Encode()))
}
} else {
err = setBodyByte(req, body)
}
if err != nil {
return err
}
return nil
}
func setHeader(req *http.Request, header any) error {
if header != nil {
switch v := header.(type) {
case map[string]string:
for k := range v {
req.Header.Add(k, v[k])
}
case http.Header:
for k, vv := range v {
for _, vvv := range vv {
req.Header.Add(k, vvv)
}
}
default:
return errors.New("header params type should be http.Header or map[string]string")
if header == nil {
return nil
}
switch v := header.(type) {
case map[string]string:
for k := range v {
req.Header.Add(k, v[k])
}
case http.Header:
for k, vv := range v {
for _, vvv := range vv {
req.Header.Add(k, vvv)
}
}
default:
return errors.New("header params type should be http.Header or map[string]string")
}
if host := req.Header.Get("Host"); host != "" {
@@ -137,19 +121,21 @@ func setUrl(req *http.Request, reqUrl string) error {
}
func setQueryParam(req *http.Request, reqUrl string, queryParam any) error {
if queryParam == nil {
return nil
}
var values url.Values
if queryParam != nil {
switch v := queryParam.(type) {
case map[string]string:
values = url.Values{}
for k := range v {
values.Set(k, v[k])
}
case url.Values:
values = v
default:
return errors.New("query string params type should be url.Values or map[string]string")
switch v := queryParam.(type) {
case map[string]string:
values = url.Values{}
for k := range v {
values.Set(k, v[k])
}
case url.Values:
values = v
default:
return errors.New("query string params type should be url.Values or map[string]string")
}
// set url
@@ -170,14 +156,36 @@ func setQueryParam(req *http.Request, reqUrl string, queryParam any) error {
}
func setBodyByte(req *http.Request, body any) error {
if body != nil {
switch b := body.(type) {
case []byte:
req.Body = io.NopCloser(bytes.NewReader(b))
req.ContentLength = int64(len(b))
default:
return errors.New("body type should be []byte")
if body == nil {
return nil
}
var bodyReader *bytes.Reader
switch b := body.(type) {
case io.Reader:
buf := bytes.NewBuffer(nil)
if _, err := io.Copy(buf, b); err != nil {
return err
}
req.Body = ioutil.NopCloser(buf)
req.ContentLength = int64(buf.Len())
case []byte:
bodyReader = bytes.NewReader(b)
req.Body = ioutil.NopCloser(bodyReader)
req.ContentLength = int64(bodyReader.Len())
case map[string]interface{}:
values := url.Values{}
for k := range b {
values.Set(k, fmt.Sprintf("%v", b[k]))
}
bodyReader = bytes.NewReader([]byte(values.Encode()))
req.Body = ioutil.NopCloser(bodyReader)
req.ContentLength = int64(bodyReader.Len())
case url.Values:
bodyReader = bytes.NewReader([]byte(b.Encode()))
req.Body = ioutil.NopCloser(bodyReader)
req.ContentLength = int64(bodyReader.Len())
default:
return fmt.Errorf("invalid body type: %T", b)
}
return nil
}

View File

@@ -9,6 +9,8 @@ import (
)
func TestGetInternalIp(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestGetInternalIp")
internalIp := GetInternalIp()
@@ -17,6 +19,8 @@ func TestGetInternalIp(t *testing.T) {
}
func TestGetRequestPublicIp(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestGetPublicIpInfo")
ip := "36.112.24.10"
@@ -50,6 +54,8 @@ func TestGetRequestPublicIp(t *testing.T) {
// }
func TestIsPublicIP(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIsPublicIP")
ips := []net.IP{
@@ -69,6 +75,8 @@ func TestIsPublicIP(t *testing.T) {
}
func TestIsInternalIP(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIsInternalIP")
ips := []net.IP{
@@ -110,14 +118,9 @@ func TestEncodeUrl(t *testing.T) {
assert.Equal(expected, encodedUrl)
}
// func TestDownloadFile(t *testing.T) {
// assert := internal.NewAssert(t, "TestDownloadFile")
// err := DownloadFile("./lancet_logo.jpg", "https://picx.zhimg.com/v2-fc82a4199749de9cfb71e32e54f489d3_720w.jpg?source=172ae18b")
// assert.IsNil(err)
// }
func TestIsPingConnected(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestIsPingConnected")
// in github action env, this will fail
@@ -129,6 +132,8 @@ func TestIsPingConnected(t *testing.T) {
}
func TestTelnetConnected(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestTelnetConnected")
result1 := IsTelnetConnected("bing.com", "80")

View File

@@ -1,8 +1,25 @@
// Copyright 2023 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license.
// Package pointer contains some util functions to operate go pointer.
package pointer
import "reflect"
// Of returns a pointer to the value `v`.
// Play: https://go.dev/play/p/HFd70x4DrMj
func Of[T any](v T) *T {
return &v
}
// Unwrap returns the value from the pointer.
// Play: https://go.dev/play/p/cgeu3g7cjWb
func Unwrap[T any](p *T) T {
return *p
}
// ExtractPointer returns the underlying value by the given interface type
// Play: https://go.dev/play/p/D7HFjeWU2ZP
func ExtractPointer(value any) any {
t := reflect.TypeOf(value)
v := reflect.ValueOf(value)

View File

@@ -0,0 +1,44 @@
package pointer
import "fmt"
func ExampleOf() {
result1 := Of(123)
result2 := Of("abc")
fmt.Println(*result1)
fmt.Println(*result2)
// Output:
// 123
// abc
}
func ExampleUnwrap() {
a := 123
b := "abc"
result1 := Unwrap(&a)
result2 := Unwrap(&b)
fmt.Println(result1)
fmt.Println(result2)
// Output:
// 123
// abc
}
func ExampleExtractPointer() {
a := 1
b := &a
c := &b
d := &c
result := ExtractPointer(d)
fmt.Println(result)
// Output:
// 1
}

View File

@@ -1,11 +1,37 @@
package pointer
import (
"github.com/duke-git/lancet/v2/internal"
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestOf(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestOf")
result1 := Of(123)
result2 := Of("abc")
assert.Equal(123, *result1)
assert.Equal("abc", *result2)
}
func TestUnwrap(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestUnwrap")
a := 123
b := "abc"
assert.Equal(a, Unwrap(&a))
assert.Equal(b, Unwrap(&b))
}
func TestExtractPointer(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestExtractPointer")

View File

@@ -9,6 +9,8 @@ import (
)
func TestResolve(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestResolve")
p := Resolve("abc")
@@ -18,6 +20,8 @@ func TestResolve(t *testing.T) {
}
func TestReject(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestReject")
err := errors.New("error")
@@ -28,6 +32,8 @@ func TestReject(t *testing.T) {
}
func TestThen(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestThen")
p1 := New(func(resolve func(string), reject func(error)) {
@@ -48,6 +54,8 @@ func TestThen(t *testing.T) {
}
func TestPromise_Then(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestPromise_Then")
p1 := New(func(resolve func(int), reject func(error)) {
@@ -68,6 +76,8 @@ func TestPromise_Then(t *testing.T) {
}
func TestCatch(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestCatch")
p1 := New(func(resolve func(string), reject func(error)) {
@@ -93,6 +103,8 @@ func TestCatch(t *testing.T) {
}
func TestPromise_Catch(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestPromise_Catch")
p1 := New(func(resolve func(string), reject func(error)) {
@@ -118,6 +130,8 @@ func TestPromise_Catch(t *testing.T) {
}
func TestAll(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestPromise_All")
t.Run("AllPromisesFullfilled", func(_ *testing.T) {
@@ -180,7 +194,6 @@ func TestAll(t *testing.T) {
_, err := p.Await()
assert.IsNotNil(err)
// assert.Equal("error1", err.Error())
})
}
@@ -227,7 +240,6 @@ func TestAny(t *testing.T) {
_, err := p.Await()
assert.IsNotNil(err)
// assert.Equal("error1", err.Error())
})
}
@@ -275,7 +287,6 @@ func TestRace(t *testing.T) {
val, err := p.Await()
assert.IsNotNil(err)
// assert.Equal("error1", err.Error())
assert.Equal("", val)
})
@@ -296,7 +307,6 @@ func TestRace(t *testing.T) {
_, err := p.Await()
assert.IsNotNil(err)
// assert.Equal("error1", err.Error())
})
}

Some files were not shown because too many files have changed in this diff Show More