mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-08 14:42:27 +08:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
975c303a31 | ||
|
|
3b8dd94a5c | ||
|
|
815791c0b6 | ||
|
|
a12a691ee6 | ||
|
|
247cf89947 | ||
|
|
c3fad62d8c | ||
|
|
a8a96be21b | ||
|
|
8e297769b2 | ||
|
|
98cdf1c040 | ||
|
|
d7976e31a4 | ||
|
|
5b11a8b457 | ||
|
|
d4a16534f2 | ||
|
|
ecf0688788 | ||
|
|
90f9cad1ea | ||
|
|
4a298876e9 | ||
|
|
74474cd9ef | ||
|
|
f23f18457e | ||
|
|
18f01ffd75 | ||
|
|
c53d541a6b | ||
|
|
5b9b4c4344 | ||
|
|
6e7300bbbf | ||
|
|
3685aee02b | ||
|
|
046f3e0bf9 | ||
|
|
c01c9d14b4 | ||
|
|
f198191063 | ||
|
|
8bdd46bda4 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -7,4 +7,5 @@ fileutil/*.zip
|
|||||||
fileutil/*.link
|
fileutil/*.link
|
||||||
fileutil/unzip/*
|
fileutil/unzip/*
|
||||||
slice/testdata/*
|
slice/testdata/*
|
||||||
cryptor/*.pem
|
cryptor/*.pem
|
||||||
|
test
|
||||||
149
README.md
149
README.md
@@ -4,7 +4,7 @@
|
|||||||
<br/>
|
<br/>
|
||||||
|
|
||||||

|

|
||||||
[](https://github.com/duke-git/lancet/releases)
|
[](https://github.com/duke-git/lancet/releases)
|
||||||
[](https://pkg.go.dev/github.com/duke-git/lancet/v2)
|
[](https://pkg.go.dev/github.com/duke-git/lancet/v2)
|
||||||
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
||||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||||
@@ -24,7 +24,7 @@ English | [简体中文](./README_zh-CN.md)
|
|||||||
## Feature
|
## Feature
|
||||||
|
|
||||||
- 👏 Comprehensive, efficient and reusable.
|
- 👏 Comprehensive, efficient and reusable.
|
||||||
- 💪 400+ go util functions, support string, slice, datetime, net, crypt...
|
- 💪 500+ go util functions, support string, slice, datetime, net, crypt...
|
||||||
- 💅 Only depend on the go standard library.
|
- 💅 Only depend on the go standard library.
|
||||||
- 🌍 Unit test for every exported function.
|
- 🌍 Unit test for every exported function.
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ 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.7. </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.3.7. </b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
go get github.com/duke-git/lancet@v1.3.7 // below go1.18, install latest version of v1.x.x
|
go get github.com/duke-git/lancet // below go1.18, install latest version of v1.x.x
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@@ -541,6 +541,8 @@ import "github.com/duke-git/lancet/v2/fileutil"
|
|||||||
- **<big>UnZip</big>** : unzip the zip file and save it to dest path.
|
- **<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)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#UnZip)]
|
||||||
[[play](https://go.dev/play/p/g0w34kS7B8m)]
|
[[play](https://go.dev/play/p/g0w34kS7B8m)]
|
||||||
|
- **<big>CurrentPath</big>** : return current absolute path.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil.md#CurrentPath)]
|
||||||
|
|
||||||
### 9. Formatter contains some functions for data formatting.
|
### 9. Formatter contains some functions for data formatting.
|
||||||
|
|
||||||
@@ -553,6 +555,18 @@ import "github.com/duke-git/lancet/v2/formatter"
|
|||||||
- **<big>Comma</big>** : add comma to a number value by every 3 numbers from right, ahead by symbol char.
|
- **<big>Comma</big>** : add comma to a number value by every 3 numbers from right, ahead by symbol char.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#Comma)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#Comma)]
|
||||||
[[play](https://go.dev/play/p/eRD5k2vzUVX)]
|
[[play](https://go.dev/play/p/eRD5k2vzUVX)]
|
||||||
|
- **<big>Pretty</big>** : pretty print data to JSON string.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#Pretty)]
|
||||||
|
- **<big>PrettyToWriter</big>** : pretty encode data to writer.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#PrettyToWriter)]
|
||||||
|
- **<big>DecimalBytes</big>** : returns a human readable byte size under decimal standard (base 1000).
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#DecimalBytes)]
|
||||||
|
- **<big>BinaryBytes</big>** : returns a human-readable byte size under binary standard (base 1024).
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#BinaryBytes)]
|
||||||
|
- **<big>ParseDecimalBytes</big>** : return the human readable bytes size string into the amount it represents(base 1000).
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#ParseDecimalBytes)]
|
||||||
|
- **<big>ParseBinaryBytes</big>** : return the human readable bytes size string into the amount it represents(base 1024).
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter.md#ParseBinaryBytes)]
|
||||||
|
|
||||||
### 10. Function package can control the flow of function execution and support part of functional programming
|
### 10. Function package can control the flow of function execution and support part of functional programming
|
||||||
|
|
||||||
@@ -598,6 +612,8 @@ import "github.com/duke-git/lancet/v2/maputil"
|
|||||||
|
|
||||||
#### Function list:
|
#### Function list:
|
||||||
|
|
||||||
|
- **<big>MapTo</big>** : quick map any value to struct or any base type.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#MapTo)]
|
||||||
- **<big>ForEach</big>** : executes iteratee funcation for every key and value pair in map.
|
- **<big>ForEach</big>** : executes iteratee funcation for every key and value pair in map.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#ForEach)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#ForEach)]
|
||||||
[[play](https://go.dev/play/p/OaThj6iNVXK)]
|
[[play](https://go.dev/play/p/OaThj6iNVXK)]
|
||||||
@@ -711,12 +727,16 @@ import "github.com/duke-git/lancet/v2/mathutil"
|
|||||||
[[play](https://go.dev/play/p/akLWz0EqOSM)]
|
[[play](https://go.dev/play/p/akLWz0EqOSM)]
|
||||||
- **<big>AngleToRadian</big>** : converts angle value to radian value.
|
- **<big>AngleToRadian</big>** : converts angle value to radian value.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#AngleToRadian)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#AngleToRadian)]
|
||||||
|
[[play](https://go.dev/play/p/CIvlICqrHql)]
|
||||||
- **<big>RadianToAngle</big>** : converts radian value to angle value.
|
- **<big>RadianToAngle</big>** : converts radian value to angle value.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#RadianToAngle)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#RadianToAngle)]
|
||||||
|
[[play](https://go.dev/play/p/dQtmOTUOMgi)]
|
||||||
- **<big>PointDistance</big>** : get two points distance.
|
- **<big>PointDistance</big>** : get two points distance.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#PointDistance)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#PointDistance)]
|
||||||
|
[[play](https://go.dev/play/p/RrG4JIaziM8)]
|
||||||
- **<big>IsPrime</big>** : checks if number is prime number.
|
- **<big>IsPrime</big>** : checks if number is prime number.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#IsPrime)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#IsPrime)]
|
||||||
|
[[play](https://go.dev/play/p/Rdd8UTHZJ7u)]
|
||||||
|
|
||||||
### 13. Netutil package contains functions to get net information and send http request.
|
### 13. Netutil package contains functions to get net information and send http request.
|
||||||
|
|
||||||
@@ -768,15 +788,15 @@ import "github.com/duke-git/lancet/v2/netutil"
|
|||||||
- **<big>StructToUrlValues</big>** : convert struct to url valuse.
|
- **<big>StructToUrlValues</big>** : convert struct to url valuse.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#StructToUrlValues)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#StructToUrlValues)]
|
||||||
[[play](https://go.dev/play/p/pFqMkM40w9z)]
|
[[play](https://go.dev/play/p/pFqMkM40w9z)]
|
||||||
- **<big>HttpGet<sup>deprecated</sup></big>** : send get http request.
|
- **<big>HttpGet<sup>deprecated</sup></big>** : send http get request.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpGet)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpGet)]
|
||||||
- **<big>HttpDelete<sup>deprecated</sup></big>** : send delete http request.
|
- **<big>HttpDelete<sup>deprecated</sup></big>** : send http delete request.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpDelete)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpDelete)]
|
||||||
- **<big>HttpPost<sup>deprecated</sup></big>** : send post http request.
|
- **<big>HttpPost<sup>deprecated</sup></big>** : send http post request.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPost)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPost)]
|
||||||
- **<big>HttpPut<sup>deprecated</sup></big>** : send put http request.
|
- **<big>HttpPut<sup>deprecated</sup></big>** : send http put request.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPut)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPut)]
|
||||||
- **<big>HttpPatch<sup>deprecated</sup></big>** : send patch http request.
|
- **<big>HttpPatch<sup>deprecated</sup></big>** : send http patch request.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPatch)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPatch)]
|
||||||
- **<big>ParseHttpResponse</big>** : decode http response into target object.
|
- **<big>ParseHttpResponse</big>** : decode http response into target object.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#ParseHttpResponse)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#ParseHttpResponse)]
|
||||||
@@ -966,8 +986,12 @@ import "github.com/duke-git/lancet/v2/slice"
|
|||||||
- **<big>Reverse</big>** : return slice of element order is reversed to the given slice.
|
- **<big>Reverse</big>** : return slice of element order is reversed to the given slice.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reverse)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reverse)]
|
||||||
[[play](https://go.dev/play/p/8uI8f1lwNrQ)]
|
[[play](https://go.dev/play/p/8uI8f1lwNrQ)]
|
||||||
- **<big>Reduce</big>** : creates an slice of values by running each element of slice thru iteratee function.
|
- **<big>Reduce<sup>deprecated</sup></big>** : creates an slice of values by running each element of slice thru iteratee function.(Deprecated: use ReduceBy)
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reduce)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Reduce)]
|
||||||
|
- **<big>ReduceBy</big>** : produces a value from slice by accumulating the result of each element as passed through the reducer function.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ReduceBy)]
|
||||||
|
- **<big>ReduceRight</big>** : ReduceRight is like ReduceBy, but it iterates over elements of slice from right to left.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#ReduceRight)]
|
||||||
[[play](https://go.dev/play/p/_RfXJJWIsIm)]
|
[[play](https://go.dev/play/p/_RfXJJWIsIm)]
|
||||||
- **<big>Replace</big>** : returns a copy of the slice with the first n non-overlapping instances of old replaced by new.
|
- **<big>Replace</big>** : returns a copy of the slice with the first n non-overlapping instances of old replaced by new.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Replace)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Replace)]
|
||||||
@@ -1039,7 +1063,91 @@ import "github.com/duke-git/lancet/v2/slice"
|
|||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#KeyBy)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice.md#KeyBy)]
|
||||||
[[play](https://go.dev/play/p/uXod2LWD1Kg)]
|
[[play](https://go.dev/play/p/uXod2LWD1Kg)]
|
||||||
|
|
||||||
### 17. Structs package provides several high level functions to manipulate struct, tag, and field.
|
### 17. 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.
|
||||||
|
|
||||||
|
```go
|
||||||
|
import "github.com/duke-git/lancet/v2/stream"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Function list:
|
||||||
|
|
||||||
|
- **<big>Of</big>** : creates a stream whose elements are the specified values.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Of)]
|
||||||
|
[[play](https://go.dev/play/p/jI6_iZZuVFE)]
|
||||||
|
- **<big>FromSlice</big>** : creates a stream from slice.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#FromSlice)]
|
||||||
|
[[play](https://go.dev/play/p/wywTO0XZtI4)]
|
||||||
|
- **<big>FromChannel</big>** : creates a stream from channel.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#FromChannel)]
|
||||||
|
[[play](https://go.dev/play/p/9TZYugGMhXZ)]
|
||||||
|
- **<big>FromRange</big>** : creates a number stream from start to end. both start and end are included. [start, end]
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#FromRange)]
|
||||||
|
[[play](https://go.dev/play/p/9Ex1-zcg-B-)]
|
||||||
|
- **<big>Generate</big>** : creates a stream where each element is generated by the provided generater function.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Generate)]
|
||||||
|
[[play](https://go.dev/play/p/rkOWL1yA3j9)]
|
||||||
|
- **<big>Concat</big>** : creates a lazily concatenated stream whose elements are all the elements of the first stream followed by all the elements of the second stream.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Concat)]
|
||||||
|
[[play](https://go.dev/play/p/HM4OlYk_OUC)]
|
||||||
|
- **<big>Distinct</big>** : creates returns a stream that removes the duplicated items.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Distinct)]
|
||||||
|
[[play](https://go.dev/play/p/eGkOSrm64cB)]
|
||||||
|
- **<big>Filter</big>** : returns a stream consisting of the elements of this stream that match the given predicate.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Filter)]
|
||||||
|
[[play](https://go.dev/play/p/MFlSANo-buc)]
|
||||||
|
- **<big>Map</big>** : returns a stream consisting of the elements of this stream that apply the given function to elements of stream.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Map)]
|
||||||
|
[[play](https://go.dev/play/p/OtNQUImdYko)]
|
||||||
|
- **<big>Peek</big>** : returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Peek)]
|
||||||
|
[[play](https://go.dev/play/p/u1VNzHs6cb2)]
|
||||||
|
- **<big>Skip</big>** : returns a stream consisting of the remaining elements of this stream after discarding the first n elements of the stream.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Skip)]
|
||||||
|
[[play](https://go.dev/play/p/fNdHbqjahum)]
|
||||||
|
- **<big>Limit</big>** : returns a stream consisting of the elements of this stream, truncated to be no longer than maxSize in length.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Limit)]
|
||||||
|
[[play](https://go.dev/play/p/qsO4aniDcGf)]
|
||||||
|
- **<big>Reverse</big>** : returns a stream whose elements are reverse order of given stream.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Reverse)]
|
||||||
|
[[play](https://go.dev/play/p/A8_zkJnLHm4)]
|
||||||
|
- **<big>Range</big>** : returns a stream whose elements are in the range from start(included) to end(excluded) original stream.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Range)]
|
||||||
|
[[play](https://go.dev/play/p/indZY5V2f4j)]
|
||||||
|
- **<big>Sorted</big>** : returns a stream consisting of the elements of this stream, sorted according to the provided less function.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Sorted)]
|
||||||
|
[[play](https://go.dev/play/p/XXtng5uonFj)]
|
||||||
|
- **<big>ForEach</big>** : performs an action for each element of this stream.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#ForEach)]
|
||||||
|
[[play](https://go.dev/play/p/Dsm0fPqcidk)]
|
||||||
|
- **<big>Reduce</big>** : performs a reduction on the elements of this stream, using an associative accumulation function, and returns an Optional describing the reduced value, if any.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Reduce)]
|
||||||
|
[[play](https://go.dev/play/p/6uzZjq_DJLU)]
|
||||||
|
- **<big>FindFirst</big>** : returns the first 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#FindFirst)]
|
||||||
|
[[play](https://go.dev/play/p/9xEf0-6C1e3)]
|
||||||
|
- **<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)]
|
||||||
|
- **<big>Min</big>** : returns the minimum 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#Min)]
|
||||||
|
[[play](https://go.dev/play/p/vZfIDgGNRe_0)]
|
||||||
|
- **<big>AllMatch</big>** : returns whether all elements of this stream match the provided predicate.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#AllMatch)]
|
||||||
|
[[play](https://go.dev/play/p/V5TBpVRs-Cx)]
|
||||||
|
- **<big>AnyMatch</big>** : returns whether any elements of this stream match the provided predicate.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#AnyMatch)]
|
||||||
|
[[play](https://go.dev/play/p/PTCnWn4OxSn)]
|
||||||
|
- **<big>NoneMatch</big>** : returns whether no elements of this stream match the provided predicate.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#NoneMatch)]
|
||||||
|
[[play](https://go.dev/play/p/iWS64pL1oo3)]
|
||||||
|
- **<big>Count</big>** : returns the count of elements in the stream.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Count)]
|
||||||
|
[[play](https://go.dev/play/p/r3koY6y_Xo-)]
|
||||||
|
- **<big>ToSlice</big>** : returns the elements in the stream.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#ToSlice)]
|
||||||
|
[[play](https://go.dev/play/p/jI6_iZZuVFE)]
|
||||||
|
|
||||||
|
### 18. Structs package provides several high level functions to manipulate struct, tag, and field.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/structs"
|
import "github.com/duke-git/lancet/v2/structs"
|
||||||
@@ -1072,7 +1180,7 @@ import "github.com/duke-git/lancet/v2/structs"
|
|||||||
- **<big>IsSlice</big>** : check if the field is a slice
|
- **<big>IsSlice</big>** : check if the field is a slice
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/field.md#IsSlice)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/field.md#IsSlice)]
|
||||||
|
|
||||||
### 18. Strutil package contains some functions to manipulate string.
|
### 19. Strutil package contains some functions to manipulate string.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/strutil"
|
import "github.com/duke-git/lancet/v2/strutil"
|
||||||
@@ -1150,8 +1258,9 @@ import "github.com/duke-git/lancet/v2/strutil"
|
|||||||
[[play](https://go.dev/play/p/bj7_odx3vRf)]
|
[[play](https://go.dev/play/p/bj7_odx3vRf)]
|
||||||
- **<big>RemoveNonPrintable</big>** : remove non-printable characters from a string.
|
- **<big>RemoveNonPrintable</big>** : remove non-printable characters from a string.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#RemoveNonPrintable)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#RemoveNonPrintable)]
|
||||||
|
[[play](https://go.dev/play/p/og47F5x_jTZ)]
|
||||||
|
|
||||||
### 19. System package contain some functions about os, runtime, shell command.
|
### 20. System package contain some functions about os, runtime, shell command.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/system"
|
import "github.com/duke-git/lancet/v2/system"
|
||||||
@@ -1187,7 +1296,7 @@ import "github.com/duke-git/lancet/v2/system"
|
|||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system.md#GetOsBits)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system.md#GetOsBits)]
|
||||||
[[play](https://go.dev/play/p/ml-_XH3gJbW)]
|
[[play](https://go.dev/play/p/ml-_XH3gJbW)]
|
||||||
|
|
||||||
### 20. Validator package contains some functions for data validation.
|
### 21. Validator package contains some functions for data validation.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/validator"
|
import "github.com/duke-git/lancet/v2/validator"
|
||||||
@@ -1240,18 +1349,24 @@ import "github.com/duke-git/lancet/v2/validator"
|
|||||||
- **<big>IsEmptyString</big>** : check if the string is empty.
|
- **<big>IsEmptyString</big>** : check if the string is empty.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsEmptyString)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsEmptyString)]
|
||||||
[[play](https://go.dev/play/p/dpzgUjFnBCX)]
|
[[play](https://go.dev/play/p/dpzgUjFnBCX)]
|
||||||
|
- **<big>IsFloat</big>** : check if the value is float(float32, float34) or not.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsFloat)]
|
||||||
- **<big>IsFloatStr</big>** : check if the string can convert to a float.
|
- **<big>IsFloatStr</big>** : check if the string can convert to a float.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#LOYwS_Oyl7U)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsFloatStr)]
|
||||||
[[play](https://go.dev/play/p/LOYwS_Oyl7U)]
|
[[play](https://go.dev/play/p/LOYwS_Oyl7U)]
|
||||||
|
- **<big>IsNumber</big>** : check if the value is number(integer, float) or not.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsNumber)]
|
||||||
- **<big>IsNumberStr</big>** : check if the string can convert to a number.
|
- **<big>IsNumberStr</big>** : check if the string can convert to a number.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsNumberStr)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsNumberStr)]
|
||||||
[[play](https://go.dev/play/p/LzaKocSV79u)]
|
[[play](https://go.dev/play/p/LzaKocSV79u)]
|
||||||
- **<big>IsJSON</big>** : check if the string is valid JSON.
|
- **<big>IsJSON</big>** : check if the string is valid JSON.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsJSON)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsJSON)]
|
||||||
[[play](https://go.dev/play/p/sRS6c4K8jGk)]
|
[[play](https://go.dev/play/p/8Kip1Itjiil)]
|
||||||
- **<big>IsRegexMatch</big>** : check if the string match the regexp.
|
- **<big>IsRegexMatch</big>** : check if the string match the regexp.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsRegexMatch)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsRegexMatch)]
|
||||||
[[play](https://go.dev/play/p/z_XeZo_litG)]
|
[[play](https://go.dev/play/p/z_XeZo_litG)]
|
||||||
|
- **<big>IsInt</big>** : check if the string can convert to a number.
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsInt)]
|
||||||
- **<big>IsIntStr</big>** : check if the string can convert to a integer.
|
- **<big>IsIntStr</big>** : check if the string can convert to a integer.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsIntStr)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsIntStr)]
|
||||||
[[play](https://go.dev/play/p/jQRtFv-a0Rk)]
|
[[play](https://go.dev/play/p/jQRtFv-a0Rk)]
|
||||||
@@ -1281,10 +1396,12 @@ import "github.com/duke-git/lancet/v2/validator"
|
|||||||
[[play](https://go.dev/play/p/E2nt3unlmzP)]
|
[[play](https://go.dev/play/p/E2nt3unlmzP)]
|
||||||
- **<big>IsASCII</big>** : checks if string is all ASCII char.
|
- **<big>IsASCII</big>** : checks if string is all ASCII char.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsASCII)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsASCII)]
|
||||||
|
[[play](https://go.dev/play/p/hfQNPLX0jNa)]
|
||||||
- **<big>IsPrintable</big>** : checks if string is all printable chars.
|
- **<big>IsPrintable</big>** : checks if string is all printable chars.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsPrintable)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsPrintable)]
|
||||||
|
[[play](https://go.dev/play/p/Pe1FE2gdtTP)]
|
||||||
|
|
||||||
### 21. xerror package implements helpers for errors.
|
### 22. xerror package implements helpers for errors.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/xerror"
|
import "github.com/duke-git/lancet/v2/xerror"
|
||||||
|
|||||||
139
README_zh-CN.md
139
README_zh-CN.md
@@ -4,7 +4,7 @@
|
|||||||
<br/>
|
<br/>
|
||||||
|
|
||||||

|

|
||||||
[](https://github.com/duke-git/lancet/releases)
|
[](https://github.com/duke-git/lancet/releases)
|
||||||
[](https://pkg.go.dev/github.com/duke-git/lancet/v2)
|
[](https://pkg.go.dev/github.com/duke-git/lancet/v2)
|
||||||
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
||||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
## 特性
|
## 特性
|
||||||
|
|
||||||
- 👏 全面、高效、可复用
|
- 👏 全面、高效、可复用
|
||||||
- 💪 400+常用 go 工具函数,支持 string、slice、datetime、net、crypt...
|
- 💪 500+常用 go 工具函数,支持 string、slice、datetime、net、crypt...
|
||||||
- 💅 只依赖 go 标准库
|
- 💅 只依赖 go 标准库
|
||||||
- 🌍 所有导出函数单元测试覆盖率 100%
|
- 🌍 所有导出函数单元测试覆盖率 100%
|
||||||
|
|
||||||
@@ -40,7 +40,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.3.7。</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
go get github.com/duke-git/lancet@v1.3.7 // 使用go1.18以下版本, 必须安装v1.x.x版本
|
go get github.com/duke-git/lancet// 使用go1.18以下版本, 必须安装v1.x.x版本
|
||||||
```
|
```
|
||||||
|
|
||||||
## 用法
|
## 用法
|
||||||
@@ -540,6 +540,8 @@ import "github.com/duke-git/lancet/v2/fileutil"
|
|||||||
- **<big>UnZip</big>** : zip 解压缩文件并保存在目录中。
|
- **<big>UnZip</big>** : zip 解压缩文件并保存在目录中。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#UnZip)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#UnZip)]
|
||||||
[[play](https://go.dev/play/p/g0w34kS7B8m)]
|
[[play](https://go.dev/play/p/g0w34kS7B8m)]
|
||||||
|
- **<big>CurrentPath</big>** : 返回当前位置的绝对路径。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/fileutil_zh-CN.md#CurrentPath)]
|
||||||
|
|
||||||
### 9. formatter 格式化器包含一些数据格式化处理方法。
|
### 9. formatter 格式化器包含一些数据格式化处理方法。
|
||||||
|
|
||||||
@@ -552,6 +554,18 @@ import "github.com/duke-git/lancet/v2/formatter"
|
|||||||
- **<big>Comma</big>** : 用逗号每隔 3 位分割数字/字符串,支持前缀添加符号。
|
- **<big>Comma</big>** : 用逗号每隔 3 位分割数字/字符串,支持前缀添加符号。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#Comma)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#Comma)]
|
||||||
[[play](https://go.dev/play/p/eRD5k2vzUVX)]
|
[[play](https://go.dev/play/p/eRD5k2vzUVX)]
|
||||||
|
- **<big>Pretty</big>** : 返回 pretty JSON 字符串。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#Pretty)]
|
||||||
|
- **<big>PrettyToWriter</big>** : Pretty encode 数据到 writer。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#PrettyToWriter)]
|
||||||
|
- **<big>DecimalBytes</big>** : 返回十进制标准(以 1000 为基数)下的可读字节单位字符串。precision 参数指定小数点后的位数,默认为 4。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#DecimalBytes)]
|
||||||
|
- **<big>BinaryBytes</big>** : 返回 binary 标准(以 1024 为基数)下的可读字节单位字符串。precision 参数指定小数点后的位数,默认为 4。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#BinaryBytes)]
|
||||||
|
- **<big>ParseDecimalBytes</big>** : 将字节单位字符串转换成其所表示的字节数(以 1000 为基数)。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#ParseDecimalBytes)]
|
||||||
|
- **<big>ParseBinaryBytes</big>** : 将字节单位字符串转换成其所表示的字节数(以 1024 为基数)。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/formatter_zh-CN.md#ParseBinaryBytes)]
|
||||||
|
|
||||||
### 10. function 函数包控制函数执行流程,包含部分函数式编程。
|
### 10. function 函数包控制函数执行流程,包含部分函数式编程。
|
||||||
|
|
||||||
@@ -597,6 +611,8 @@ import "github.com/duke-git/lancet/v2/maputil"
|
|||||||
|
|
||||||
#### 函数列表:
|
#### 函数列表:
|
||||||
|
|
||||||
|
- **<big>MapTo</big>** : 快速将 map 或者其他类型映射到结构体或者指定类型。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#MapTo)]
|
||||||
- **<big>ForEach</big>** : 对 map 中的每对 key 和 value 执行 iteratee 函数。
|
- **<big>ForEach</big>** : 对 map 中的每对 key 和 value 执行 iteratee 函数。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#ForEach)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#ForEach)]
|
||||||
[[play](https://go.dev/play/p/OaThj6iNVXK)]
|
[[play](https://go.dev/play/p/OaThj6iNVXK)]
|
||||||
@@ -710,12 +726,16 @@ import "github.com/duke-git/lancet/v2/mathutil"
|
|||||||
[[play](https://go.dev/play/p/akLWz0EqOSM)]
|
[[play](https://go.dev/play/p/akLWz0EqOSM)]
|
||||||
- **<big>AngleToRadian</big>** : 将角度值转为弧度值。
|
- **<big>AngleToRadian</big>** : 将角度值转为弧度值。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#AngleToRadian)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#AngleToRadian)]
|
||||||
|
[[play](https://go.dev/play/p/CIvlICqrHql)]
|
||||||
- **<big>RadianToAngle</big>** : 将弧度值转为角度值。
|
- **<big>RadianToAngle</big>** : 将弧度值转为角度值。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RadianToAngle)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#RadianToAngle)]
|
||||||
|
[[play](https://go.dev/play/p/dQtmOTUOMgi)]
|
||||||
- **<big>PointDistance</big>** : 计算两个坐标点的距离。
|
- **<big>PointDistance</big>** : 计算两个坐标点的距离。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#PointDistance)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#PointDistance)]
|
||||||
|
[[play](https://go.dev/play/p/RrG4JIaziM8)]
|
||||||
- **<big>IsPrime</big>** : 判断质数。
|
- **<big>IsPrime</big>** : 判断质数。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#IsPrime)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#IsPrime)]
|
||||||
|
[[play](https://go.dev/play/p/Rdd8UTHZJ7u)]
|
||||||
|
|
||||||
### 13. netutil 网络包支持获取 ip 地址,发送 http 请求。
|
### 13. netutil 网络包支持获取 ip 地址,发送 http 请求。
|
||||||
|
|
||||||
@@ -965,9 +985,13 @@ import "github.com/duke-git/lancet/v2/slice"
|
|||||||
- **<big>Reverse</big>** : 反转切片中的元素顺序。
|
- **<big>Reverse</big>** : 反转切片中的元素顺序。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Reverse)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Reverse)]
|
||||||
[[play](https://go.dev/play/p/8uI8f1lwNrQ)]
|
[[play](https://go.dev/play/p/8uI8f1lwNrQ)]
|
||||||
- **<big>Reduce</big>** : 将切片中的元素依次运行 iteratee 函数,返回运行结果。
|
- **<big>Reduce<sup>deprecated</sup></big>** : 将切片中的元素依次运行 iteratee 函数,返回运行结果。(废弃:建议使用 ReduceBy)
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Reduce)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Reduce)]
|
||||||
[[play](https://go.dev/play/p/_RfXJJWIsIm)]
|
[[play](https://go.dev/play/p/_RfXJJWIsIm)]
|
||||||
|
- **<big>ReduceBy</big>** : 对切片元素执行 reduce 操作。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ReduceBy)]
|
||||||
|
- **<big>ReduceRight</big>** : 类似 ReduceBy 操作,迭代切片元素顺序从右至左。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#ReduceRight)]
|
||||||
- **<big>Replace</big>** : 返回切片的副本,其中前 n 个不重叠的 old 替换为 new。
|
- **<big>Replace</big>** : 返回切片的副本,其中前 n 个不重叠的 old 替换为 new。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Replace)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Replace)]
|
||||||
[[play](https://go.dev/play/p/P5mZp7IhOFo)]
|
[[play](https://go.dev/play/p/P5mZp7IhOFo)]
|
||||||
@@ -1038,7 +1062,91 @@ import "github.com/duke-git/lancet/v2/slice"
|
|||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#KeyBy)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#KeyBy)]
|
||||||
[[play](https://go.dev/play/p/uXod2LWD1Kg)]
|
[[play](https://go.dev/play/p/uXod2LWD1Kg)]
|
||||||
|
|
||||||
### 17. structs 提供操作 struct, tag, field 的相关函数。
|
### 17. Stream 流,该包仅验证简单的 stream 实现,功能有限。
|
||||||
|
|
||||||
|
```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)]
|
||||||
|
[[play](https://go.dev/play/p/jI6_iZZuVFE)]
|
||||||
|
- **<big>FromSlice</big>** : 从切片创建 stream。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#FromSlice)]
|
||||||
|
[[play](https://go.dev/play/p/wywTO0XZtI4)]
|
||||||
|
- **<big>FromChannel</big>** : 从通道创建 stream。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#FromChannel)]
|
||||||
|
[[play](https://go.dev/play/p/9TZYugGMhXZ)]
|
||||||
|
- **<big>FromRange</big>** : 指定一个数字范围创建 stream, 范围两端点值都包括在内。. [start, end]
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#FromRange)]
|
||||||
|
[[play](https://go.dev/play/p/9Ex1-zcg-B-)]
|
||||||
|
- **<big>Generate</big>** : 创建一个 stream,其中每个元素都由提供的生成器函数生成。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Generate)]
|
||||||
|
[[play](https://go.dev/play/p/rkOWL1yA3j9)]
|
||||||
|
- **<big>Concat</big>** : 创建一个延迟连接 stream,其元素是第一个 stream 的所有元素,后跟第二个 stream 的全部元素。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Concat)]
|
||||||
|
[[play](https://go.dev/play/p/HM4OlYk_OUC)]
|
||||||
|
- **<big>Distinct</big>** : 创建并返回一个 stream,用于删除重复的项。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Distinct)]
|
||||||
|
[[play](https://go.dev/play/p/eGkOSrm64cB)]
|
||||||
|
- **<big>Filter</big>** : 返回一个通过判定函数的 stream。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Filter)]
|
||||||
|
[[play](https://go.dev/play/p/MFlSANo-buc)]
|
||||||
|
- **<big>Map</big>** : 返回一个 stream,该 stream 由将给定函数应用于源 stream 元素的元素组成。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Map)]
|
||||||
|
[[play](https://go.dev/play/p/OtNQUImdYko)]
|
||||||
|
- **<big>Peek</big>** : 返回一个由源 stream 的元素组成的 stream,并在从生成的 stream 中消耗元素时对每个元素执行所提供的操作。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Peek)]
|
||||||
|
[[play](https://go.dev/play/p/u1VNzHs6cb2)]
|
||||||
|
- **<big>Skip</big>** : 在丢弃 stream 的前 n 个元素后,返回由源 stream 的其余元素组成的 stream。如果此 stream 包含的元素少于 n 个,则将返回一个空 stream。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Skip)]
|
||||||
|
[[play](https://go.dev/play/p/fNdHbqjahum)]
|
||||||
|
- **<big>Limit</big>** : 返回由源 stream 的元素组成的 stream,该 stream 被截断为长度不超过 maxSize。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Limit)]
|
||||||
|
[[play](https://go.dev/play/p/qsO4aniDcGf)]
|
||||||
|
- **<big>Reverse</big>** : 返回元素与源 stream 的顺序相反的 stream。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Reverse)]
|
||||||
|
[[play](https://go.dev/play/p/A8_zkJnLHm4)]
|
||||||
|
- **<big>Range</big>** : 返回一个 stream,该 stream 的元素在从源 stream 的开始(包含)到结束(排除)的范围内。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Range)]
|
||||||
|
[[play](https://go.dev/play/p/indZY5V2f4j)]
|
||||||
|
- **<big>Sorted</big>** : 返回一个 stream,该 stream 由源 stream 的元素组成,并根据提供的 less 函数进行排序。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Sorted)]
|
||||||
|
[[play](https://go.dev/play/p/XXtng5uonFj)]
|
||||||
|
- **<big>ForEach</big>** : 对 stream 的每个元素执行一个操作。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#ForEach)]
|
||||||
|
[[play](https://go.dev/play/p/Dsm0fPqcidk)]
|
||||||
|
- **<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 的第一个元素和 true,如果 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>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)]
|
||||||
|
- **<big>Min</big>** : 根据提供的 less 函数返回 stream 的最小元素。less 函数: a < b
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Min)]
|
||||||
|
[[play](https://go.dev/play/p/vZfIDgGNRe_0)]
|
||||||
|
- **<big>AllMatch</big>** : 判断 stream 的所有元素是否全部匹配指定判定函数。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#AllMatch)]
|
||||||
|
[[play](https://go.dev/play/p/V5TBpVRs-Cx)]
|
||||||
|
- **<big>AnyMatch</big>** : 判断 stream 是否包含匹配指定判定函数的元素。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#AnyMatch)]
|
||||||
|
[[play](https://go.dev/play/p/PTCnWn4OxSn)]
|
||||||
|
- **<big>NoneMatch</big>** : 判断 stream 的元素是否全部不匹配指定的判定函数。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#NoneMatch)]
|
||||||
|
[[play](https://go.dev/play/p/iWS64pL1oo3)]
|
||||||
|
- **<big>Count</big>** : 返回 stream 中元素的数量。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Count)]
|
||||||
|
[[play](https://go.dev/play/p/r3koY6y_Xo-)]
|
||||||
|
- **<big>ToSlice</big>** : 返回 stream 中的元素切片。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#ToSlice)]
|
||||||
|
[[play](https://go.dev/play/p/jI6_iZZuVFE)]
|
||||||
|
|
||||||
|
### 18. structs 提供操作 struct, tag, field 的相关函数。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/structs"
|
import "github.com/duke-git/lancet/v2/structs"
|
||||||
@@ -1073,7 +1181,7 @@ import "github.com/duke-git/lancet/v2/structs"
|
|||||||
- **<big>IsSlice</big>** : 判断属性是否是切片。
|
- **<big>IsSlice</big>** : 判断属性是否是切片。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/field_zh-CN.md#IsSlice)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/structs/field_zh-CN.md#IsSlice)]
|
||||||
|
|
||||||
### 18. strutil 包含字符串处理的相关函数。
|
### 19. strutil 包含字符串处理的相关函数。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/strutil"
|
import "github.com/duke-git/lancet/v2/strutil"
|
||||||
@@ -1152,8 +1260,9 @@ import "github.com/duke-git/lancet/v2/strutil"
|
|||||||
[[play](https://go.dev/play/p/bj7_odx3vRf)]
|
[[play](https://go.dev/play/p/bj7_odx3vRf)]
|
||||||
- **<big>RemoveNonPrintable</big>** : 删除字符串中不可打印的字符。
|
- **<big>RemoveNonPrintable</big>** : 删除字符串中不可打印的字符。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#RemoveNonPrintable)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#RemoveNonPrintable)]
|
||||||
|
[[play](https://go.dev/play/p/og47F5x_jTZ)]
|
||||||
|
|
||||||
### 19. system 包含 os, runtime, shell command 的相关函数。
|
### 20. system 包含 os, runtime, shell command 的相关函数。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/system"
|
import "github.com/duke-git/lancet/v2/system"
|
||||||
@@ -1189,7 +1298,7 @@ import "github.com/duke-git/lancet/v2/system"
|
|||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN#GetOsBits)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/system_zh-CN#GetOsBits)]
|
||||||
[[play](https://go.dev/play/p/ml-_XH3gJbW)]
|
[[play](https://go.dev/play/p/ml-_XH3gJbW)]
|
||||||
|
|
||||||
### 20. validator 验证器包,包含常用字符串格式验证函数。
|
### 21. validator 验证器包,包含常用字符串格式验证函数。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/validator"
|
import "github.com/duke-git/lancet/v2/validator"
|
||||||
@@ -1242,18 +1351,24 @@ import "github.com/duke-git/lancet/v2/validator"
|
|||||||
- **<big>IsEmptyString</big>** : 验证字符串是否是空字符串。
|
- **<big>IsEmptyString</big>** : 验证字符串是否是空字符串。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsEmptyString)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsEmptyString)]
|
||||||
[[play](https://go.dev/play/p/dpzgUjFnBCX)]
|
[[play](https://go.dev/play/p/dpzgUjFnBCX)]
|
||||||
|
- **<big>IsFloat</big>** : 验证参数是否是浮点数((float32,float34)。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsFloat)]
|
||||||
- **<big>IsFloatStr</big>** : 验证字符串是否是可以转换为浮点数。
|
- **<big>IsFloatStr</big>** : 验证字符串是否是可以转换为浮点数。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#LOYwS_Oyl7U)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsFloatStr)]
|
||||||
[[play](https://go.dev/play/p/LOYwS_Oyl7U)]
|
[[play](https://go.dev/play/p/LOYwS_Oyl7U)]
|
||||||
|
- **<big>IsNumber</big>** : 验证参数是否是数字(integer,float)。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsNumber)]
|
||||||
- **<big>IsNumberStr</big>** : 验证字符串是否是可以转换为数字。
|
- **<big>IsNumberStr</big>** : 验证字符串是否是可以转换为数字。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsNumberStr)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsNumberStr)]
|
||||||
[[play](https://go.dev/play/p/LzaKocSV79u)]
|
[[play](https://go.dev/play/p/LzaKocSV79u)]
|
||||||
- **<big>IsJSON</big>** : 验证字符串是否是有效 json。
|
- **<big>IsJSON</big>** : 验证字符串是否是有效 json。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsJSON)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsJSON)]
|
||||||
[[play](https://go.dev/play/p/sRS6c4K8jGk)]
|
[[play](https://go.dev/play/p/8Kip1Itjiil)]
|
||||||
- **<big>IsRegexMatch</big>** : 验证字符串是否可以匹配正则表达式。
|
- **<big>IsRegexMatch</big>** : 验证字符串是否可以匹配正则表达式。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsRegexMatch)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsRegexMatch)]
|
||||||
[[play](https://go.dev/play/p/z_XeZo_litG)]
|
[[play](https://go.dev/play/p/z_XeZo_litG)]
|
||||||
|
- **<big>IsInt</big>** : 验证参数是否是整数(int, unit)。
|
||||||
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsInt)]
|
||||||
- **<big>IsIntStr</big>** : 验证字符串是否是可以转换为整数。
|
- **<big>IsIntStr</big>** : 验证字符串是否是可以转换为整数。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIntStr)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsIntStr)]
|
||||||
[[play](https://go.dev/play/p/jQRtFv-a0Rk)]
|
[[play](https://go.dev/play/p/jQRtFv-a0Rk)]
|
||||||
@@ -1283,10 +1398,12 @@ import "github.com/duke-git/lancet/v2/validator"
|
|||||||
[[play](https://go.dev/play/p/E2nt3unlmzP)]
|
[[play](https://go.dev/play/p/E2nt3unlmzP)]
|
||||||
- **<big>IsASCII</big>** : 验证字符串全部为 ASCII 字符。
|
- **<big>IsASCII</big>** : 验证字符串全部为 ASCII 字符。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsASCII)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsASCII)]
|
||||||
|
[[play](https://go.dev/play/p/hfQNPLX0jNa)]
|
||||||
- **<big>IsPrintable</big>** : 检查字符串是否全部为可打印字符。
|
- **<big>IsPrintable</big>** : 检查字符串是否全部为可打印字符。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsPrintable)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsPrintable)]
|
||||||
|
[[play](https://go.dev/play/p/Pe1FE2gdtTP)]
|
||||||
|
|
||||||
### 21. xerror 包实现一些错误处理函数
|
### 22. xerror 包实现一些错误处理函数
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/duke-git/lancet/v2/xerror"
|
import "github.com/duke-git/lancet/v2/xerror"
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import (
|
|||||||
- [CreateFile](#CreateFile)
|
- [CreateFile](#CreateFile)
|
||||||
- [CreateDir](#CreateDir)
|
- [CreateDir](#CreateDir)
|
||||||
- [CopyFile](#CopyFile)
|
- [CopyFile](#CopyFile)
|
||||||
|
- [CurrentPath](#CurrentPath)
|
||||||
- [FileMode](#FileMode)
|
- [FileMode](#FileMode)
|
||||||
- [MiMeType](#MiMeType)
|
- [MiMeType](#MiMeType)
|
||||||
- [IsExist](#IsExist)
|
- [IsExist](#IsExist)
|
||||||
@@ -151,6 +152,32 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="CurrentPath">CurrentPath</span>
|
||||||
|
|
||||||
|
<p>return current absolute path.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func CurrentPath() string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/fileutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
absPath := CurrentPath()
|
||||||
|
fmt.Println(absPath)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="FileMode">FileMode</span>
|
### <span id="FileMode">FileMode</span>
|
||||||
|
|
||||||
<p>Return file mode infomation.</p>
|
<p>Return file mode infomation.</p>
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import (
|
|||||||
- [CreateFile](#CreateFile)
|
- [CreateFile](#CreateFile)
|
||||||
- [CreateDir](#CreateDir)
|
- [CreateDir](#CreateDir)
|
||||||
- [CopyFile](#CopyFile)
|
- [CopyFile](#CopyFile)
|
||||||
|
- [CurrentPath](#CurrentPath)
|
||||||
- [FileMode](#FileMode)
|
- [FileMode](#FileMode)
|
||||||
- [MiMeType](#MiMeType)
|
- [MiMeType](#MiMeType)
|
||||||
- [IsExist](#IsExist)
|
- [IsExist](#IsExist)
|
||||||
@@ -150,6 +151,32 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="CurrentPath">CurrentPath</span>
|
||||||
|
|
||||||
|
<p>返回当前位置的绝对路径。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func CurrentPath() string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/fileutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
absPath := CurrentPath()
|
||||||
|
fmt.Println(absPath)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="FileMode">FileMode</span>
|
### <span id="FileMode">FileMode</span>
|
||||||
|
|
||||||
<p>获取文件mode信息</p>
|
<p>获取文件mode信息</p>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ formatter contains some functions for data formatting.
|
|||||||
## Source:
|
## Source:
|
||||||
|
|
||||||
- [https://github.com/duke-git/lancet/blob/main/formatter/formatter.go](https://github.com/duke-git/lancet/blob/main/formatter/formatter.go)
|
- [https://github.com/duke-git/lancet/blob/main/formatter/formatter.go](https://github.com/duke-git/lancet/blob/main/formatter/formatter.go)
|
||||||
|
- [https://github.com/duke-git/lancet/blob/main/formatter/byte.go](https://github.com/duke-git/lancet/blob/main/formatter/byte.go)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -23,6 +24,12 @@ import (
|
|||||||
## Index
|
## Index
|
||||||
|
|
||||||
- [Comma](#Comma)
|
- [Comma](#Comma)
|
||||||
|
- [Pretty](#Pretty)
|
||||||
|
- [PrettyToWriter](#PrettyToWriter)
|
||||||
|
- [DecimalBytes](#DecimalBytes)
|
||||||
|
- [BinaryBytes](#BinaryBytes)
|
||||||
|
- [ParseDecimalBytes](#ParseDecimalBytes)
|
||||||
|
- [ParseBinaryBytes](#ParseBinaryBytes)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -63,3 +70,241 @@ func main() {
|
|||||||
// ¥1,234,567
|
// ¥1,234,567
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="Pretty">Pretty</span>
|
||||||
|
|
||||||
|
<p>Pretty data to JSON string.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Pretty(v any) (string, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1, _ := formatter.Pretty([]string{"a", "b", "c"})
|
||||||
|
result2, _ := formatter.Pretty(map[string]int{"a": 1})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [
|
||||||
|
// "a",
|
||||||
|
// "b",
|
||||||
|
// "c"
|
||||||
|
// ]
|
||||||
|
// {
|
||||||
|
// "a": 1
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="PrettyToWriter">PrettyToWriter</span>
|
||||||
|
|
||||||
|
<p>Pretty encode data to writer.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func PrettyToWriter(v any, out io.Writer) error
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
type User struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Aage uint `json:"age"`
|
||||||
|
}
|
||||||
|
user := User{Name: "King", Aage: 10000}
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
err := formatter.PrettyToWriter(user, buf)
|
||||||
|
|
||||||
|
fmt.Println(buf)
|
||||||
|
fmt.Println(err)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// {
|
||||||
|
// "name": "King",
|
||||||
|
// "age": 10000
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// <nil>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="DecimalBytes">DecimalBytes</span>
|
||||||
|
|
||||||
|
<p>Returns a human readable byte size under decimal standard (base 1000). The precision parameter specifies the number of digits after the decimal point, which is 4 for default.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func DecimalBytes(size float64, precision ...int) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := formatter.DecimalBytes(1000)
|
||||||
|
result2 := formatter.DecimalBytes(1024)
|
||||||
|
result3 := formatter.DecimalBytes(1234567)
|
||||||
|
result4 := formatter.DecimalBytes(1234567, 3)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1KB
|
||||||
|
// 1.024KB
|
||||||
|
// 1.2346MB
|
||||||
|
// 1.235MB
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="BinaryBytes">BinaryBytes</span>
|
||||||
|
|
||||||
|
<p>Returns a human readable byte size under binary standard (base 1024). The precision parameter specifies the number of digits after the decimal point, which is 4 for default.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func BinaryBytes(size float64, precision ...int) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := formatter.BinaryBytes(1024)
|
||||||
|
result2 := formatter.BinaryBytes(1024 * 1024)
|
||||||
|
result3 := formatter.BinaryBytes(1234567)
|
||||||
|
result4 := formatter.BinaryBytes(1234567, 2)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1KiB
|
||||||
|
// 1MiB
|
||||||
|
// 1.1774MiB
|
||||||
|
// 1.18MiB
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ParseDecimalBytes">ParseDecimalBytes</span>
|
||||||
|
|
||||||
|
<p>Returns the human readable bytes size string into the amount it represents(base 1000).</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ParseDecimalBytes(size string) (uint64, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1, _ := formatter.ParseDecimalBytes("12")
|
||||||
|
result2, _ := formatter.ParseDecimalBytes("12k")
|
||||||
|
result3, _ := formatter.ParseDecimalBytes("12 Kb")
|
||||||
|
result4, _ := formatter.ParseDecimalBytes("12.2 kb")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 12
|
||||||
|
// 12000
|
||||||
|
// 12000
|
||||||
|
// 12200
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ParseBinaryBytes">ParseBinaryBytes</span>
|
||||||
|
|
||||||
|
<p>Returns the human readable bytes size string into the amount it represents(base 1024).</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ParseBinaryBytes(size string) (uint64, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1, _ := formatter.ParseBinaryBytes("12")
|
||||||
|
result2, _ := formatter.ParseBinaryBytes("12ki")
|
||||||
|
result3, _ := formatter.ParseBinaryBytes("12 KiB")
|
||||||
|
result4, _ := formatter.ParseBinaryBytes("12.2 kib")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 12
|
||||||
|
// 12288
|
||||||
|
// 12288
|
||||||
|
// 12492
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ formatter 格式化器包含一些数据格式化处理方法。
|
|||||||
## 源码:
|
## 源码:
|
||||||
|
|
||||||
- [https://github.com/duke-git/lancet/blob/main/formatter/formatter.go](https://github.com/duke-git/lancet/blob/main/formatter/formatter.go)
|
- [https://github.com/duke-git/lancet/blob/main/formatter/formatter.go](https://github.com/duke-git/lancet/blob/main/formatter/formatter.go)
|
||||||
|
- [https://github.com/duke-git/lancet/blob/main/formatter/byte.go](https://github.com/duke-git/lancet/blob/main/formatter/byte.go)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -23,6 +24,12 @@ import (
|
|||||||
## 目录
|
## 目录
|
||||||
|
|
||||||
- [Comma](#Comma)
|
- [Comma](#Comma)
|
||||||
|
- [Pretty](#Pretty)
|
||||||
|
- [PrettyToWriter](#PrettyToWriter)
|
||||||
|
- [DecimalBytes](#DecimalBytes)
|
||||||
|
- [BinaryBytes](#BinaryBytes)
|
||||||
|
- [ParseDecimalBytes](#ParseDecimalBytes)
|
||||||
|
- [ParseBinaryBytes](#ParseBinaryBytes)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -63,3 +70,241 @@ func main() {
|
|||||||
// ¥1,234,567
|
// ¥1,234,567
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="Pretty">Pretty</span>
|
||||||
|
|
||||||
|
<p>返回pretty JSON字符串.</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Pretty(v any) (string, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1, _ := formatter.Pretty([]string{"a", "b", "c"})
|
||||||
|
result2, _ := formatter.Pretty(map[string]int{"a": 1})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [
|
||||||
|
// "a",
|
||||||
|
// "b",
|
||||||
|
// "c"
|
||||||
|
// ]
|
||||||
|
// {
|
||||||
|
// "a": 1
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="PrettyToWriter">PrettyToWriter</span>
|
||||||
|
|
||||||
|
<p>Pretty encode数据到writer。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func PrettyToWriter(v any, out io.Writer) error
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
type User struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Aage uint `json:"age"`
|
||||||
|
}
|
||||||
|
user := User{Name: "King", Aage: 10000}
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
err := formatter.PrettyToWriter(user, buf)
|
||||||
|
|
||||||
|
fmt.Println(buf)
|
||||||
|
fmt.Println(err)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// {
|
||||||
|
// "name": "King",
|
||||||
|
// "age": 10000
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// <nil>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="DecimalBytes">DecimalBytes</span>
|
||||||
|
|
||||||
|
<p>返回十进制标准(以1000为基数)下的可读字节单位字符串。precision参数指定小数点后的位数,默认为4。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func DecimalBytes(size float64, precision ...int) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := formatter.DecimalBytes(1000)
|
||||||
|
result2 := formatter.DecimalBytes(1024)
|
||||||
|
result3 := formatter.DecimalBytes(1234567)
|
||||||
|
result4 := formatter.DecimalBytes(1234567, 3)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1KB
|
||||||
|
// 1.024KB
|
||||||
|
// 1.2346MB
|
||||||
|
// 1.235MB
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="BinaryBytes">BinaryBytes</span>
|
||||||
|
|
||||||
|
<p>返回binary标准(以1024为基数)下的可读字节单位字符串。precision参数指定小数点后的位数,默认为4。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func BinaryBytes(size float64, precision ...int) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := formatter.BinaryBytes(1024)
|
||||||
|
result2 := formatter.BinaryBytes(1024 * 1024)
|
||||||
|
result3 := formatter.BinaryBytes(1234567)
|
||||||
|
result4 := formatter.BinaryBytes(1234567, 2)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1KiB
|
||||||
|
// 1MiB
|
||||||
|
// 1.1774MiB
|
||||||
|
// 1.18MiB
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ParseDecimalBytes">ParseDecimalBytes</span>
|
||||||
|
|
||||||
|
<p>将字节单位字符串转换成其所表示的字节数(以1000为基数)。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ParseDecimalBytes(size string) (uint64, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1, _ := formatter.ParseDecimalBytes("12")
|
||||||
|
result2, _ := formatter.ParseDecimalBytes("12k")
|
||||||
|
result3, _ := formatter.ParseDecimalBytes("12 Kb")
|
||||||
|
result4, _ := formatter.ParseDecimalBytes("12.2 kb")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 12
|
||||||
|
// 12000
|
||||||
|
// 12000
|
||||||
|
// 12200
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ParseBinaryBytes">ParseBinaryBytes</span>
|
||||||
|
|
||||||
|
<p>将字节单位字符串转换成其所表示的字节数(以1024为基数)。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ParseBinaryBytes(size string) (uint64, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/formatter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1, _ := formatter.ParseBinaryBytes("12")
|
||||||
|
result2, _ := formatter.ParseBinaryBytes("12ki")
|
||||||
|
result3, _ := formatter.ParseBinaryBytes("12 KiB")
|
||||||
|
result4, _ := formatter.ParseBinaryBytes("12.2 kib")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 12
|
||||||
|
// 12288
|
||||||
|
// 12288
|
||||||
|
// 12492
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import (
|
|||||||
|
|
||||||
## Index
|
## Index
|
||||||
|
|
||||||
|
- [MapTo](#MapTo)
|
||||||
- [ForEach](#ForEach)
|
- [ForEach](#ForEach)
|
||||||
- [Filter](#Filter)
|
- [Filter](#Filter)
|
||||||
- [FilterByKeys](#FilterByKeys)
|
- [FilterByKeys](#FilterByKeys)
|
||||||
@@ -47,6 +48,64 @@ import (
|
|||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="MapTo">MapTo</span>
|
||||||
|
|
||||||
|
<p>Rry to map any interface to struct or base type.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func MapTo(src any, dst any) error
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
type (
|
||||||
|
Person struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Age int `json:"age"`
|
||||||
|
Phone string `json:"phone"`
|
||||||
|
Addr Address `json:"address"`
|
||||||
|
}
|
||||||
|
|
||||||
|
Address struct {
|
||||||
|
Street string `json:"street"`
|
||||||
|
Number int `json:"number"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
personInfo := map[string]interface{}{
|
||||||
|
"name": "Nothin",
|
||||||
|
"age": 28,
|
||||||
|
"phone": "123456789",
|
||||||
|
"address": map[string]interface{}{
|
||||||
|
"street": "test",
|
||||||
|
"number": 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var p Person
|
||||||
|
err := MapTo(personInfo, &p)
|
||||||
|
|
||||||
|
fmt.Println(err)
|
||||||
|
fmt.Println(p)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// <nil>
|
||||||
|
// {Nothin 28 123456789 {test 1}}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="ForEach">ForEach</span>
|
### <span id="ForEach">ForEach</span>
|
||||||
|
|
||||||
<p>Executes iteratee funcation for every key and value pair in map.</p>
|
<p>Executes iteratee funcation for every key and value pair in map.</p>
|
||||||
@@ -123,7 +182,7 @@ func main() {
|
|||||||
maputil.Filter(m, func(_ string, value int) {
|
maputil.Filter(m, func(_ string, value int) {
|
||||||
sum += value
|
sum += value
|
||||||
})
|
})
|
||||||
|
|
||||||
result := maputil.Filter(m, isEven)
|
result := maputil.Filter(m, isEven)
|
||||||
|
|
||||||
fmt.Println(result)
|
fmt.Println(result)
|
||||||
@@ -133,7 +192,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="FilterByKeys">FilterByKeys</span>
|
### <span id="FilterByKeys">FilterByKeys</span>
|
||||||
|
|
||||||
<p>Iterates over map, return a new map whose keys are all given keys.</p>
|
<p>Iterates over map, return a new map whose keys are all given keys.</p>
|
||||||
@@ -172,7 +230,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="FilterByValues">FilterByValues</span>
|
### <span id="FilterByValues">FilterByValues</span>
|
||||||
|
|
||||||
<p>Iterates over map, return a new map whose values are all given values.</p>
|
<p>Iterates over map, return a new map whose values are all given values.</p>
|
||||||
@@ -211,7 +268,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="OmitBy">OmitBy</span>
|
### <span id="OmitBy">OmitBy</span>
|
||||||
|
|
||||||
<p>OmitBy is the opposite of Filter, removes all the map elements for which the predicate function returns true.</p>
|
<p>OmitBy is the opposite of Filter, removes all the map elements for which the predicate function returns true.</p>
|
||||||
@@ -253,7 +309,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="OmitByKeys">OmitByKeys</span>
|
### <span id="OmitByKeys">OmitByKeys</span>
|
||||||
|
|
||||||
<p>The opposite of FilterByKeys, extracts all the map elements which keys are not omitted.</p>
|
<p>The opposite of FilterByKeys, extracts all the map elements which keys are not omitted.</p>
|
||||||
@@ -292,7 +347,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="OmitByValues">OmitByValues</span>
|
### <span id="OmitByValues">OmitByValues</span>
|
||||||
|
|
||||||
<p>The opposite of FilterByValues. remov all elements whose value are in the give slice.</p>
|
<p>The opposite of FilterByValues. remov all elements whose value are in the give slice.</p>
|
||||||
@@ -331,7 +385,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="Intersect">Intersect</span>
|
### <span id="Intersect">Intersect</span>
|
||||||
|
|
||||||
<p>Iterates over maps, return a new map of key and value pairs in all given maps.</p>
|
<p>Iterates over maps, return a new map of key and value pairs in all given maps.</p>
|
||||||
@@ -419,7 +472,7 @@ func main() {
|
|||||||
|
|
||||||
keys := maputil.Keys(m)
|
keys := maputil.Keys(m)
|
||||||
sort.Ints(keys)
|
sort.Ints(keys)
|
||||||
|
|
||||||
fmt.Println(keys)
|
fmt.Println(keys)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
@@ -498,7 +551,7 @@ func main() {
|
|||||||
"b": 22,
|
"b": 22,
|
||||||
"d": 33,
|
"d": 33,
|
||||||
}
|
}
|
||||||
|
|
||||||
result := maputil.Minus(m1, m2)
|
result := maputil.Minus(m1, m2)
|
||||||
|
|
||||||
fmt.Println(result)
|
fmt.Println(result)
|
||||||
@@ -638,7 +691,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="MapKeys">MapKeys</span>
|
### <span id="MapKeys">MapKeys</span>
|
||||||
|
|
||||||
<p>Transforms a map to other type map by manipulating it's keys.</p>
|
<p>Transforms a map to other type map by manipulating it's keys.</p>
|
||||||
@@ -717,7 +769,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="Entry">Entry</span>
|
### <span id="Entry">Entry</span>
|
||||||
|
|
||||||
<p>Transforms a map into array of key/value pairs.</p>
|
<p>Transforms a map into array of key/value pairs.</p>
|
||||||
@@ -763,7 +814,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="FromEntries">FromEntries</span>
|
### <span id="FromEntries">FromEntries</span>
|
||||||
|
|
||||||
<p>Creates a map based on a slice of key/value pairs.</p>
|
<p>Creates a map based on a slice of key/value pairs.</p>
|
||||||
@@ -841,7 +891,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="IsDisjoint">IsDisjoint</span>
|
### <span id="IsDisjoint">IsDisjoint</span>
|
||||||
|
|
||||||
<p>Checks two maps are disjoint if they have no keys in common</p>
|
<p>Checks two maps are disjoint if they have no keys in common</p>
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import (
|
|||||||
|
|
||||||
## 目录:
|
## 目录:
|
||||||
|
|
||||||
|
- [MapTo](#MapTo)
|
||||||
- [ForEach](#ForEach)
|
- [ForEach](#ForEach)
|
||||||
- [Filter](#Filter)
|
- [Filter](#Filter)
|
||||||
- [FilterByKeys](#FilterByKeys)
|
- [FilterByKeys](#FilterByKeys)
|
||||||
@@ -47,6 +48,63 @@ import (
|
|||||||
|
|
||||||
## API 文档:
|
## API 文档:
|
||||||
|
|
||||||
|
### <span id="MapTo">MapTo</span>
|
||||||
|
|
||||||
|
<p>快速将map或者其他类型映射到结构体或者指定类型。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func MapTo(src any, dst any) error
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/maputil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
type (
|
||||||
|
Person struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Age int `json:"age"`
|
||||||
|
Phone string `json:"phone"`
|
||||||
|
Addr Address `json:"address"`
|
||||||
|
}
|
||||||
|
|
||||||
|
Address struct {
|
||||||
|
Street string `json:"street"`
|
||||||
|
Number int `json:"number"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
personInfo := map[string]interface{}{
|
||||||
|
"name": "Nothin",
|
||||||
|
"age": 28,
|
||||||
|
"phone": "123456789",
|
||||||
|
"address": map[string]interface{}{
|
||||||
|
"street": "test",
|
||||||
|
"number": 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var p Person
|
||||||
|
err := MapTo(personInfo, &p)
|
||||||
|
|
||||||
|
fmt.Println(err)
|
||||||
|
fmt.Println(p)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// <nil>
|
||||||
|
// {Nothin 28 123456789 {test 1}}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="ForEach">ForEach</span>
|
### <span id="ForEach">ForEach</span>
|
||||||
|
|
||||||
<p>对map中的每对key和value执行iteratee函数</p>
|
<p>对map中的每对key和value执行iteratee函数</p>
|
||||||
@@ -80,7 +138,7 @@ func main() {
|
|||||||
maputil.ForEach(m, func(_ string, value int) {
|
maputil.ForEach(m, func(_ string, value int) {
|
||||||
sum += value
|
sum += value
|
||||||
})
|
})
|
||||||
|
|
||||||
fmt.Println(sum)
|
fmt.Println(sum)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
@@ -123,7 +181,7 @@ func main() {
|
|||||||
maputil.Filter(m, func(_ string, value int) {
|
maputil.Filter(m, func(_ string, value int) {
|
||||||
sum += value
|
sum += value
|
||||||
})
|
})
|
||||||
|
|
||||||
result := Filter(m, isEven)
|
result := Filter(m, isEven)
|
||||||
|
|
||||||
fmt.Println(result)
|
fmt.Println(result)
|
||||||
@@ -171,7 +229,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="FilterByValues">FilterByValues</span>
|
### <span id="FilterByValues">FilterByValues</span>
|
||||||
|
|
||||||
<p>迭代map, 返回一个新map,其value都是给定的value值。</p>
|
<p>迭代map, 返回一个新map,其value都是给定的value值。</p>
|
||||||
@@ -210,7 +267,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="OmitBy">OmitBy</span>
|
### <span id="OmitBy">OmitBy</span>
|
||||||
|
|
||||||
<p>Filter的反向操作, 迭代map中的每对key和value, 删除符合predicate函数的key, value, 返回新map。</p>
|
<p>Filter的反向操作, 迭代map中的每对key和value, 删除符合predicate函数的key, value, 返回新map。</p>
|
||||||
@@ -252,7 +308,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="OmitByKeys">OmitByKeys</span>
|
### <span id="OmitByKeys">OmitByKeys</span>
|
||||||
|
|
||||||
<p>FilterByKeys的反向操作, 迭代map, 返回一个新map,其key不包括给定的key值。</p>
|
<p>FilterByKeys的反向操作, 迭代map, 返回一个新map,其key不包括给定的key值。</p>
|
||||||
@@ -291,7 +346,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="OmitByValues">OmitByValues</span>
|
### <span id="OmitByValues">OmitByValues</span>
|
||||||
|
|
||||||
<p>FilterByValues的反向操作, 迭代map, 返回一个新map,其value不包括给定的value值。</p>
|
<p>FilterByValues的反向操作, 迭代map, 返回一个新map,其value不包括给定的value值。</p>
|
||||||
@@ -416,7 +470,7 @@ func main() {
|
|||||||
|
|
||||||
keys := maputil.Keys(m)
|
keys := maputil.Keys(m)
|
||||||
sort.Ints(keys)
|
sort.Ints(keys)
|
||||||
|
|
||||||
fmt.Println(keys)
|
fmt.Println(keys)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
@@ -453,7 +507,7 @@ func main() {
|
|||||||
1: "1",
|
1: "1",
|
||||||
3: "2",
|
3: "2",
|
||||||
}
|
}
|
||||||
|
|
||||||
result := maputil.Merge(m1, m2)
|
result := maputil.Merge(m1, m2)
|
||||||
|
|
||||||
fmt.Println(result)
|
fmt.Println(result)
|
||||||
@@ -632,7 +686,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="MapKeys">MapKeys</span>
|
### <span id="MapKeys">MapKeys</span>
|
||||||
|
|
||||||
<p>操作map的每个key,然后转为新的map。</p>
|
<p>操作map的每个key,然后转为新的map。</p>
|
||||||
@@ -711,7 +764,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="Entry">Entry</span>
|
### <span id="Entry">Entry</span>
|
||||||
|
|
||||||
<p>将map转换为键/值对切片。</p>
|
<p>将map转换为键/值对切片。</p>
|
||||||
@@ -757,7 +809,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="FromEntries">FromEntries</span>
|
### <span id="FromEntries">FromEntries</span>
|
||||||
|
|
||||||
<p>基于键/值对的切片创建map。</p>
|
<p>基于键/值对的切片创建map。</p>
|
||||||
|
|||||||
@@ -62,7 +62,9 @@ import (
|
|||||||
- [FlatMap](#FlatMap)
|
- [FlatMap](#FlatMap)
|
||||||
- [Merge](#Merge)
|
- [Merge](#Merge)
|
||||||
- [Reverse](#Reverse)
|
- [Reverse](#Reverse)
|
||||||
- [Reduce](#Reduce)
|
- [Reduce<sup>deprecated</sup>](#Reduce)
|
||||||
|
- [ReduceBy](#ReduceBy)
|
||||||
|
- [ReduceRight](#ReduceRight)
|
||||||
- [Replace](#Replace)
|
- [Replace](#Replace)
|
||||||
- [ReplaceAll](#ReplaceAll)
|
- [ReplaceAll](#ReplaceAll)
|
||||||
- [Repeat](#Repeat)
|
- [Repeat](#Repeat)
|
||||||
@@ -1472,7 +1474,7 @@ func main() {
|
|||||||
|
|
||||||
### <span id="Reduce">Reduce</span>
|
### <span id="Reduce">Reduce</span>
|
||||||
|
|
||||||
<p>Reduce slice.</p>
|
<p>Reduce slice.(Deprecated: use ReduceBy)</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
@@ -1504,6 +1506,72 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="ReduceBy">ReduceBy</span>
|
||||||
|
|
||||||
|
<p>Produces a value from slice by accumulating the result of each element as passed through the reducer function.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ReduceBy[T any, U any](slice []T, initial U, reducer func(index int, item T, agg U) U) U
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/slice"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := slice.ReduceBy([]int{1, 2, 3, 4}, 0, func(_ int, item int, agg int) int {
|
||||||
|
return agg + item
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := slice.ReduceBy([]int{1, 2, 3, 4}, "", func(_ int, item int, agg string) string {
|
||||||
|
return agg + fmt.Sprintf("%v", item)
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 10
|
||||||
|
// 1234
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ReduceRight">ReduceRight</span>
|
||||||
|
|
||||||
|
<p>ReduceRight is like ReduceBy, but it iterates over elements of slice from right to left.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ReduceRight[T any, U any](slice []T, initial U, reducer func(index int, item T, agg U) U) U
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/slice"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result := slice.ReduceRight([]int{1, 2, 3, 4}, "", func(_ int, item int, agg string) string {
|
||||||
|
return agg + fmt.Sprintf("%v", item)
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 4321
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="Replace">Replace</span>
|
### <span id="Replace">Replace</span>
|
||||||
|
|
||||||
<p>Returns a copy of the slice with the first n non-overlapping instances of old replaced by new.</p>
|
<p>Returns a copy of the slice with the first n non-overlapping instances of old replaced by new.</p>
|
||||||
|
|||||||
@@ -62,7 +62,9 @@ import (
|
|||||||
- [FlatMap](#FlatMap)
|
- [FlatMap](#FlatMap)
|
||||||
- [Merge](#Merge)
|
- [Merge](#Merge)
|
||||||
- [Reverse](#Reverse)
|
- [Reverse](#Reverse)
|
||||||
- [Reduce](#Reduce)
|
- [Reduce<sup>deprecated</sup>](#Reduce)
|
||||||
|
- [ReduceBy](#ReduceBy)
|
||||||
|
- [ReduceRight](#ReduceRight)
|
||||||
- [Replace](#Replace)
|
- [Replace](#Replace)
|
||||||
- [ReplaceAll](#ReplaceAll)
|
- [ReplaceAll](#ReplaceAll)
|
||||||
- [Repeat](#Repeat)
|
- [Repeat](#Repeat)
|
||||||
@@ -1473,7 +1475,7 @@ func main() {
|
|||||||
|
|
||||||
### <span id="Reduce">Reduce</span>
|
### <span id="Reduce">Reduce</span>
|
||||||
|
|
||||||
<p>将切片中的元素依次运行iteratee函数,返回运行结果</p>
|
<p>将切片中的元素依次运行iteratee函数,返回运行结果(废弃:建议使用ReduceBy)</p>
|
||||||
|
|
||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
@@ -1505,6 +1507,72 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="ReduceBy">ReduceBy</span>
|
||||||
|
|
||||||
|
<p>对切片元素执行reduce操作。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ReduceBy[T any, U any](slice []T, initial U, reducer func(index int, item T, agg U) U) U
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/slice"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := slice.ReduceBy([]int{1, 2, 3, 4}, 0, func(_ int, item int, agg int) int {
|
||||||
|
return agg + item
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := slice.ReduceBy([]int{1, 2, 3, 4}, "", func(_ int, item int, agg string) string {
|
||||||
|
return agg + fmt.Sprintf("%v", item)
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 10
|
||||||
|
// 1234
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ReduceRight">ReduceRight</span>
|
||||||
|
|
||||||
|
<p>类似ReduceBy操作,迭代切片元素顺序从右至左。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ReduceRight[T any, U any](slice []T, initial U, reducer func(index int, item T, agg U) U) U
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/slice"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result := slice.ReduceRight([]int{1, 2, 3, 4}, "", func(_ int, item int, agg string) string {
|
||||||
|
return agg + fmt.Sprintf("%v", item)
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 4321
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="Replace">Replace</span>
|
### <span id="Replace">Replace</span>
|
||||||
|
|
||||||
<p>返回切片的副本,其中前n个不重叠的old替换为new</p>
|
<p>返回切片的副本,其中前n个不重叠的old替换为new</p>
|
||||||
|
|||||||
907
docs/stream.md
Normal file
907
docs/stream.md
Normal file
@@ -0,0 +1,907 @@
|
|||||||
|
# Stream
|
||||||
|
|
||||||
|
Package stream 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. it's feature is very limited.
|
||||||
|
|
||||||
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
## Source:
|
||||||
|
|
||||||
|
- [https://github.com/duke-git/lancet/blob/main/stream/stream.go](https://github.com/duke-git/lancet/blob/main/stream/stream.go)
|
||||||
|
|
||||||
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
## Usage:
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
## Index
|
||||||
|
|
||||||
|
- [Of](#Of)
|
||||||
|
- [FromSlice](#FromSlice)
|
||||||
|
- [FromChannel](#FromChannel)
|
||||||
|
- [FromRange](#FromRange)
|
||||||
|
- [Generate](#Generate)
|
||||||
|
- [Concat](#Concat)
|
||||||
|
- [Distinct](#Distinct)
|
||||||
|
- [Filter](#Filter)
|
||||||
|
- [Map](#Map)
|
||||||
|
- [Peek](#Peek)
|
||||||
|
- [Skip](#Skip)
|
||||||
|
- [Limit](#Limit)
|
||||||
|
- [Reverse](#Reverse)
|
||||||
|
- [Range](#Range)
|
||||||
|
- [Sorted](#Sorted)
|
||||||
|
- [ForEach](#ForEach)
|
||||||
|
- [Reduce](#Reduce)
|
||||||
|
- [FindFirst](#FindFirst)
|
||||||
|
- [Max](#Max)
|
||||||
|
- [Min](#Min)
|
||||||
|
- [AllMatch](#AllMatch)
|
||||||
|
- [AnyMatch](#AnyMatch)
|
||||||
|
- [NoneMatch](#NoneMatch)
|
||||||
|
- [Count](#Count)
|
||||||
|
- [ToSlice](#ToSlice)
|
||||||
|
|
||||||
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
### <span id="Of">Of</span>
|
||||||
|
|
||||||
|
<p>Creates a stream whose elements are the specified values.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Of[T any](elems ...T) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := stream.Of(1, 2, 3)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="FromSlice">FromSlice</span>
|
||||||
|
|
||||||
|
<p>Creates a stream from slice.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func FromSlice[T any](source []T) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="FromChannel">FromChannel</span>
|
||||||
|
|
||||||
|
<p>Creates a stream from channel.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func FromChannel[T any](source <-chan T) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ch := make(chan int)
|
||||||
|
go func() {
|
||||||
|
for i := 1; i < 4; i++ {
|
||||||
|
ch <- i
|
||||||
|
}
|
||||||
|
close(ch)
|
||||||
|
}()
|
||||||
|
|
||||||
|
s := stream.FromChannel(ch)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="FromRange">FromRange</span>
|
||||||
|
|
||||||
|
<p>Creates a number stream from start to end. both start and end are included. [start, end]</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func FromRange[T constraints.Integer | constraints.Float](start, end, step T) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := stream.FromRange(1, 5, 1)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3 4 5]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Generate">Generate</span>
|
||||||
|
|
||||||
|
<p>Creates a stream where each element is generated by the provided generater function.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Generate[T any](generator func() func() (item T, ok bool)) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
n := 0
|
||||||
|
max := 4
|
||||||
|
|
||||||
|
generator := func() func() (int, bool) {
|
||||||
|
return func() (int, bool) {
|
||||||
|
n++
|
||||||
|
return n, n < max
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s := stream.Generate(generator)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Concat">Concat</span>
|
||||||
|
|
||||||
|
<p>Creates a lazily concatenated stream whose elements are all the elements of the first stream followed by all the elements of the second stream.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Concat[T any](a, b stream[T]) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s1 := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
s2 := stream.FromSlice([]int{4, 5, 6})
|
||||||
|
|
||||||
|
s := Concat(s1, s2)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3 4 5 6]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Distinct">Distinct</span>
|
||||||
|
|
||||||
|
<p>Creates returns a stream that removes the duplicated items. <b>Support chainable operation</b></p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Distinct() stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 2, 3, 3, 3})
|
||||||
|
distinct := original.Distinct()
|
||||||
|
|
||||||
|
data1 := original.ToSlice()
|
||||||
|
data2 := distinct.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data1)
|
||||||
|
fmt.Println(data2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 2 3 3 3]
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Filter">Filter</span>
|
||||||
|
|
||||||
|
<p>Returns a stream consisting of the elements of this stream that match the given predicate. <b>Support chainable operation</b></p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Filter(predicate func(item T) bool) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3, 4, 5})
|
||||||
|
|
||||||
|
isEven := func(n int) bool {
|
||||||
|
return n%2 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
even := original.Filter(isEven)
|
||||||
|
|
||||||
|
fmt.Println(even.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [2 4]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Map">Map</span>
|
||||||
|
|
||||||
|
<p>Returns a stream consisting of the elements of this stream that apply the given function to elements of stream. <b>Support chainable operation</b></p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Map(mapper func(item T) T) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
addOne := func(n int) int {
|
||||||
|
return n + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
increament := original.Map(addOne)
|
||||||
|
|
||||||
|
fmt.Println(increament.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [2 3 4]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Peek">Peek</span>
|
||||||
|
|
||||||
|
<p>Returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream. <b>Support chainable operation</b></p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Peek(consumer func(item T)) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
data := []string{}
|
||||||
|
peekStream := original.Peek(func(n int) {
|
||||||
|
data = append(data, fmt.Sprint("value", n))
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(original.ToSlice())
|
||||||
|
fmt.Println(peekStream.ToSlice())
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
// [1 2 3]
|
||||||
|
// [value1 value2 value3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Skip">Skip</span>
|
||||||
|
|
||||||
|
<p>Returns a stream consisting of the remaining elements of this stream after discarding the first n elements of the stream. If this stream contains fewer than n elements then an empty stream will be returned. <b>Support chainable operation</b></p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Skip(n int) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3, 4})
|
||||||
|
|
||||||
|
s1 := original.Skip(-1)
|
||||||
|
s2 := original.Skip(0)
|
||||||
|
s3 := original.Skip(1)
|
||||||
|
s4 := original.Skip(5)
|
||||||
|
|
||||||
|
fmt.Println(s1.ToSlice())
|
||||||
|
fmt.Println(s2.ToSlice())
|
||||||
|
fmt.Println(s3.ToSlice())
|
||||||
|
fmt.Println(s4.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3 4]
|
||||||
|
// [1 2 3 4]
|
||||||
|
// [2 3 4]
|
||||||
|
// []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Limit">Limit</span>
|
||||||
|
|
||||||
|
<p>Returns a stream consisting of the elements of this stream, truncated to be no longer than maxSize in length. <b>Support chainable operation</b></p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Limit(maxSize int) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3, 4})
|
||||||
|
|
||||||
|
s1 := original.Limit(-1)
|
||||||
|
s2 := original.Limit(0)
|
||||||
|
s3 := original.Limit(1)
|
||||||
|
s4 := original.Limit(5)
|
||||||
|
|
||||||
|
fmt.Println(s1.ToSlice())
|
||||||
|
fmt.Println(s2.ToSlice())
|
||||||
|
fmt.Println(s3.ToSlice())
|
||||||
|
fmt.Println(s4.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// []
|
||||||
|
// []
|
||||||
|
// [1]
|
||||||
|
// [1 2 3 4]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Reverse">Reverse</span>
|
||||||
|
|
||||||
|
<p>Returns a stream whose elements are reverse order of given stream. <b>Support chainable operation</b></p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Reverse() stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
reverse := original.Reverse()
|
||||||
|
|
||||||
|
fmt.Println(reverse.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [3 2 1]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Range">Range</span>
|
||||||
|
|
||||||
|
<p>Returns a stream whose elements are in the range from start(included) to end(excluded) original stream.<b>Support chainable operation</b></p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Range(start, end int) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
s1 := original.Range(0, 0)
|
||||||
|
s2 := original.Range(0, 1)
|
||||||
|
s3 := original.Range(0, 3)
|
||||||
|
s4 := original.Range(1, 2)
|
||||||
|
|
||||||
|
fmt.Println(s1.ToSlice())
|
||||||
|
fmt.Println(s2.ToSlice())
|
||||||
|
fmt.Println(s3.ToSlice())
|
||||||
|
fmt.Println(s4.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// []
|
||||||
|
// [1]
|
||||||
|
// [1 2 3]
|
||||||
|
// [2]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Sorted">Sorted</span>
|
||||||
|
|
||||||
|
<p>Returns a stream consisting of the elements of this stream, sorted according to the provided less function.<b>Support chainable operation</b></p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Sorted(less func(a, b T) bool) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{4, 2, 1, 3})
|
||||||
|
|
||||||
|
sorted := original.Sorted(func(a, b int) bool { return a < b })
|
||||||
|
|
||||||
|
fmt.Println(original.ToSlice())
|
||||||
|
fmt.Println(sorted.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [4 2 1 3]
|
||||||
|
// [1 2 3 4]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ForEach">ForEach</span>
|
||||||
|
|
||||||
|
<p>Performs an action for each element of this stream.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) ForEach(action func(item T))
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result := 0
|
||||||
|
original.ForEach(func(item int) {
|
||||||
|
result += item
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 6
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Reduce">Reduce</span>
|
||||||
|
|
||||||
|
<p>Performs a reduction on the elements of this stream, using an associative accumulation function, and returns an Optional describing the reduced value, if any.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Reduce(initial T, accumulator func(a, b T) T) T
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result := original.Reduce(0, func(a, b int) int {
|
||||||
|
return a + b
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 6
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="FindFirst">FindFirst</span>
|
||||||
|
|
||||||
|
<p>Returns the first element of this stream and true, or zero value and false if the stream is empty.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) FindFirst() (T, bool)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result, ok := original.FindFirst()
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
fmt.Println(ok)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Max">Max</span>
|
||||||
|
|
||||||
|
<p>Returns the maximum element of this stream according to the provided less function. less fuction: a > b</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Max(less func(a, b T) bool) (T, bool)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{4, 2, 1, 3})
|
||||||
|
|
||||||
|
max, ok := original.Max(func(a, b int) bool { return a > b })
|
||||||
|
|
||||||
|
fmt.Println(max)
|
||||||
|
fmt.Println(ok)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 4
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Min">Min</span>
|
||||||
|
|
||||||
|
<p>Returns the minimum element of this stream according to the provided less function. less fuction: a < b</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Min(less func(a, b T) bool) (T, bool)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{4, 2, 1, 3})
|
||||||
|
|
||||||
|
min, ok := original.Min(func(a, b int) bool { return a < b })
|
||||||
|
|
||||||
|
fmt.Println(min)
|
||||||
|
fmt.Println(ok)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="AllMatch">AllMatch</span>
|
||||||
|
|
||||||
|
<p>Returns whether all elements of this stream match the provided predicate.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) AllMatch(predicate func(item T) bool) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result1 := original.AllMatch(func(item int) bool {
|
||||||
|
return item > 0
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := original.AllMatch(func(item int) bool {
|
||||||
|
return item > 1
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="AnyMatch">AnyMatch</span>
|
||||||
|
|
||||||
|
<p>Returns whether any elements of this stream match the provided predicate.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) AnyMatch(predicate func(item T) bool) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result1 := original.AnyMatch(func(item int) bool {
|
||||||
|
return item > 1
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := original.AnyMatch(func(item int) bool {
|
||||||
|
return item > 3
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="NoneMatch">NoneMatch</span>
|
||||||
|
|
||||||
|
<p>Returns whether no elements of this stream match the provided predicate.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) NoneMatch(predicate func(item T) bool) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result1 := original.NoneMatch(func(item int) bool {
|
||||||
|
return item > 3
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := original.NoneMatch(func(item int) bool {
|
||||||
|
return item > 1
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Count">Count</span>
|
||||||
|
|
||||||
|
<p>Returns the count of elements in the stream.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Count() int
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s1 := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
s2 := stream.FromSlice([]int{})
|
||||||
|
|
||||||
|
fmt.Println(s1.Count())
|
||||||
|
fmt.Println(s2.Count())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 3
|
||||||
|
// 0
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ToSlice">ToSlice</span>
|
||||||
|
|
||||||
|
<p>Returns the elements in the stream.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) ToSlice() []T
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := stream.Of(1, 2, 3)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
```
|
||||||
907
docs/stream_zh-CN.md
Normal file
907
docs/stream_zh-CN.md
Normal file
@@ -0,0 +1,907 @@
|
|||||||
|
# Stream
|
||||||
|
|
||||||
|
Stream 流,该包仅验证简单 stream 实现,功能有限。
|
||||||
|
|
||||||
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
## 源码:
|
||||||
|
|
||||||
|
- [https://github.com/duke-git/lancet/blob/main/stream/stream.go](https://github.com/duke-git/lancet/blob/main/stream/stream.go)
|
||||||
|
|
||||||
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
## 用法:
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
## 目录
|
||||||
|
|
||||||
|
- [Of](#Of)
|
||||||
|
- [FromSlice](#FromSlice)
|
||||||
|
- [FromChannel](#FromChannel)
|
||||||
|
- [FromRange](#FromRange)
|
||||||
|
- [Generate](#Generate)
|
||||||
|
- [Concat](#Concat)
|
||||||
|
- [Distinct](#Distinct)
|
||||||
|
- [Filter](#Filter)
|
||||||
|
- [Map](#Map)
|
||||||
|
- [Peek](#Peek)
|
||||||
|
- [Skip](#Skip)
|
||||||
|
- [Limit](#Limit)
|
||||||
|
- [Reverse](#Reverse)
|
||||||
|
- [Range](#Range)
|
||||||
|
- [Sorted](#Sorted)
|
||||||
|
- [ForEach](#ForEach)
|
||||||
|
- [Reduce](#Reduce)
|
||||||
|
- [FindFirst](#FindFirst)
|
||||||
|
- [Max](#Max)
|
||||||
|
- [Min](#Min)
|
||||||
|
- [AllMatch](#AllMatch)
|
||||||
|
- [AnyMatch](#AnyMatch)
|
||||||
|
- [NoneMatch](#NoneMatch)
|
||||||
|
- [Count](#Count)
|
||||||
|
- [ToSlice](#ToSlice)
|
||||||
|
|
||||||
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
|
## 文档
|
||||||
|
|
||||||
|
### <span id="Of">Of</span>
|
||||||
|
|
||||||
|
<p>创建元素为指定值的stream。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Of[T any](elems ...T) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := stream.Of(1, 2, 3)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="FromSlice">FromSlice</span>
|
||||||
|
|
||||||
|
<p>从切片创建stream。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func FromSlice[T any](source []T) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="FromChannel">FromChannel</span>
|
||||||
|
|
||||||
|
<p>从通道创建stream。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func FromChannel[T any](source <-chan T) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ch := make(chan int)
|
||||||
|
go func() {
|
||||||
|
for i := 1; i < 4; i++ {
|
||||||
|
ch <- i
|
||||||
|
}
|
||||||
|
close(ch)
|
||||||
|
}()
|
||||||
|
|
||||||
|
s := stream.FromChannel(ch)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="FromRange">FromRange</span>
|
||||||
|
|
||||||
|
<p>指定一个范围创建stream, 范围两端点值都包括在内。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func FromRange[T constraints.Integer | constraints.Float](start, end, step T) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := stream.FromRange(1, 5, 1)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3 4 5]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Generate">Generate</span>
|
||||||
|
|
||||||
|
<p>创建一个stream,其中每个元素都由提供的生成器函数生成</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Generate[T any](generator func() func() (item T, ok bool)) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
n := 0
|
||||||
|
max := 4
|
||||||
|
|
||||||
|
generator := func() func() (int, bool) {
|
||||||
|
return func() (int, bool) {
|
||||||
|
n++
|
||||||
|
return n, n < max
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s := stream.Generate(generator)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Concat">Concat</span>
|
||||||
|
|
||||||
|
<p>创建一个延迟连接stream,其元素是第一个stream的所有元素,后跟第二个stream的全部元素。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Concat[T any](a, b stream[T]) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s1 := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
s2 := stream.FromSlice([]int{4, 5, 6})
|
||||||
|
|
||||||
|
s := Concat(s1, s2)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3 4 5 6]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Distinct">Distinct</span>
|
||||||
|
|
||||||
|
<p>创建并返回一个stream,用于删除重复的项。 <b>支持链式操作</b></p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Distinct() stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 2, 3, 3, 3})
|
||||||
|
distinct := original.Distinct()
|
||||||
|
|
||||||
|
data1 := original.ToSlice()
|
||||||
|
data2 := distinct.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data1)
|
||||||
|
fmt.Println(data2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 2 3 3 3]
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Filter">Filter</span>
|
||||||
|
|
||||||
|
<p>返回一个通过判定函数的stream <b>支持链式操作</b></p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Filter(predicate func(item T) bool) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3, 4, 5})
|
||||||
|
|
||||||
|
isEven := func(n int) bool {
|
||||||
|
return n%2 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
even := original.Filter(isEven)
|
||||||
|
|
||||||
|
fmt.Println(even.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [2 4]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Map">Map</span>
|
||||||
|
|
||||||
|
<p>返回一个stream,该stream由将给定函数应用于源stream元素的元素组成。<b>支持链式操作</b></p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Map(mapper func(item T) T) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
addOne := func(n int) int {
|
||||||
|
return n + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
increament := original.Map(addOne)
|
||||||
|
|
||||||
|
fmt.Println(increament.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [2 3 4]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Peek">Peek</span>
|
||||||
|
|
||||||
|
<p>返回一个由源stream的元素组成的stream,并在从生成的stream中消耗元素时对每个元素执行所提供的操作。 <b>支持链式操作</b></p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Peek(consumer func(item T)) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
data := []string{}
|
||||||
|
peekStream := original.Peek(func(n int) {
|
||||||
|
data = append(data, fmt.Sprint("value", n))
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(original.ToSlice())
|
||||||
|
fmt.Println(peekStream.ToSlice())
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
// [1 2 3]
|
||||||
|
// [value1 value2 value3]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Skip">Skip</span>
|
||||||
|
|
||||||
|
<p>在丢弃stream的前n个元素后,返回由源stream的其余元素组成的stream。如果此stream包含的元素少于n个,则将返回一个空stream。<b>支持链式操作</b></p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Skip(n int) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3, 4})
|
||||||
|
|
||||||
|
s1 := original.Skip(-1)
|
||||||
|
s2 := original.Skip(0)
|
||||||
|
s3 := original.Skip(1)
|
||||||
|
s4 := original.Skip(5)
|
||||||
|
|
||||||
|
fmt.Println(s1.ToSlice())
|
||||||
|
fmt.Println(s2.ToSlice())
|
||||||
|
fmt.Println(s3.ToSlice())
|
||||||
|
fmt.Println(s4.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3 4]
|
||||||
|
// [1 2 3 4]
|
||||||
|
// [2 3 4]
|
||||||
|
// []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Limit">Limit</span>
|
||||||
|
|
||||||
|
<p>返回由源stream的元素组成的stream,该stream被截断为长度不超过maxSize。<b>支持链式操作</b></p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Limit(maxSize int) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3, 4})
|
||||||
|
|
||||||
|
s1 := original.Limit(-1)
|
||||||
|
s2 := original.Limit(0)
|
||||||
|
s3 := original.Limit(1)
|
||||||
|
s4 := original.Limit(5)
|
||||||
|
|
||||||
|
fmt.Println(s1.ToSlice())
|
||||||
|
fmt.Println(s2.ToSlice())
|
||||||
|
fmt.Println(s3.ToSlice())
|
||||||
|
fmt.Println(s4.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// []
|
||||||
|
// []
|
||||||
|
// [1]
|
||||||
|
// [1 2 3 4]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Reverse">Reverse</span>
|
||||||
|
|
||||||
|
<p>返回元素与源stream的顺序相反的stream。<b>支持链式操作</b></p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Reverse() stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
reverse := original.Reverse()
|
||||||
|
|
||||||
|
fmt.Println(reverse.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [3 2 1]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Range">Range</span>
|
||||||
|
|
||||||
|
<p>返回一个stream,该stream的元素在从源stream的开始(包含)到结束(排除)的范围内。<b>支持链式操作</b></p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Range(start, end int) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
s1 := original.Range(0, 0)
|
||||||
|
s2 := original.Range(0, 1)
|
||||||
|
s3 := original.Range(0, 3)
|
||||||
|
s4 := original.Range(1, 2)
|
||||||
|
|
||||||
|
fmt.Println(s1.ToSlice())
|
||||||
|
fmt.Println(s2.ToSlice())
|
||||||
|
fmt.Println(s3.ToSlice())
|
||||||
|
fmt.Println(s4.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// []
|
||||||
|
// [1]
|
||||||
|
// [1 2 3]
|
||||||
|
// [2]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Sorted">Sorted</span>
|
||||||
|
|
||||||
|
<p>返回一个stream,该stream由源stream的元素组成,并根据提供的less函数进行排序。<b>支持链式操作</b></p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Sorted(less func(a, b T) bool) stream[T]
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{4, 2, 1, 3})
|
||||||
|
|
||||||
|
sorted := original.Sorted(func(a, b int) bool { return a < b })
|
||||||
|
|
||||||
|
fmt.Println(original.ToSlice())
|
||||||
|
fmt.Println(sorted.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [4 2 1 3]
|
||||||
|
// [1 2 3 4]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ForEach">ForEach</span>
|
||||||
|
|
||||||
|
<p>对stream的每个元素执行一个操作。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) ForEach(action func(item T))
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result := 0
|
||||||
|
original.ForEach(func(item int) {
|
||||||
|
result += item
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 6
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Reduce">Reduce</span>
|
||||||
|
|
||||||
|
<p>使用关联累加函数对stream的元素执行reduce操作,并reduce操作结果(如果有)。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Reduce(initial T, accumulator func(a, b T) T) T
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result := original.Reduce(0, func(a, b int) int {
|
||||||
|
return a + b
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 6
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="FindFirst">FindFirst</span>
|
||||||
|
|
||||||
|
<p>返回此stream的第一个元素和true,如果stream为空,则返回零值和false。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) FindFirst() (T, bool)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result, ok := original.FindFirst()
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
fmt.Println(ok)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Max">Max</span>
|
||||||
|
|
||||||
|
<p>根据提供的less函数返回stream的最大元素。less 函数: a > b</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Max(less func(a, b T) bool) (T, bool)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{4, 2, 1, 3})
|
||||||
|
|
||||||
|
max, ok := original.Max(func(a, b int) bool { return a > b })
|
||||||
|
|
||||||
|
fmt.Println(max)
|
||||||
|
fmt.Println(ok)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 4
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Min">Min</span>
|
||||||
|
|
||||||
|
<p>根据提供的less函数返回stream的最小元素。less函数: a < b</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Min(less func(a, b T) bool) (T, bool)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{4, 2, 1, 3})
|
||||||
|
|
||||||
|
min, ok := original.Min(func(a, b int) bool { return a < b })
|
||||||
|
|
||||||
|
fmt.Println(min)
|
||||||
|
fmt.Println(ok)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="AllMatch">AllMatch</span>
|
||||||
|
|
||||||
|
<p>判断stream的所有元素是否全部匹配指定判定函数。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) AllMatch(predicate func(item T) bool) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result1 := original.AllMatch(func(item int) bool {
|
||||||
|
return item > 0
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := original.AllMatch(func(item int) bool {
|
||||||
|
return item > 1
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="AnyMatch">AnyMatch</span>
|
||||||
|
|
||||||
|
<p>判断stream是否包含匹配指定判定函数的元素。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) AnyMatch(predicate func(item T) bool) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result1 := original.AnyMatch(func(item int) bool {
|
||||||
|
return item > 1
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := original.AnyMatch(func(item int) bool {
|
||||||
|
return item > 3
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="NoneMatch">NoneMatch</span>
|
||||||
|
|
||||||
|
<p>判断stream的元素是否全部不匹配指定的判定函数。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) NoneMatch(predicate func(item T) bool) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
original := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result1 := original.NoneMatch(func(item int) bool {
|
||||||
|
return item > 3
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := original.NoneMatch(func(item int) bool {
|
||||||
|
return item > 1
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Count">Count</span>
|
||||||
|
|
||||||
|
<p>返回stream中元素的数量。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) Count() int
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s1 := stream.FromSlice([]int{1, 2, 3})
|
||||||
|
s2 := stream.FromSlice([]int{})
|
||||||
|
|
||||||
|
fmt.Println(s1.Count())
|
||||||
|
fmt.Println(s2.Count())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 3
|
||||||
|
// 0
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ToSlice">ToSlice</span>
|
||||||
|
|
||||||
|
<p>返回stream中的元素切片。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (s stream[T]) ToSlice() []T
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/stream"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := stream.Of(1, 2, 3)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -38,11 +38,14 @@ import (
|
|||||||
- [IsDns](#IsDns)
|
- [IsDns](#IsDns)
|
||||||
- [IsEmail](#IsEmail)
|
- [IsEmail](#IsEmail)
|
||||||
- [IsEmptyString](#IsEmptyString)
|
- [IsEmptyString](#IsEmptyString)
|
||||||
|
- [IsInt](#IsInt)
|
||||||
|
- [IsFloat](#IsFloat)
|
||||||
|
- [IsNumber](#IsNumber)
|
||||||
|
- [IsIntStr](#IsIntStr)
|
||||||
- [IsFloatStr](#IsFloatStr)
|
- [IsFloatStr](#IsFloatStr)
|
||||||
- [IsNumberStr](#IsNumberStr)
|
- [IsNumberStr](#IsNumberStr)
|
||||||
- [IsJSON](#IsJSON)
|
- [IsJSON](#IsJSON)
|
||||||
- [IsRegexMatch](#IsRegexMatch)
|
- [IsRegexMatch](#IsRegexMatch)
|
||||||
- [IsIntStr](#IsIntStr)
|
|
||||||
- [IsIp](#IsIp)
|
- [IsIp](#IsIp)
|
||||||
- [IsIpV4](#IsIpV4)
|
- [IsIpV4](#IsIpV4)
|
||||||
- [IsIpV6](#IsIpV6)
|
- [IsIpV6](#IsIpV6)
|
||||||
@@ -589,6 +592,154 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="IsInt">IsInt</span>
|
||||||
|
|
||||||
|
<p>Check if the value is integer(int, unit) or not.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsInt(v any) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := validator.IsInt("")
|
||||||
|
result2 := validator.IsInt("3")
|
||||||
|
result3 := validator.IsInt(0.1)
|
||||||
|
result4 := validator.IsInt(0)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="IsFloat">IsFloat</span>
|
||||||
|
|
||||||
|
<p>Check if the value is float(float32, float34) or not.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsFloat(v any) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := validator.IsFloat("")
|
||||||
|
result2 := validator.IsFloat("3")
|
||||||
|
result3 := validator.IsFloat(0)
|
||||||
|
result4 := validator.IsFloat(0.1)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="IsNumber">IsNumber</span>
|
||||||
|
|
||||||
|
<p>Check if the value is number(integer, float) or not.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsNumber(v any) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := validator.IsNumber("")
|
||||||
|
result2 := validator.IsNumber("3")
|
||||||
|
result3 := validator.IsNumber(0.1)
|
||||||
|
result4 := validator.IsNumber(0)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="IsIntStr">IsIntStr</span>
|
||||||
|
|
||||||
|
<p>Check if the string can convert to a integer.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsIntStr(s string) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := validator.IsIntStr("+3")
|
||||||
|
result2 := validator.IsIntStr("-3")
|
||||||
|
result3 := validator.IsIntStr("3.")
|
||||||
|
result4 := validator.IsIntStr("abc")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="IsFloatStr">IsFloatStr</span>
|
### <span id="IsFloatStr">IsFloatStr</span>
|
||||||
|
|
||||||
<p>Check if the string can convert to a float.</p>
|
<p>Check if the string can convert to a float.</p>
|
||||||
@@ -684,8 +835,8 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
result1 := validator.IsJSON("{}")
|
result1 := validator.IsJSON("{}")
|
||||||
result2 := validator.IsJSON("{\"name\": \"test\"}")
|
result2 := validator.IsJSON("{\"name\": \"test\"}")
|
||||||
result3 := validator.IsIntStr("")
|
result3 := validator.IsJSON("")
|
||||||
result4 := validator.IsIntStr("abc")
|
result4 := validator.IsJSON("abc")
|
||||||
|
|
||||||
fmt.Println(result1)
|
fmt.Println(result1)
|
||||||
fmt.Println(result2)
|
fmt.Println(result2)
|
||||||
@@ -731,43 +882,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### <span id="IsIntStr">IsIntStr</span>
|
|
||||||
|
|
||||||
<p>Check if the string can convert to a integer.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func IsIntStr(s string) bool
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/validator"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
result1 := validator.IsIntStr("+3")
|
|
||||||
result2 := validator.IsIntStr("-3")
|
|
||||||
result3 := validator.IsIntStr("3.")
|
|
||||||
result4 := validator.IsIntStr("abc")
|
|
||||||
|
|
||||||
fmt.Println(result1)
|
|
||||||
fmt.Println(result2)
|
|
||||||
fmt.Println(result3)
|
|
||||||
fmt.Println(result4)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// true
|
|
||||||
// true
|
|
||||||
// false
|
|
||||||
// false
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="IsIp">IsIp</span>
|
### <span id="IsIp">IsIp</span>
|
||||||
|
|
||||||
<p>Check if the string is a ip address.</p>
|
<p>Check if the string is a ip address.</p>
|
||||||
@@ -1033,7 +1147,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### <span id="IsPrintable">IsPrintable</span>
|
### <span id="IsPrintable">IsPrintable</span>
|
||||||
|
|
||||||
<p>Checks if string is all printable chars.</p>
|
<p>Checks if string is all printable chars.</p>
|
||||||
@@ -1072,4 +1185,4 @@ func main() {
|
|||||||
// true
|
// true
|
||||||
// false
|
// false
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -38,11 +38,14 @@ import (
|
|||||||
- [IsDns](#IsDns)
|
- [IsDns](#IsDns)
|
||||||
- [IsEmail](#IsEmail)
|
- [IsEmail](#IsEmail)
|
||||||
- [IsEmptyString](#IsEmptyString)
|
- [IsEmptyString](#IsEmptyString)
|
||||||
|
- [IsInt](#IsInt)
|
||||||
|
- [IsFloat](#IsFloat)
|
||||||
|
- [IsNumber](#IsNumber)
|
||||||
|
- [IsIntStr](#IsIntStr)
|
||||||
- [IsFloatStr](#IsFloatStr)
|
- [IsFloatStr](#IsFloatStr)
|
||||||
- [IsNumberStr](#IsNumberStr)
|
- [IsNumberStr](#IsNumberStr)
|
||||||
- [IsJSON](#IsJSON)
|
- [IsJSON](#IsJSON)
|
||||||
- [IsRegexMatch](#IsRegexMatch)
|
- [IsRegexMatch](#IsRegexMatch)
|
||||||
- [IsIntStr](#IsIntStr)
|
|
||||||
- [IsIp](#IsIp)
|
- [IsIp](#IsIp)
|
||||||
- [IsIpV4](#IsIpV4)
|
- [IsIpV4](#IsIpV4)
|
||||||
- [IsIpV6](#IsIpV6)
|
- [IsIpV6](#IsIpV6)
|
||||||
@@ -589,6 +592,155 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="IsInt">IsInt</span>
|
||||||
|
|
||||||
|
<p>验证参数是否是整数(int, unit)。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsInt(v any) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := validator.IsInt("")
|
||||||
|
result2 := validator.IsInt("3")
|
||||||
|
result3 := validator.IsInt(0.1)
|
||||||
|
result4 := validator.IsInt(0)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="IsFloat">IsFloat</span>
|
||||||
|
|
||||||
|
<p>验证参数是否是浮点数((float32, float34)。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsFloat(v any) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := validator.IsFloat("")
|
||||||
|
result2 := validator.IsFloat("3")
|
||||||
|
result3 := validator.IsFloat(0)
|
||||||
|
result4 := validator.IsFloat(0.1)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="IsNumber">IsNumber</span>
|
||||||
|
|
||||||
|
<p>验证参数是否是数字(integer or float)</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsNumber(v any) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := validator.IsNumber("")
|
||||||
|
result2 := validator.IsNumber("3")
|
||||||
|
result3 := validator.IsNumber(0.1)
|
||||||
|
result4 := validator.IsNumber(0)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### <span id="IsIntStr">IsIntStr</span>
|
||||||
|
|
||||||
|
<p>验证字符串是否是可以转换为整数</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func IsIntStr(s string) bool
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
result1 := validator.IsIntStr("+3")
|
||||||
|
result2 := validator.IsIntStr("-3")
|
||||||
|
result3 := validator.IsIntStr("3.")
|
||||||
|
result4 := validator.IsIntStr("abc")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="IsFloatStr">IsFloatStr</span>
|
### <span id="IsFloatStr">IsFloatStr</span>
|
||||||
|
|
||||||
<p>验证字符串是否是可以转换为浮点数</p>
|
<p>验证字符串是否是可以转换为浮点数</p>
|
||||||
@@ -684,8 +836,8 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
result1 := validator.IsJSON("{}")
|
result1 := validator.IsJSON("{}")
|
||||||
result2 := validator.IsJSON("{\"name\": \"test\"}")
|
result2 := validator.IsJSON("{\"name\": \"test\"}")
|
||||||
result3 := validator.IsIntStr("")
|
result3 := validator.IsJSON("")
|
||||||
result4 := validator.IsIntStr("abc")
|
result4 := validator.IsJSON("abc")
|
||||||
|
|
||||||
fmt.Println(result1)
|
fmt.Println(result1)
|
||||||
fmt.Println(result2)
|
fmt.Println(result2)
|
||||||
@@ -731,42 +883,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### <span id="IsIntStr">IsIntStr</span>
|
|
||||||
|
|
||||||
<p>验证字符串是否是可以转换为整数</p>
|
|
||||||
|
|
||||||
<b>函数签名:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func IsIntStr(s string) bool
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>示例:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/validator"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
result1 := validator.IsIntStr("+3")
|
|
||||||
result2 := validator.IsIntStr("-3")
|
|
||||||
result3 := validator.IsIntStr("3.")
|
|
||||||
result4 := validator.IsIntStr("abc")
|
|
||||||
|
|
||||||
fmt.Println(result1)
|
|
||||||
fmt.Println(result2)
|
|
||||||
fmt.Println(result3)
|
|
||||||
fmt.Println(result4)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// true
|
|
||||||
// true
|
|
||||||
// false
|
|
||||||
// false
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="IsIp">IsIp</span>
|
### <span id="IsIp">IsIp</span>
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -345,3 +346,15 @@ func MiMeType(file any) string {
|
|||||||
}
|
}
|
||||||
return mediatype
|
return mediatype
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CurrentPath return current absolute path.
|
||||||
|
// Play: todo
|
||||||
|
func CurrentPath() string {
|
||||||
|
var absPath string
|
||||||
|
_, filename, _, ok := runtime.Caller(1)
|
||||||
|
if ok {
|
||||||
|
absPath = path.Dir(filename)
|
||||||
|
}
|
||||||
|
|
||||||
|
return absPath
|
||||||
|
}
|
||||||
|
|||||||
@@ -175,11 +175,11 @@ func ExampleReadFileByLine() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ExampleListFileNames() {
|
func ExampleListFileNames() {
|
||||||
fileList, _ := ListFileNames("../formatter/")
|
fileList, _ := ListFileNames("./")
|
||||||
fmt.Println(fileList)
|
fmt.Println(fileList)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// [formatter.go formatter_example_test.go formatter_test.go]
|
// [file.go file_example_test.go file_test.go]
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleZip() {
|
func ExampleZip() {
|
||||||
|
|||||||
@@ -235,9 +235,14 @@ func TestMiMeType(t *testing.T) {
|
|||||||
func TestListFileNames(t *testing.T) {
|
func TestListFileNames(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestListFileNames")
|
assert := internal.NewAssert(t, "TestListFileNames")
|
||||||
|
|
||||||
filesInPath, err := ListFileNames("../formatter/")
|
filesInPath, err := ListFileNames("./")
|
||||||
assert.IsNil(err)
|
assert.IsNil(err)
|
||||||
|
|
||||||
expected := []string{"formatter.go", "formatter_example_test.go", "formatter_test.go"}
|
expected := []string{"file.go", "file_example_test.go", "file_test.go"}
|
||||||
assert.Equal(expected, filesInPath)
|
assert.Equal(expected, filesInPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCurrentPath(t *testing.T) {
|
||||||
|
absPath := CurrentPath()
|
||||||
|
t.Log(absPath)
|
||||||
|
}
|
||||||
|
|||||||
178
formatter/byte.go
Normal file
178
formatter/byte.go
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
package formatter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
//
|
||||||
|
// code logic come from:
|
||||||
|
// https://github.com/docker/go-units/blob/master/size.go
|
||||||
|
|
||||||
|
// http://en.wikipedia.org/wiki/Binary_prefix
|
||||||
|
const (
|
||||||
|
// Decimal
|
||||||
|
UnitB = 1
|
||||||
|
UnitKB = 1000
|
||||||
|
UnitMB = 1000 * UnitKB
|
||||||
|
UnitGB = 1000 * UnitMB
|
||||||
|
UnitTB = 1000 * UnitGB
|
||||||
|
UnitPB = 1000 * UnitTB
|
||||||
|
UnitEB = 1000 * UnitPB
|
||||||
|
|
||||||
|
// Binary
|
||||||
|
UnitBiB = 1
|
||||||
|
UnitKiB = 1024
|
||||||
|
UnitMiB = 1024 * UnitKiB
|
||||||
|
UnitGiB = 1024 * UnitMiB
|
||||||
|
UnitTiB = 1024 * UnitGiB
|
||||||
|
UnitPiB = 1024 * UnitTiB
|
||||||
|
UnitEiB = 1024 * UnitPiB
|
||||||
|
)
|
||||||
|
|
||||||
|
// type byteUnitMap map[byte]int64
|
||||||
|
|
||||||
|
var (
|
||||||
|
decimalByteMap = map[string]uint64{
|
||||||
|
"b": UnitB,
|
||||||
|
"kb": UnitKB,
|
||||||
|
"mb": UnitMB,
|
||||||
|
"gb": UnitGB,
|
||||||
|
"tb": UnitTB,
|
||||||
|
"pb": UnitPB,
|
||||||
|
"eb": UnitEB,
|
||||||
|
|
||||||
|
// Without suffix
|
||||||
|
"": UnitB,
|
||||||
|
"k": UnitKB,
|
||||||
|
"m": UnitMB,
|
||||||
|
"g": UnitGB,
|
||||||
|
"t": UnitTB,
|
||||||
|
"p": UnitPB,
|
||||||
|
"e": UnitEB,
|
||||||
|
}
|
||||||
|
|
||||||
|
binaryByteMap = map[string]uint64{
|
||||||
|
"bi": UnitBiB,
|
||||||
|
"kib": UnitKiB,
|
||||||
|
"mib": UnitMiB,
|
||||||
|
"gib": UnitGiB,
|
||||||
|
"tib": UnitTiB,
|
||||||
|
"pib": UnitPiB,
|
||||||
|
"eib": UnitEiB,
|
||||||
|
|
||||||
|
// Without suffix
|
||||||
|
"": UnitBiB,
|
||||||
|
"ki": UnitKiB,
|
||||||
|
"mi": UnitMiB,
|
||||||
|
"gi": UnitGiB,
|
||||||
|
"ti": UnitTiB,
|
||||||
|
"pi": UnitPiB,
|
||||||
|
"ei": UnitEiB,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
decimalByteUnits = []string{"B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
|
||||||
|
binaryByteUnits = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}
|
||||||
|
)
|
||||||
|
|
||||||
|
// DecimalBytes returns a human readable byte size under decimal standard (base 1000)
|
||||||
|
// The precision parameter specifies the number of digits after the decimal point, which defaults to 4.
|
||||||
|
// Play: todo
|
||||||
|
func DecimalBytes(size float64, precision ...int) string {
|
||||||
|
p := 5
|
||||||
|
if len(precision) > 0 {
|
||||||
|
p = precision[0] + 1
|
||||||
|
}
|
||||||
|
size, unit := calculateByteSize(size, 1000.0, decimalByteUnits)
|
||||||
|
|
||||||
|
return fmt.Sprintf("%.*g%s", p, size, unit)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BinaryBytes returns a human-readable byte size under binary standard (base 1024)
|
||||||
|
// The precision parameter specifies the number of digits after the decimal point, which defaults to 4.
|
||||||
|
// Play: todo
|
||||||
|
func BinaryBytes(size float64, precision ...int) string {
|
||||||
|
p := 5
|
||||||
|
if len(precision) > 0 {
|
||||||
|
p = precision[0] + 1
|
||||||
|
}
|
||||||
|
size, unit := calculateByteSize(size, 1024.0, binaryByteUnits)
|
||||||
|
|
||||||
|
return fmt.Sprintf("%.*g%s", p, size, unit)
|
||||||
|
}
|
||||||
|
|
||||||
|
func calculateByteSize(size float64, base float64, byteUnits []string) (float64, string) {
|
||||||
|
i := 0
|
||||||
|
unitsLimit := len(byteUnits) - 1
|
||||||
|
for size >= base && i < unitsLimit {
|
||||||
|
size = size / base
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return size, byteUnits[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseDecimalBytes return the human readable bytes size string into the amount it represents(base 1000).
|
||||||
|
// ParseDecimalBytes("42 MB") -> 42000000, nil
|
||||||
|
// Play: todo
|
||||||
|
func ParseDecimalBytes(size string) (uint64, error) {
|
||||||
|
return parseBytes(size, "decimal")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseBinaryBytes return the human readable bytes size string into the amount it represents(base 1024).
|
||||||
|
// ParseBinaryBytes("42 mib") -> 44040192, nil
|
||||||
|
// Play: todo
|
||||||
|
func ParseBinaryBytes(size string) (uint64, error) {
|
||||||
|
return parseBytes(size, "binary")
|
||||||
|
}
|
||||||
|
|
||||||
|
// see https://github.com/dustin/go-humanize/blob/master/bytes.go
|
||||||
|
func parseBytes(s string, kind string) (uint64, error) {
|
||||||
|
lastDigit := 0
|
||||||
|
hasComma := false
|
||||||
|
for _, r := range s {
|
||||||
|
if !(unicode.IsDigit(r) || r == '.' || r == ',') {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if r == ',' {
|
||||||
|
hasComma = true
|
||||||
|
}
|
||||||
|
lastDigit++
|
||||||
|
}
|
||||||
|
|
||||||
|
num := s[:lastDigit]
|
||||||
|
if hasComma {
|
||||||
|
num = strings.Replace(num, ",", "", -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := strconv.ParseFloat(num, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
extra := strings.ToLower(strings.TrimSpace(s[lastDigit:]))
|
||||||
|
|
||||||
|
if kind == "decimal" {
|
||||||
|
if m, ok := decimalByteMap[extra]; ok {
|
||||||
|
f *= float64(m)
|
||||||
|
if f >= math.MaxUint64 {
|
||||||
|
return 0, fmt.Errorf("too large: %v", s)
|
||||||
|
}
|
||||||
|
return uint64(f), nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if m, ok := binaryByteMap[extra]; ok {
|
||||||
|
f *= float64(m)
|
||||||
|
if f >= math.MaxUint64 {
|
||||||
|
return 0, fmt.Errorf("too large: %v", s)
|
||||||
|
}
|
||||||
|
return uint64(f), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, fmt.Errorf("unhandled size name: %v", extra)
|
||||||
|
}
|
||||||
87
formatter/byte_test.go
Normal file
87
formatter/byte_test.go
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
package formatter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/v2/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDecimalBytes(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestDecimalBytes")
|
||||||
|
|
||||||
|
assert.Equal("1KB", DecimalBytes(1000))
|
||||||
|
assert.Equal("1.024KB", DecimalBytes(1024))
|
||||||
|
assert.Equal("1.2346MB", DecimalBytes(1234567))
|
||||||
|
assert.Equal("1.235MB", DecimalBytes(1234567, 3))
|
||||||
|
assert.Equal("1.123GB", DecimalBytes(float64(1.123*UnitGB)))
|
||||||
|
assert.Equal("2.123TB", DecimalBytes(float64(2.123*UnitTB)))
|
||||||
|
assert.Equal("3.123PB", DecimalBytes(float64(3.123*UnitPB)))
|
||||||
|
assert.Equal("4.123EB", DecimalBytes(float64(4.123*UnitEB)))
|
||||||
|
assert.Equal("1EB", DecimalBytes(float64(1000*UnitPB)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBinaryBytes(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestBinaryBytes")
|
||||||
|
|
||||||
|
assert.Equal("1KiB", BinaryBytes(1024))
|
||||||
|
assert.Equal("1MiB", BinaryBytes(1024*1024))
|
||||||
|
assert.Equal("1.1774MiB", BinaryBytes(1234567))
|
||||||
|
assert.Equal("1.18MiB", BinaryBytes(1234567, 2))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseDecimalBytes(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestParseDecimalBytes")
|
||||||
|
|
||||||
|
cases := map[string]uint64{
|
||||||
|
"12": uint64(12),
|
||||||
|
"12 k": uint64(12000),
|
||||||
|
"12 kb": uint64(12000),
|
||||||
|
"12kb": uint64(12000),
|
||||||
|
"12k": uint64(12000),
|
||||||
|
"12K": uint64(12000),
|
||||||
|
"12KB": uint64(12000),
|
||||||
|
"12 K": uint64(12000),
|
||||||
|
"12 KB": uint64(12000),
|
||||||
|
"12 Kb": uint64(12000),
|
||||||
|
"12 kB": uint64(12000),
|
||||||
|
"12.2 KB": uint64(12200),
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range cases {
|
||||||
|
result, err := ParseDecimalBytes(k)
|
||||||
|
assert.Equal(v, result)
|
||||||
|
assert.IsNil(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := ParseDecimalBytes("12 AB")
|
||||||
|
assert.IsNotNil(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseBinaryBytes(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestParseBinaryBytes")
|
||||||
|
|
||||||
|
cases := map[string]uint64{
|
||||||
|
"12": uint64(12),
|
||||||
|
"12 ki": uint64(12288),
|
||||||
|
"12 kib": uint64(12288),
|
||||||
|
"12kib": uint64(12288),
|
||||||
|
"12ki": uint64(12288),
|
||||||
|
"12KI": uint64(12288),
|
||||||
|
"12KIB": uint64(12288),
|
||||||
|
"12KiB": uint64(12288),
|
||||||
|
"12 Ki": uint64(12288),
|
||||||
|
"12 KiB": uint64(12288),
|
||||||
|
"12 Kib": uint64(12288),
|
||||||
|
"12 kiB": uint64(12288),
|
||||||
|
"12.2 KiB": uint64(12492),
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range cases {
|
||||||
|
result, err := ParseBinaryBytes(k)
|
||||||
|
assert.Equal(v, result)
|
||||||
|
assert.IsNil(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := ParseDecimalBytes("12 AB")
|
||||||
|
assert.IsNotNil(err)
|
||||||
|
}
|
||||||
@@ -5,11 +5,13 @@
|
|||||||
package formatter
|
package formatter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"io"
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/v2/convertor"
|
||||||
|
"github.com/duke-git/lancet/v2/strutil"
|
||||||
|
"github.com/duke-git/lancet/v2/validator"
|
||||||
"golang.org/x/exp/constraints"
|
"golang.org/x/exp/constraints"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,54 +20,49 @@ import (
|
|||||||
// Comma("12345", "$") => "$12,345", Comma(12345, "$") => "$12,345"
|
// Comma("12345", "$") => "$12,345", Comma(12345, "$") => "$12,345"
|
||||||
// Play: https://go.dev/play/p/eRD5k2vzUVX
|
// Play: https://go.dev/play/p/eRD5k2vzUVX
|
||||||
func Comma[T constraints.Float | constraints.Integer | string](value T, symbol string) string {
|
func Comma[T constraints.Float | constraints.Integer | string](value T, symbol string) string {
|
||||||
s, err := numberToString(value)
|
if validator.IsInt(value) {
|
||||||
if err != nil {
|
v, err := convertor.ToInt(value)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return symbol + commaInt(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if validator.IsFloat(value) {
|
||||||
|
v, err := convertor.ToFloat(value)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return symbol + commaFloat(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if strutil.IsString(value) {
|
||||||
|
v := fmt.Sprintf("%v", value)
|
||||||
|
if validator.IsNumberStr(v) {
|
||||||
|
return symbol + commaStr(v)
|
||||||
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
dotIndex := strings.Index(s, ".")
|
return ""
|
||||||
if dotIndex != -1 {
|
|
||||||
return symbol + commaString(s[:dotIndex]) + s[dotIndex:]
|
|
||||||
}
|
|
||||||
|
|
||||||
return symbol + commaString(s)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func commaString(s string) string {
|
// Pretty data to JSON string.
|
||||||
if len(s) <= 3 {
|
// Play: todo
|
||||||
return s
|
func Pretty(v any) (string, error) {
|
||||||
}
|
out, err := json.MarshalIndent(v, "", " ")
|
||||||
return commaString(s[:len(s)-3]) + "," + commaString(s[len(s)-3:])
|
return string(out), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func numberToString(value any) (string, error) {
|
// PrettyToWriter pretty encode data to writer.
|
||||||
switch reflect.TypeOf(value).Kind() {
|
// Play: todo
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
func PrettyToWriter(v any, out io.Writer) error {
|
||||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
enc := json.NewEncoder(out)
|
||||||
return fmt.Sprintf("%v", value), nil
|
enc.SetIndent("", " ")
|
||||||
|
|
||||||
// todo: need to handle 12345678.9 => 1.23456789e+07
|
if err := enc.Encode(v); err != nil {
|
||||||
case reflect.Float32, reflect.Float64:
|
return err
|
||||||
return fmt.Sprintf("%v", value), nil
|
|
||||||
|
|
||||||
case reflect.String:
|
|
||||||
{
|
|
||||||
sv := fmt.Sprintf("%v", value)
|
|
||||||
if strings.Contains(sv, ".") {
|
|
||||||
_, err := strconv.ParseFloat(sv, 64)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return sv, nil
|
|
||||||
} else {
|
|
||||||
_, err := strconv.ParseInt(sv, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
return sv, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return "", nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package formatter
|
package formatter
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
func ExampleComma() {
|
func ExampleComma() {
|
||||||
result1 := Comma("123", "")
|
result1 := Comma("123", "")
|
||||||
@@ -16,3 +19,115 @@ func ExampleComma() {
|
|||||||
// $12,345
|
// $12,345
|
||||||
// ¥1,234,567
|
// ¥1,234,567
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExamplePretty() {
|
||||||
|
result1, _ := Pretty([]string{"a", "b", "c"})
|
||||||
|
result2, _ := Pretty(map[string]int{"a": 1})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [
|
||||||
|
// "a",
|
||||||
|
// "b",
|
||||||
|
// "c"
|
||||||
|
// ]
|
||||||
|
// {
|
||||||
|
// "a": 1
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExamplePrettyToWriter() {
|
||||||
|
type User struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Aage uint `json:"age"`
|
||||||
|
}
|
||||||
|
user := User{Name: "King", Aage: 10000}
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
err := PrettyToWriter(user, buf)
|
||||||
|
|
||||||
|
fmt.Println(buf)
|
||||||
|
fmt.Println(err)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// {
|
||||||
|
// "name": "King",
|
||||||
|
// "age": 10000
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// <nil>
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleDecimalBytes() {
|
||||||
|
result1 := DecimalBytes(1000)
|
||||||
|
result2 := DecimalBytes(1024)
|
||||||
|
result3 := DecimalBytes(1234567)
|
||||||
|
result4 := DecimalBytes(1234567, 3)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1KB
|
||||||
|
// 1.024KB
|
||||||
|
// 1.2346MB
|
||||||
|
// 1.235MB
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleBinaryBytes() {
|
||||||
|
result1 := BinaryBytes(1024)
|
||||||
|
result2 := BinaryBytes(1024 * 1024)
|
||||||
|
result3 := BinaryBytes(1234567)
|
||||||
|
result4 := BinaryBytes(1234567, 2)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1KiB
|
||||||
|
// 1MiB
|
||||||
|
// 1.1774MiB
|
||||||
|
// 1.18MiB
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleParseDecimalBytes() {
|
||||||
|
result1, _ := ParseDecimalBytes("12")
|
||||||
|
result2, _ := ParseDecimalBytes("12k")
|
||||||
|
result3, _ := ParseDecimalBytes("12 Kb")
|
||||||
|
result4, _ := ParseDecimalBytes("12.2 kb")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 12
|
||||||
|
// 12000
|
||||||
|
// 12000
|
||||||
|
// 12200
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleParseBinaryBytes() {
|
||||||
|
result1, _ := ParseBinaryBytes("12")
|
||||||
|
result2, _ := ParseBinaryBytes("12ki")
|
||||||
|
result3, _ := ParseBinaryBytes("12 KiB")
|
||||||
|
result4, _ := ParseBinaryBytes("12.2 kib")
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 12
|
||||||
|
// 12288
|
||||||
|
// 12288
|
||||||
|
// 12492
|
||||||
|
}
|
||||||
|
|||||||
85
formatter/formatter_internal.go
Normal file
85
formatter/formatter_internal.go
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
package formatter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"math"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// see https://github.com/dustin/go-humanize/blob/master/comma.go
|
||||||
|
func commaInt(v int64) string {
|
||||||
|
sign := ""
|
||||||
|
|
||||||
|
// Min int64 can't be negated to a usable value, so it has to be special cased.
|
||||||
|
if v == math.MinInt64 {
|
||||||
|
return "-9,223,372,036,854,775,808"
|
||||||
|
}
|
||||||
|
|
||||||
|
if v < 0 {
|
||||||
|
sign = "-"
|
||||||
|
v = 0 - v
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := []string{"", "", "", "", "", "", ""}
|
||||||
|
j := len(parts) - 1
|
||||||
|
|
||||||
|
for v > 999 {
|
||||||
|
parts[j] = strconv.FormatInt(v%1000, 10)
|
||||||
|
switch len(parts[j]) {
|
||||||
|
case 2:
|
||||||
|
parts[j] = "0" + parts[j]
|
||||||
|
case 1:
|
||||||
|
parts[j] = "00" + parts[j]
|
||||||
|
}
|
||||||
|
v = v / 1000
|
||||||
|
j--
|
||||||
|
}
|
||||||
|
parts[j] = strconv.Itoa(int(v))
|
||||||
|
return sign + strings.Join(parts[j:], ",")
|
||||||
|
}
|
||||||
|
|
||||||
|
func commaFloat(v float64) string {
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
if v < 0 {
|
||||||
|
buf.Write([]byte{'-'})
|
||||||
|
v = 0 - v
|
||||||
|
}
|
||||||
|
|
||||||
|
comma := []byte{','}
|
||||||
|
|
||||||
|
parts := strings.Split(strconv.FormatFloat(v, 'f', -1, 64), ".")
|
||||||
|
pos := 0
|
||||||
|
if len(parts[0])%3 != 0 {
|
||||||
|
pos += len(parts[0]) % 3
|
||||||
|
buf.WriteString(parts[0][:pos])
|
||||||
|
buf.Write(comma)
|
||||||
|
}
|
||||||
|
for ; pos < len(parts[0]); pos += 3 {
|
||||||
|
buf.WriteString(parts[0][pos : pos+3])
|
||||||
|
buf.Write(comma)
|
||||||
|
}
|
||||||
|
buf.Truncate(buf.Len() - 1)
|
||||||
|
|
||||||
|
if len(parts) > 1 {
|
||||||
|
buf.Write([]byte{'.'})
|
||||||
|
buf.WriteString(parts[1])
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func commaStr(s string) string {
|
||||||
|
dotIndex := strings.Index(s, ".")
|
||||||
|
if dotIndex != -1 {
|
||||||
|
return commaStrRecursive(s[:dotIndex]) + s[dotIndex:]
|
||||||
|
}
|
||||||
|
|
||||||
|
return commaStrRecursive(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func commaStrRecursive(s string) string {
|
||||||
|
if len(s) <= 3 {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return commaStrRecursive(s[:len(s)-3]) + "," + commaStrRecursive(s[len(s)-3:])
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package formatter
|
package formatter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/v2/internal"
|
"github.com/duke-git/lancet/v2/internal"
|
||||||
@@ -16,12 +17,64 @@ func TestComma(t *testing.T) {
|
|||||||
assert.Equal("12,345", Comma("12345", ""))
|
assert.Equal("12,345", Comma("12345", ""))
|
||||||
assert.Equal("12,345.6789", Comma("12345.6789", ""))
|
assert.Equal("12,345.6789", Comma("12345.6789", ""))
|
||||||
assert.Equal("123,456,789,000", Comma("123456789000", ""))
|
assert.Equal("123,456,789,000", Comma("123456789000", ""))
|
||||||
|
assert.Equal("12,345,678.9", Comma("12345678.9", ""))
|
||||||
|
|
||||||
assert.Equal("12,345", Comma(12345, ""))
|
assert.Equal("12,345", Comma(12345, ""))
|
||||||
assert.Equal("$12,345", Comma(12345, "$"))
|
assert.Equal("$12,345", Comma(12345, "$"))
|
||||||
assert.Equal("¥12,345", Comma(12345, "¥"))
|
assert.Equal("¥12,345", Comma(12345, "¥"))
|
||||||
assert.Equal("12,345.6789", Comma(12345.6789, ""))
|
assert.Equal("12,345.6789", Comma(12345.6789, ""))
|
||||||
assert.Equal("12,345.6789", Comma(+12345.6789, ""))
|
assert.Equal("12,345.6789", Comma(+12345.6789, ""))
|
||||||
// assert.Equal("12,345,678.9", Comma(12345678.9, ""))
|
assert.Equal("12,345,678.9", Comma(12345678.9, ""))
|
||||||
assert.Equal("123,456,789,000", Comma(123456789000, ""))
|
assert.Equal("123,456,789,000", Comma(123456789000, ""))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPretty(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestPretty")
|
||||||
|
|
||||||
|
cases := []any{
|
||||||
|
"",
|
||||||
|
"abc",
|
||||||
|
123,
|
||||||
|
[]string{"a", "b", "c"},
|
||||||
|
map[string]int{"a": 1},
|
||||||
|
struct {
|
||||||
|
Abc int `json:"abc"`
|
||||||
|
}{Abc: 123},
|
||||||
|
}
|
||||||
|
|
||||||
|
expects := []string{
|
||||||
|
"\"\"",
|
||||||
|
`"abc"`,
|
||||||
|
"123",
|
||||||
|
"[\n \"a\",\n \"b\",\n \"c\"\n]",
|
||||||
|
"{\n \"a\": 1\n}",
|
||||||
|
"{\n \"abc\": 123\n}",
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, v := range cases {
|
||||||
|
result, err := Pretty(v)
|
||||||
|
|
||||||
|
assert.IsNil(err)
|
||||||
|
|
||||||
|
t.Log("result -> ", result)
|
||||||
|
assert.Equal(expects[i], result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrettyToWriter(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestPrettyToWriter")
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Aage uint `json:"age"`
|
||||||
|
}
|
||||||
|
user := User{Name: "King", Aage: 10000}
|
||||||
|
|
||||||
|
expects := "{\n \"name\": \"King\",\n \"age\": 10000\n}\n"
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
err := PrettyToWriter(user, buf)
|
||||||
|
|
||||||
|
assert.IsNil(err)
|
||||||
|
assert.Equal(expects, buf.String())
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
@@ -44,6 +45,52 @@ func (a *Assert) NotEqual(expected, actual any) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EqualValues asserts that two objects are equal or convertable to the same types and equal.
|
||||||
|
// https://github.com/stretchr/testify/assert/assertions.go
|
||||||
|
func (a *Assert) EqualValues(expected, actual any) {
|
||||||
|
if !objectsAreEqualValues(expected, actual) {
|
||||||
|
makeTestFailed(a.T, a.CaseName, expected, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func objectsAreEqualValues(expected, actual interface{}) bool {
|
||||||
|
if objectsAreEqual(expected, actual) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
actualType := reflect.TypeOf(actual)
|
||||||
|
if actualType == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
expectedValue := reflect.ValueOf(expected)
|
||||||
|
if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) {
|
||||||
|
// Attempt comparison after type conversion
|
||||||
|
return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func objectsAreEqual(expected, actual interface{}) bool {
|
||||||
|
if expected == nil || actual == nil {
|
||||||
|
return expected == actual
|
||||||
|
}
|
||||||
|
|
||||||
|
exp, ok := expected.([]byte)
|
||||||
|
if !ok {
|
||||||
|
return reflect.DeepEqual(expected, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
act, ok := actual.([]byte)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if exp == nil || act == nil {
|
||||||
|
return exp == nil && act == nil
|
||||||
|
}
|
||||||
|
return bytes.Equal(exp, act)
|
||||||
|
}
|
||||||
|
|
||||||
// Greater check if expected is greate than actual
|
// Greater check if expected is greate than actual
|
||||||
func (a *Assert) Greater(expected, actual any) {
|
func (a *Assert) Greater(expected, actual any) {
|
||||||
if compare(expected, actual) != compareGreater {
|
if compare(expected, actual) != compareGreater {
|
||||||
|
|||||||
@@ -397,3 +397,39 @@ func ExampleOmitByValues() {
|
|||||||
// Output:
|
// Output:
|
||||||
// map[a:1 b:2 c:3]
|
// map[a:1 b:2 c:3]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleMapTo() {
|
||||||
|
type (
|
||||||
|
Person struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Age int `json:"age"`
|
||||||
|
Phone string `json:"phone"`
|
||||||
|
Addr Address `json:"address"`
|
||||||
|
}
|
||||||
|
|
||||||
|
Address struct {
|
||||||
|
Street string `json:"street"`
|
||||||
|
Number int `json:"number"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
personInfo := map[string]interface{}{
|
||||||
|
"name": "Nothin",
|
||||||
|
"age": 28,
|
||||||
|
"phone": "123456789",
|
||||||
|
"address": map[string]interface{}{
|
||||||
|
"street": "test",
|
||||||
|
"number": 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var p Person
|
||||||
|
err := MapTo(personInfo, &p)
|
||||||
|
|
||||||
|
fmt.Println(err)
|
||||||
|
fmt.Println(p)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// <nil>
|
||||||
|
// {Nothin 28 123456789 {test 1}}
|
||||||
|
}
|
||||||
|
|||||||
180
maputil/typemap.go
Normal file
180
maputil/typemap.go
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
package maputil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var mapHandlers = map[reflect.Kind]func(reflect.Value, reflect.Value) error{
|
||||||
|
reflect.String: convertNormal,
|
||||||
|
reflect.Int: convertNormal,
|
||||||
|
reflect.Int16: convertNormal,
|
||||||
|
reflect.Int32: convertNormal,
|
||||||
|
reflect.Int64: convertNormal,
|
||||||
|
reflect.Uint: convertNormal,
|
||||||
|
reflect.Uint16: convertNormal,
|
||||||
|
reflect.Uint32: convertNormal,
|
||||||
|
reflect.Uint64: convertNormal,
|
||||||
|
reflect.Float32: convertNormal,
|
||||||
|
reflect.Float64: convertNormal,
|
||||||
|
reflect.Uint8: convertNormal,
|
||||||
|
reflect.Int8: convertNormal,
|
||||||
|
reflect.Struct: convertNormal,
|
||||||
|
reflect.Complex64: convertNormal,
|
||||||
|
reflect.Complex128: convertNormal,
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ = func() struct{} {
|
||||||
|
mapHandlers[reflect.Map] = convertMap
|
||||||
|
mapHandlers[reflect.Array] = convertSlice
|
||||||
|
mapHandlers[reflect.Slice] = convertSlice
|
||||||
|
return struct{}{}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// MapTo try to map any interface to struct or base type
|
||||||
|
/*
|
||||||
|
Eg:
|
||||||
|
v := map[string]interface{}{
|
||||||
|
"service":map[string]interface{}{
|
||||||
|
"ip":"127.0.0.1",
|
||||||
|
"port":1234,
|
||||||
|
},
|
||||||
|
version:"v1.0.01"
|
||||||
|
}
|
||||||
|
|
||||||
|
type Target struct {
|
||||||
|
Service struct {
|
||||||
|
Ip string `json:"ip"`
|
||||||
|
Port int `json:"port"`
|
||||||
|
} `json:"service"`
|
||||||
|
Ver string `json:"version"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var dist Target
|
||||||
|
if err := maputil.MapTo(v,&dist); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println(dist)
|
||||||
|
|
||||||
|
*/
|
||||||
|
func MapTo(src any, dst any) error {
|
||||||
|
|
||||||
|
dstRef := reflect.ValueOf(dst)
|
||||||
|
if dstRef.Kind() != reflect.Ptr {
|
||||||
|
return fmt.Errorf("dst is not ptr")
|
||||||
|
}
|
||||||
|
|
||||||
|
dstRef = reflect.Indirect(dstRef)
|
||||||
|
|
||||||
|
srcRef := reflect.ValueOf(src)
|
||||||
|
if srcRef.Kind() == reflect.Ptr || srcRef.Kind() == reflect.Interface {
|
||||||
|
srcRef = srcRef.Elem()
|
||||||
|
}
|
||||||
|
if f, ok := mapHandlers[srcRef.Kind()]; ok {
|
||||||
|
return f(srcRef, dstRef)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("no implemented:%s", srcRef.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertNormal(src reflect.Value, dst reflect.Value) error {
|
||||||
|
if dst.CanSet() {
|
||||||
|
if src.Type() == dst.Type() {
|
||||||
|
dst.Set(src)
|
||||||
|
} else if src.CanConvert(dst.Type()) {
|
||||||
|
dst.Set(src.Convert(dst.Type()))
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("can not convert:%s:%s", src.Type().String(), dst.Type().String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertSlice(src reflect.Value, dst reflect.Value) error {
|
||||||
|
if dst.Kind() != reflect.Array && dst.Kind() != reflect.Slice {
|
||||||
|
return fmt.Errorf("error type:%s", dst.Type().String())
|
||||||
|
}
|
||||||
|
l := src.Len()
|
||||||
|
target := reflect.MakeSlice(dst.Type(), l, l)
|
||||||
|
if dst.CanSet() {
|
||||||
|
dst.Set(target)
|
||||||
|
}
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
srcValue := src.Index(i)
|
||||||
|
if srcValue.Kind() == reflect.Ptr || srcValue.Kind() == reflect.Interface {
|
||||||
|
srcValue = srcValue.Elem()
|
||||||
|
}
|
||||||
|
if f, ok := mapHandlers[srcValue.Kind()]; ok {
|
||||||
|
err := f(srcValue, dst.Index(i))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertMap(src reflect.Value, dst reflect.Value) error {
|
||||||
|
if src.Kind() != reflect.Map || dst.Kind() != reflect.Struct {
|
||||||
|
if src.Kind() == reflect.Interface {
|
||||||
|
return convertMap(src.Elem(), dst)
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("src or dst type error,%s,%s", src.Type().String(), dst.Type().String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dstType := dst.Type()
|
||||||
|
num := dstType.NumField()
|
||||||
|
exist := map[string]int{}
|
||||||
|
for i := 0; i < num; i++ {
|
||||||
|
k := dstType.Field(i).Tag.Get("json")
|
||||||
|
if k == "" {
|
||||||
|
k = dstType.Field(i).Name
|
||||||
|
}
|
||||||
|
if strings.Contains(k, ",") {
|
||||||
|
taglist := strings.Split(k, ",")
|
||||||
|
if taglist[0] == "" {
|
||||||
|
|
||||||
|
k = dstType.Field(i).Name
|
||||||
|
} else {
|
||||||
|
k = taglist[0]
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
exist[k] = i
|
||||||
|
}
|
||||||
|
|
||||||
|
keys := src.MapKeys()
|
||||||
|
for _, key := range keys {
|
||||||
|
if index, ok := exist[key.String()]; ok {
|
||||||
|
v := dst.Field(index)
|
||||||
|
if v.Kind() == reflect.Struct {
|
||||||
|
err := convertMap(src.MapIndex(key), v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if v.CanSet() {
|
||||||
|
if v.Type() == src.MapIndex(key).Elem().Type() {
|
||||||
|
v.Set(src.MapIndex(key).Elem())
|
||||||
|
} else if src.MapIndex(key).Elem().CanConvert(v.Type()) {
|
||||||
|
v.Set(src.MapIndex(key).Elem().Convert(v.Type()))
|
||||||
|
} else if f, ok := mapHandlers[src.MapIndex(key).Elem().Kind()]; ok && f != nil {
|
||||||
|
err := f(src.MapIndex(key).Elem(), v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("error type:d(%s)s(%s)", v.Type(), src.Type())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
111
maputil/typemap_test.go
Normal file
111
maputil/typemap_test.go
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
package maputil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/v2/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
Person struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Age int `json:"age"`
|
||||||
|
Phone string `json:"phone"`
|
||||||
|
Addr Address `json:"address"`
|
||||||
|
}
|
||||||
|
|
||||||
|
Address struct {
|
||||||
|
Street string `json:"street"`
|
||||||
|
Number int `json:"number"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStructType(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestStructType")
|
||||||
|
|
||||||
|
src := map[string]interface{}{
|
||||||
|
"name": "Nothin",
|
||||||
|
"age": 28,
|
||||||
|
"phone": "123456789",
|
||||||
|
"address": map[string]interface{}{
|
||||||
|
"street": "test",
|
||||||
|
"number": 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var p Person
|
||||||
|
err := MapTo(src, &p)
|
||||||
|
assert.IsNil(err)
|
||||||
|
assert.Equal(src["name"], p.Name)
|
||||||
|
assert.Equal(src["age"], p.Age)
|
||||||
|
assert.Equal(src["phone"], p.Phone)
|
||||||
|
assert.Equal("test", p.Addr.Street)
|
||||||
|
assert.Equal(1, p.Addr.Number)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBaseType(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestBaseType")
|
||||||
|
|
||||||
|
tc := map[string]interface{}{
|
||||||
|
"i32": -32,
|
||||||
|
"i8": -8,
|
||||||
|
"i16": -16,
|
||||||
|
"i64": -64,
|
||||||
|
"i": -1,
|
||||||
|
"u32": 32,
|
||||||
|
"u8": 8,
|
||||||
|
"u16": 16,
|
||||||
|
"u64": 64,
|
||||||
|
"u": 1,
|
||||||
|
"tf": true,
|
||||||
|
"f32": 1.32,
|
||||||
|
"f64": 1.64,
|
||||||
|
"str": "hello mapto",
|
||||||
|
"complex": 1 + 3i,
|
||||||
|
}
|
||||||
|
|
||||||
|
type BaseType struct {
|
||||||
|
I int `json:"i"`
|
||||||
|
I8 int8 `json:"i8"`
|
||||||
|
I16 int16 `json:"i16"`
|
||||||
|
I32 int32 `json:"i32"`
|
||||||
|
I64 int64 `json:"i64"`
|
||||||
|
U uint `json:"u"`
|
||||||
|
U8 uint8 `json:"u8"`
|
||||||
|
U16 uint16 `json:"u16"`
|
||||||
|
U32 uint32 `json:"u32"`
|
||||||
|
U64 uint64 `json:"u64"`
|
||||||
|
F32 float32 `json:"f32"`
|
||||||
|
F64 float64 `json:"f64"`
|
||||||
|
Tf bool `json:"tf"`
|
||||||
|
Str string `json:"str"`
|
||||||
|
Comp complex128 `json:"complex"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var dist BaseType
|
||||||
|
err := MapTo(tc, &dist)
|
||||||
|
assert.IsNil(err)
|
||||||
|
|
||||||
|
var number float64
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
@@ -218,21 +218,21 @@ func RangeWithStep[T constraints.Integer | constraints.Float](start, end, step T
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AngleToRadian converts angle value to radian value.
|
// AngleToRadian converts angle value to radian value.
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/CIvlICqrHql
|
||||||
func AngleToRadian(angle float64) float64 {
|
func AngleToRadian(angle float64) float64 {
|
||||||
radian := angle * (math.Pi / 180)
|
radian := angle * (math.Pi / 180)
|
||||||
return radian
|
return radian
|
||||||
}
|
}
|
||||||
|
|
||||||
// RadianToAngle converts radian value to angle value.
|
// RadianToAngle converts radian value to angle value.
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/dQtmOTUOMgi
|
||||||
func RadianToAngle(radian float64) float64 {
|
func RadianToAngle(radian float64) float64 {
|
||||||
angle := radian * (180 / math.Pi)
|
angle := radian * (180 / math.Pi)
|
||||||
return angle
|
return angle
|
||||||
}
|
}
|
||||||
|
|
||||||
// PointDistance get two points distance.
|
// PointDistance get two points distance.
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/RrG4JIaziM8
|
||||||
func PointDistance(x1, y1, x2, y2 float64) float64 {
|
func PointDistance(x1, y1, x2, y2 float64) float64 {
|
||||||
a := x1 - x2
|
a := x1 - x2
|
||||||
b := y1 - y2
|
b := y1 - y2
|
||||||
@@ -242,7 +242,7 @@ func PointDistance(x1, y1, x2, y2 float64) float64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IsPrimes checks if number is prime number.
|
// IsPrimes checks if number is prime number.
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/Rdd8UTHZJ7u
|
||||||
func IsPrime(n int) bool {
|
func IsPrime(n int) bool {
|
||||||
if n < 2 {
|
if n < 2 {
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -492,6 +492,30 @@ func Reduce[T any](slice []T, iteratee func(index int, item1, item2 T) T, initia
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReduceBy produces a value from slice by accumulating the result of each element as passed through the reducer function.
|
||||||
|
// Play: todo
|
||||||
|
func ReduceBy[T any, U any](slice []T, initial U, reducer func(index int, item T, agg U) U) U {
|
||||||
|
accumulator := initial
|
||||||
|
|
||||||
|
for i, v := range slice {
|
||||||
|
accumulator = reducer(i, v, accumulator)
|
||||||
|
}
|
||||||
|
|
||||||
|
return accumulator
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReduceRight is like ReduceBy, but it iterates over elements of slice from right to left.
|
||||||
|
// Play: todo
|
||||||
|
func ReduceRight[T any, U any](slice []T, initial U, reducer func(index int, item T, agg U) U) U {
|
||||||
|
accumulator := initial
|
||||||
|
|
||||||
|
for i := len(slice) - 1; i >= 0; i-- {
|
||||||
|
accumulator = reducer(i, slice[i], accumulator)
|
||||||
|
}
|
||||||
|
|
||||||
|
return accumulator
|
||||||
|
}
|
||||||
|
|
||||||
// Replace returns a copy of the slice with the first n non-overlapping instances of old replaced by new.
|
// Replace returns a copy of the slice with the first n non-overlapping instances of old replaced by new.
|
||||||
// Play: https://go.dev/play/p/P5mZp7IhOFo
|
// Play: https://go.dev/play/p/P5mZp7IhOFo
|
||||||
func Replace[T comparable](slice []T, old T, new T, n int) []T {
|
func Replace[T comparable](slice []T, old T, new T, n int) []T {
|
||||||
|
|||||||
@@ -460,6 +460,34 @@ func ExampleReduce() {
|
|||||||
// 6
|
// 6
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleReduceBy() {
|
||||||
|
result1 := ReduceBy([]int{1, 2, 3, 4}, 0, func(_ int, item int, agg int) int {
|
||||||
|
return agg + item
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := ReduceBy([]int{1, 2, 3, 4}, "", func(_ int, item int, agg string) string {
|
||||||
|
return agg + fmt.Sprintf("%v", item)
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 10
|
||||||
|
// 1234
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleReduceRight() {
|
||||||
|
result := ReduceRight([]int{1, 2, 3, 4}, "", func(_ int, item int, agg string) string {
|
||||||
|
return agg + fmt.Sprintf("%v", item)
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 4321
|
||||||
|
}
|
||||||
|
|
||||||
func ExampleReplace() {
|
func ExampleReplace() {
|
||||||
strs := []string{"a", "b", "c", "a"}
|
strs := []string{"a", "b", "c", "a"}
|
||||||
|
|
||||||
|
|||||||
@@ -405,6 +405,32 @@ func TestReduce(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReduceBy(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestReduceBy")
|
||||||
|
|
||||||
|
result1 := ReduceBy([]int{1, 2, 3, 4}, 0, func(_ int, item int, agg int) int {
|
||||||
|
return agg + item
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := ReduceBy([]int{1, 2, 3, 4}, "", func(_ int, item int, agg string) string {
|
||||||
|
return agg + fmt.Sprintf("%v", item)
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Equal(10, result1)
|
||||||
|
assert.Equal("1234", result2)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReduceRight(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "ReduceRight")
|
||||||
|
|
||||||
|
result := ReduceRight([]int{1, 2, 3, 4}, "", func(_ int, item int, agg string) string {
|
||||||
|
return agg + fmt.Sprintf("%v", item)
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Equal("4321", result)
|
||||||
|
}
|
||||||
|
|
||||||
func TestIntSlice(t *testing.T) {
|
func TestIntSlice(t *testing.T) {
|
||||||
var nums []any
|
var nums []any
|
||||||
nums = append(nums, 1, 2, 3)
|
nums = append(nums, 1, 2, 3)
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
// Copyright 2023 dudaodong@gmail.com. All rights resulterved.
|
// Copyright 2023 dudaodong@gmail.com. All rights resulterved.
|
||||||
// Use of this source code is governed by MIT license
|
// Use of this source code is governed by MIT license
|
||||||
|
|
||||||
// Package stream implements a sequence of elements supporting sequential and parallel aggregate operations.
|
// Package stream 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. it's complete, but not
|
// this package is an experiment to explore if stream in go can work as the way java does. its function is very limited.
|
||||||
// powerful like other libs
|
|
||||||
package stream
|
package stream
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -52,13 +51,14 @@ type stream[T any] struct {
|
|||||||
source []T
|
source []T
|
||||||
}
|
}
|
||||||
|
|
||||||
// Of creates a stream stream whose elements are the specified values.
|
// Of creates a stream whose elements are the specified values.
|
||||||
|
// Play: https://go.dev/play/p/jI6_iZZuVFE
|
||||||
func Of[T any](elems ...T) stream[T] {
|
func Of[T any](elems ...T) stream[T] {
|
||||||
return FromSlice(elems)
|
return FromSlice(elems)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate stream where each element is generated by the provided generater function
|
// Generate stream where each element is generated by the provided generater function
|
||||||
// generater function: func() func() (item T, ok bool) {}
|
// Play: https://go.dev/play/p/rkOWL1yA3j9
|
||||||
func Generate[T any](generator func() func() (item T, ok bool)) stream[T] {
|
func Generate[T any](generator func() func() (item T, ok bool)) stream[T] {
|
||||||
source := make([]T, 0)
|
source := make([]T, 0)
|
||||||
|
|
||||||
@@ -75,11 +75,13 @@ func Generate[T any](generator func() func() (item T, ok bool)) stream[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FromSlice creates stream from slice.
|
// FromSlice creates stream from slice.
|
||||||
|
// Play: https://go.dev/play/p/wywTO0XZtI4
|
||||||
func FromSlice[T any](source []T) stream[T] {
|
func FromSlice[T any](source []T) stream[T] {
|
||||||
return stream[T]{source: source}
|
return stream[T]{source: source}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromChannel creates stream from channel.
|
// FromChannel creates stream from channel.
|
||||||
|
// Play: https://go.dev/play/p/9TZYugGMhXZ
|
||||||
func FromChannel[T any](source <-chan T) stream[T] {
|
func FromChannel[T any](source <-chan T) stream[T] {
|
||||||
s := make([]T, 0)
|
s := make([]T, 0)
|
||||||
|
|
||||||
@@ -91,6 +93,7 @@ func FromChannel[T any](source <-chan T) stream[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FromRange creates a number stream from start to end. both start and end are included. [start, end]
|
// FromRange creates a number stream from start to end. both start and end are included. [start, end]
|
||||||
|
// Play: https://go.dev/play/p/9Ex1-zcg-B-
|
||||||
func FromRange[T constraints.Integer | constraints.Float](start, end, step T) stream[T] {
|
func FromRange[T constraints.Integer | constraints.Float](start, end, step T) stream[T] {
|
||||||
if end < start {
|
if end < start {
|
||||||
panic("stream.FromRange: param start should be before param end")
|
panic("stream.FromRange: param start should be before param end")
|
||||||
@@ -109,6 +112,7 @@ func FromRange[T constraints.Integer | constraints.Float](start, end, step T) st
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Concat creates a lazily concatenated stream whose elements are all the elements of the first stream followed by all the elements of the second stream.
|
// Concat creates a lazily concatenated stream whose elements are all the elements of the first stream followed by all the elements of the second stream.
|
||||||
|
// Play: https://go.dev/play/p/HM4OlYk_OUC
|
||||||
func Concat[T any](a, b stream[T]) stream[T] {
|
func Concat[T any](a, b stream[T]) stream[T] {
|
||||||
source := make([]T, 0)
|
source := make([]T, 0)
|
||||||
|
|
||||||
@@ -119,6 +123,7 @@ func Concat[T any](a, b stream[T]) stream[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Distinct returns a stream that removes the duplicated items.
|
// Distinct returns a stream that removes the duplicated items.
|
||||||
|
// Play: https://go.dev/play/p/eGkOSrm64cB
|
||||||
func (s stream[T]) Distinct() stream[T] {
|
func (s stream[T]) Distinct() stream[T] {
|
||||||
source := make([]T, 0)
|
source := make([]T, 0)
|
||||||
|
|
||||||
@@ -147,6 +152,7 @@ func hashKey(data any) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Filter returns a stream consisting of the elements of this stream that match the given predicate.
|
// Filter returns a stream consisting of the elements of this stream that match the given predicate.
|
||||||
|
// Play: https://go.dev/play/p/MFlSANo-buc
|
||||||
func (s stream[T]) Filter(predicate func(item T) bool) stream[T] {
|
func (s stream[T]) Filter(predicate func(item T) bool) stream[T] {
|
||||||
source := make([]T, 0)
|
source := make([]T, 0)
|
||||||
|
|
||||||
@@ -160,6 +166,7 @@ func (s stream[T]) Filter(predicate func(item T) bool) stream[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Map returns a stream consisting of the elements of this stream that apply the given function to elements of stream.
|
// Map returns a stream consisting of the elements of this stream that apply the given function to elements of stream.
|
||||||
|
// Play: https://go.dev/play/p/OtNQUImdYko
|
||||||
func (s stream[T]) Map(mapper func(item T) T) stream[T] {
|
func (s stream[T]) Map(mapper func(item T) T) stream[T] {
|
||||||
source := make([]T, s.Count())
|
source := make([]T, s.Count())
|
||||||
|
|
||||||
@@ -171,6 +178,7 @@ func (s stream[T]) Map(mapper func(item T) T) stream[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Peek returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream.
|
// Peek returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream.
|
||||||
|
// Play: https://go.dev/play/p/u1VNzHs6cb2
|
||||||
func (s stream[T]) Peek(consumer func(item T)) stream[T] {
|
func (s stream[T]) Peek(consumer func(item T)) stream[T] {
|
||||||
for _, v := range s.source {
|
for _, v := range s.source {
|
||||||
consumer(v)
|
consumer(v)
|
||||||
@@ -181,6 +189,7 @@ func (s stream[T]) Peek(consumer func(item T)) stream[T] {
|
|||||||
|
|
||||||
// Skip returns a stream consisting of the remaining elements of this stream after discarding the first n elements of the stream.
|
// Skip returns a stream consisting of the remaining elements of this stream after discarding the first n elements of the stream.
|
||||||
// If this stream contains fewer than n elements then an empty stream will be returned.
|
// If this stream contains fewer than n elements then an empty stream will be returned.
|
||||||
|
// Play: https://go.dev/play/p/fNdHbqjahum
|
||||||
func (s stream[T]) Skip(n int) stream[T] {
|
func (s stream[T]) Skip(n int) stream[T] {
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
return s
|
return s
|
||||||
@@ -201,6 +210,7 @@ func (s stream[T]) Skip(n int) stream[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Limit returns a stream consisting of the elements of this stream, truncated to be no longer than maxSize in length.
|
// Limit returns a stream consisting of the elements of this stream, truncated to be no longer than maxSize in length.
|
||||||
|
// Play: https://go.dev/play/p/qsO4aniDcGf
|
||||||
func (s stream[T]) Limit(maxSize int) stream[T] {
|
func (s stream[T]) Limit(maxSize int) stream[T] {
|
||||||
if s.source == nil {
|
if s.source == nil {
|
||||||
return s
|
return s
|
||||||
@@ -220,6 +230,7 @@ func (s stream[T]) Limit(maxSize int) stream[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AllMatch returns whether all elements of this stream match the provided predicate.
|
// AllMatch returns whether all elements of this stream match the provided predicate.
|
||||||
|
// Play: https://go.dev/play/p/V5TBpVRs-Cx
|
||||||
func (s stream[T]) AllMatch(predicate func(item T) bool) bool {
|
func (s stream[T]) AllMatch(predicate func(item T) bool) bool {
|
||||||
for _, v := range s.source {
|
for _, v := range s.source {
|
||||||
if !predicate(v) {
|
if !predicate(v) {
|
||||||
@@ -231,6 +242,7 @@ func (s stream[T]) AllMatch(predicate func(item T) bool) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AnyMatch returns whether any elements of this stream match the provided predicate.
|
// AnyMatch returns whether any elements of this stream match the provided predicate.
|
||||||
|
// Play: https://go.dev/play/p/PTCnWn4OxSn
|
||||||
func (s stream[T]) AnyMatch(predicate func(item T) bool) bool {
|
func (s stream[T]) AnyMatch(predicate func(item T) bool) bool {
|
||||||
for _, v := range s.source {
|
for _, v := range s.source {
|
||||||
if predicate(v) {
|
if predicate(v) {
|
||||||
@@ -242,11 +254,13 @@ func (s stream[T]) AnyMatch(predicate func(item T) bool) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NoneMatch returns whether no elements of this stream match the provided predicate.
|
// NoneMatch returns whether no elements of this stream match the provided predicate.
|
||||||
|
// Play: https://go.dev/play/p/iWS64pL1oo3
|
||||||
func (s stream[T]) NoneMatch(predicate func(item T) bool) bool {
|
func (s stream[T]) NoneMatch(predicate func(item T) bool) bool {
|
||||||
return !s.AnyMatch(predicate)
|
return !s.AnyMatch(predicate)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ForEach performs an action for each element of this stream.
|
// ForEach performs an action for each element of this stream.
|
||||||
|
// Play: https://go.dev/play/p/Dsm0fPqcidk
|
||||||
func (s stream[T]) ForEach(action func(item T)) {
|
func (s stream[T]) ForEach(action func(item T)) {
|
||||||
for _, v := range s.source {
|
for _, v := range s.source {
|
||||||
action(v)
|
action(v)
|
||||||
@@ -254,20 +268,23 @@ func (s stream[T]) ForEach(action func(item T)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reduce performs a reduction on the elements of this stream, using an associative accumulation function, and returns an Optional describing the reduced value, if any.
|
// Reduce performs a reduction on the elements of this stream, using an associative accumulation function, and returns an Optional describing the reduced value, if any.
|
||||||
func (s stream[T]) Reduce(init T, accumulator func(a, b T) T) T {
|
// Play: https://go.dev/play/p/6uzZjq_DJLU
|
||||||
|
func (s stream[T]) Reduce(initial T, accumulator func(a, b T) T) T {
|
||||||
for _, v := range s.source {
|
for _, v := range s.source {
|
||||||
init = accumulator(init, v)
|
initial = accumulator(initial, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
return init
|
return initial
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count returns the count of elements in the stream.
|
// Count returns the count of elements in the stream.
|
||||||
|
// Play: https://go.dev/play/p/r3koY6y_Xo-
|
||||||
func (s stream[T]) Count() int {
|
func (s stream[T]) Count() int {
|
||||||
return len(s.source)
|
return len(s.source)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindFirst returns the first element of this stream and true, or zero value and false if the stream is empty.
|
// FindFirst returns the first element of this stream and true, or zero value and false if the stream is empty.
|
||||||
|
// Play: https://go.dev/play/p/9xEf0-6C1e3
|
||||||
func (s stream[T]) FindFirst() (T, bool) {
|
func (s stream[T]) FindFirst() (T, bool) {
|
||||||
var result T
|
var result T
|
||||||
|
|
||||||
@@ -279,6 +296,7 @@ func (s stream[T]) FindFirst() (T, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reverse returns a stream whose elements are reverse order of given stream.
|
// Reverse returns a stream whose elements are reverse order of given stream.
|
||||||
|
// Play: https://go.dev/play/p/A8_zkJnLHm4
|
||||||
func (s stream[T]) Reverse() stream[T] {
|
func (s stream[T]) Reverse() stream[T] {
|
||||||
l := len(s.source)
|
l := len(s.source)
|
||||||
source := make([]T, l)
|
source := make([]T, l)
|
||||||
@@ -290,6 +308,7 @@ func (s stream[T]) Reverse() stream[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Range returns a stream whose elements are in the range from start(included) to end(excluded) original stream.
|
// Range returns a stream whose elements are in the range from start(included) to end(excluded) original stream.
|
||||||
|
// Play: https://go.dev/play/p/indZY5V2f4j
|
||||||
func (s stream[T]) Range(start, end int) stream[T] {
|
func (s stream[T]) Range(start, end int) stream[T] {
|
||||||
if start < 0 {
|
if start < 0 {
|
||||||
start = 0
|
start = 0
|
||||||
@@ -315,6 +334,7 @@ func (s stream[T]) Range(start, end int) stream[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sorted returns a stream consisting of the elements of this stream, sorted according to the provided less function.
|
// Sorted returns a stream consisting of the elements of this stream, sorted according to the provided less function.
|
||||||
|
// Play: https://go.dev/play/p/XXtng5uonFj
|
||||||
func (s stream[T]) Sorted(less func(a, b T) bool) stream[T] {
|
func (s stream[T]) Sorted(less func(a, b T) bool) stream[T] {
|
||||||
source := []T{}
|
source := []T{}
|
||||||
source = append(source, s.source...)
|
source = append(source, s.source...)
|
||||||
@@ -326,6 +346,7 @@ func (s stream[T]) Sorted(less func(a, b T) bool) stream[T] {
|
|||||||
|
|
||||||
// Max returns the maximum element of this stream according to the provided less function.
|
// Max returns the maximum element of this stream according to the provided less function.
|
||||||
// less: a > b
|
// less: a > b
|
||||||
|
// Play: https://go.dev/play/p/fm-1KOPtGzn
|
||||||
func (s stream[T]) Max(less func(a, b T) bool) (T, bool) {
|
func (s stream[T]) Max(less func(a, b T) bool) (T, bool) {
|
||||||
var max T
|
var max T
|
||||||
|
|
||||||
@@ -343,6 +364,7 @@ func (s stream[T]) Max(less func(a, b T) bool) (T, bool) {
|
|||||||
|
|
||||||
// Min returns the minimum element of this stream according to the provided less function.
|
// Min returns the minimum element of this stream according to the provided less function.
|
||||||
// less: a < b
|
// less: a < b
|
||||||
|
// Play: https://go.dev/play/p/vZfIDgGNRe_0
|
||||||
func (s stream[T]) Min(less func(a, b T) bool) (T, bool) {
|
func (s stream[T]) Min(less func(a, b T) bool) (T, bool) {
|
||||||
var min T
|
var min T
|
||||||
|
|
||||||
@@ -360,6 +382,7 @@ func (s stream[T]) Min(less func(a, b T) bool) (T, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ToSlice return the elements in the stream.
|
// ToSlice return the elements in the stream.
|
||||||
|
// Play: https://go.dev/play/p/jI6_iZZuVFE
|
||||||
func (s stream[T]) ToSlice() []T {
|
func (s stream[T]) ToSlice() []T {
|
||||||
return s.source
|
return s.source
|
||||||
}
|
}
|
||||||
|
|||||||
373
stream/stream_example_test.go
Normal file
373
stream/stream_example_test.go
Normal file
@@ -0,0 +1,373 @@
|
|||||||
|
package stream
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExampleOf() {
|
||||||
|
s := Of(1, 2, 3)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleFromSlice() {
|
||||||
|
s := FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleFromChannel() {
|
||||||
|
ch := make(chan int)
|
||||||
|
go func() {
|
||||||
|
for i := 1; i < 4; i++ {
|
||||||
|
ch <- i
|
||||||
|
}
|
||||||
|
close(ch)
|
||||||
|
}()
|
||||||
|
|
||||||
|
s := FromChannel(ch)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleFromRange() {
|
||||||
|
s := FromRange(1, 5, 1)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3 4 5]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleGenerate() {
|
||||||
|
n := 0
|
||||||
|
max := 4
|
||||||
|
|
||||||
|
generator := func() func() (int, bool) {
|
||||||
|
return func() (int, bool) {
|
||||||
|
n++
|
||||||
|
return n, n < max
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s := Generate(generator)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleConcat() {
|
||||||
|
s1 := FromSlice([]int{1, 2, 3})
|
||||||
|
s2 := FromSlice([]int{4, 5, 6})
|
||||||
|
|
||||||
|
s := Concat(s1, s2)
|
||||||
|
|
||||||
|
data := s.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3 4 5 6]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Distinct() {
|
||||||
|
original := FromSlice([]int{1, 2, 2, 3, 3, 3})
|
||||||
|
distinct := original.Distinct()
|
||||||
|
|
||||||
|
data1 := original.ToSlice()
|
||||||
|
data2 := distinct.ToSlice()
|
||||||
|
|
||||||
|
fmt.Println(data1)
|
||||||
|
fmt.Println(data2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 2 3 3 3]
|
||||||
|
// [1 2 3]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Filter() {
|
||||||
|
original := FromSlice([]int{1, 2, 3, 4, 5})
|
||||||
|
|
||||||
|
isEven := func(n int) bool {
|
||||||
|
return n%2 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
even := original.Filter(isEven)
|
||||||
|
|
||||||
|
fmt.Println(even.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [2 4]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Map() {
|
||||||
|
original := FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
addOne := func(n int) int {
|
||||||
|
return n + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
increament := original.Map(addOne)
|
||||||
|
|
||||||
|
fmt.Println(increament.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [2 3 4]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Peek() {
|
||||||
|
original := FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
data := []string{}
|
||||||
|
peekStream := original.Peek(func(n int) {
|
||||||
|
data = append(data, fmt.Sprint("value", n))
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(original.ToSlice())
|
||||||
|
fmt.Println(peekStream.ToSlice())
|
||||||
|
fmt.Println(data)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3]
|
||||||
|
// [1 2 3]
|
||||||
|
// [value1 value2 value3]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Skip() {
|
||||||
|
original := FromSlice([]int{1, 2, 3, 4})
|
||||||
|
|
||||||
|
s1 := original.Skip(-1)
|
||||||
|
s2 := original.Skip(0)
|
||||||
|
s3 := original.Skip(1)
|
||||||
|
s4 := original.Skip(5)
|
||||||
|
|
||||||
|
fmt.Println(s1.ToSlice())
|
||||||
|
fmt.Println(s2.ToSlice())
|
||||||
|
fmt.Println(s3.ToSlice())
|
||||||
|
fmt.Println(s4.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [1 2 3 4]
|
||||||
|
// [1 2 3 4]
|
||||||
|
// [2 3 4]
|
||||||
|
// []
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Limit() {
|
||||||
|
original := FromSlice([]int{1, 2, 3, 4})
|
||||||
|
|
||||||
|
s1 := original.Limit(-1)
|
||||||
|
s2 := original.Limit(0)
|
||||||
|
s3 := original.Limit(1)
|
||||||
|
s4 := original.Limit(5)
|
||||||
|
|
||||||
|
fmt.Println(s1.ToSlice())
|
||||||
|
fmt.Println(s2.ToSlice())
|
||||||
|
fmt.Println(s3.ToSlice())
|
||||||
|
fmt.Println(s4.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// []
|
||||||
|
// []
|
||||||
|
// [1]
|
||||||
|
// [1 2 3 4]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_AllMatch() {
|
||||||
|
original := FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result1 := original.AllMatch(func(item int) bool {
|
||||||
|
return item > 0
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := original.AllMatch(func(item int) bool {
|
||||||
|
return item > 1
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_AnyMatch() {
|
||||||
|
original := FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result1 := original.AnyMatch(func(item int) bool {
|
||||||
|
return item > 1
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := original.AnyMatch(func(item int) bool {
|
||||||
|
return item > 3
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_NoneMatch() {
|
||||||
|
original := FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result1 := original.NoneMatch(func(item int) bool {
|
||||||
|
return item > 3
|
||||||
|
})
|
||||||
|
|
||||||
|
result2 := original.NoneMatch(func(item int) bool {
|
||||||
|
return item > 1
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_ForEach() {
|
||||||
|
original := FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result := 0
|
||||||
|
original.ForEach(func(item int) {
|
||||||
|
result += item
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 6
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Reduce() {
|
||||||
|
original := FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result := original.Reduce(0, func(a, b int) int {
|
||||||
|
return a + b
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 6
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_FindFirst() {
|
||||||
|
original := FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
result, ok := original.FindFirst()
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
fmt.Println(ok)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Reverse() {
|
||||||
|
original := FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
reverse := original.Reverse()
|
||||||
|
|
||||||
|
fmt.Println(reverse.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [3 2 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Range() {
|
||||||
|
original := FromSlice([]int{1, 2, 3})
|
||||||
|
|
||||||
|
s1 := original.Range(0, 0)
|
||||||
|
s2 := original.Range(0, 1)
|
||||||
|
s3 := original.Range(0, 3)
|
||||||
|
s4 := original.Range(1, 2)
|
||||||
|
|
||||||
|
fmt.Println(s1.ToSlice())
|
||||||
|
fmt.Println(s2.ToSlice())
|
||||||
|
fmt.Println(s3.ToSlice())
|
||||||
|
fmt.Println(s4.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// []
|
||||||
|
// [1]
|
||||||
|
// [1 2 3]
|
||||||
|
// [2]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Sorted() {
|
||||||
|
original := FromSlice([]int{4, 2, 1, 3})
|
||||||
|
|
||||||
|
sorted := original.Sorted(func(a, b int) bool { return a < b })
|
||||||
|
|
||||||
|
fmt.Println(original.ToSlice())
|
||||||
|
fmt.Println(sorted.ToSlice())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [4 2 1 3]
|
||||||
|
// [1 2 3 4]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Max() {
|
||||||
|
original := FromSlice([]int{4, 2, 1, 3})
|
||||||
|
|
||||||
|
max, ok := original.Max(func(a, b int) bool { return a > b })
|
||||||
|
|
||||||
|
fmt.Println(max)
|
||||||
|
fmt.Println(ok)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 4
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Min() {
|
||||||
|
original := FromSlice([]int{4, 2, 1, 3})
|
||||||
|
|
||||||
|
min, ok := original.Min(func(a, b int) bool { return a < b })
|
||||||
|
|
||||||
|
fmt.Println(min)
|
||||||
|
fmt.Println(ok)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleStream_Count() {
|
||||||
|
s1 := FromSlice([]int{1, 2, 3})
|
||||||
|
s2 := FromSlice([]int{})
|
||||||
|
|
||||||
|
fmt.Println(s1.Count())
|
||||||
|
fmt.Println(s2.Count())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 3
|
||||||
|
// 0
|
||||||
|
}
|
||||||
@@ -147,13 +147,17 @@ func TestStream_Peek(t *testing.T) {
|
|||||||
func TestStream_Skip(t *testing.T) {
|
func TestStream_Skip(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestStream_Peek")
|
assert := internal.NewAssert(t, "TestStream_Peek")
|
||||||
|
|
||||||
stream := FromSlice([]int{1, 2, 3, 4, 5, 6})
|
stream := FromSlice([]int{1, 2, 3, 4})
|
||||||
|
|
||||||
s1 := stream.Skip(-1)
|
s1 := stream.Skip(-1)
|
||||||
s2 := stream.Skip(0)
|
s2 := stream.Skip(0)
|
||||||
|
s3 := stream.Skip(1)
|
||||||
|
s4 := stream.Skip(2)
|
||||||
|
|
||||||
assert.Equal([]int{1, 2, 3, 4, 5, 6}, s1.ToSlice())
|
assert.Equal([]int{1, 2, 3, 4}, s1.ToSlice())
|
||||||
assert.Equal([]int{1, 2, 3, 4, 5, 6}, s2.ToSlice())
|
assert.Equal([]int{1, 2, 3, 4}, s2.ToSlice())
|
||||||
|
assert.Equal([]int{2, 3, 4}, s3.ToSlice())
|
||||||
|
assert.Equal([]int{3, 4}, s4.ToSlice())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStream_Limit(t *testing.T) {
|
func TestStream_Limit(t *testing.T) {
|
||||||
@@ -248,6 +252,16 @@ func TestStream_Reduce(t *testing.T) {
|
|||||||
assert.Equal(6, result)
|
assert.Equal(6, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStream_Count(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestStream_Count")
|
||||||
|
|
||||||
|
s1 := FromSlice([]int{1, 2, 3})
|
||||||
|
s2 := FromSlice([]int{})
|
||||||
|
|
||||||
|
assert.Equal(3, s1.Count())
|
||||||
|
assert.Equal(0, s2.Count())
|
||||||
|
}
|
||||||
|
|
||||||
func TestStream_FindFirst(t *testing.T) {
|
func TestStream_FindFirst(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestStream_FindFirst")
|
assert := internal.NewAssert(t, "TestStream_FindFirst")
|
||||||
|
|
||||||
|
|||||||
@@ -362,7 +362,7 @@ func WordCount(s string) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RemoveNonPrintable remove non-printable characters from a string.
|
// RemoveNonPrintable remove non-printable characters from a string.
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/og47F5x_jTZ
|
||||||
func RemoveNonPrintable(str string) string {
|
func RemoveNonPrintable(str string) string {
|
||||||
result := strings.Map(func(r rune) rune {
|
result := strings.Map(func(r rune) rune {
|
||||||
if unicode.IsPrint(r) {
|
if unicode.IsPrint(r) {
|
||||||
|
|||||||
12
system/os.go
12
system/os.go
@@ -15,6 +15,10 @@ import (
|
|||||||
"golang.org/x/text/encoding/simplifiedchinese"
|
"golang.org/x/text/encoding/simplifiedchinese"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
Option func(*exec.Cmd)
|
||||||
|
)
|
||||||
|
|
||||||
// IsWindows check if current os is windows.
|
// IsWindows check if current os is windows.
|
||||||
// Play: https://go.dev/play/p/XzJULbzmf9m
|
// Play: https://go.dev/play/p/XzJULbzmf9m
|
||||||
func IsWindows() bool {
|
func IsWindows() bool {
|
||||||
@@ -66,7 +70,7 @@ func CompareOsEnv(key, comparedEnv string) bool {
|
|||||||
// in linux, use /bin/bash -c to execute command
|
// in linux, use /bin/bash -c to execute command
|
||||||
// in windows, use powershell.exe to execute command
|
// in windows, use powershell.exe to execute command
|
||||||
// Play: https://go.dev/play/p/n-2fLyZef-4
|
// Play: https://go.dev/play/p/n-2fLyZef-4
|
||||||
func ExecCommand(command string) (stdout, stderr string, err error) {
|
func ExecCommand(command string, opts ...Option) (stdout, stderr string, err error) {
|
||||||
var out bytes.Buffer
|
var out bytes.Buffer
|
||||||
var errOut bytes.Buffer
|
var errOut bytes.Buffer
|
||||||
|
|
||||||
@@ -74,6 +78,12 @@ func ExecCommand(command string) (stdout, stderr string, err error) {
|
|||||||
if IsWindows() {
|
if IsWindows() {
|
||||||
cmd = exec.Command("powershell.exe", command)
|
cmd = exec.Command("powershell.exe", command)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
if opt != nil {
|
||||||
|
opt(cmd)
|
||||||
|
}
|
||||||
|
}
|
||||||
cmd.Stdout = &out
|
cmd.Stdout = &out
|
||||||
cmd.Stderr = &errOut
|
cmd.Stderr = &errOut
|
||||||
|
|
||||||
|
|||||||
18
system/os_linux.go
Normal file
18
system/os_linux.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package system
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func WithForeground() Option {
|
||||||
|
return func(c *exec.Cmd) {
|
||||||
|
if c.SysProcAttr == nil {
|
||||||
|
c.SysProcAttr = &syscall.SysProcAttr{
|
||||||
|
Foreground: true,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.SysProcAttr.Foreground = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
system/os_windows.go
Normal file
18
system/os_windows.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package system
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func WithWinHide() Option {
|
||||||
|
return func(c *exec.Cmd) {
|
||||||
|
if c.SysProcAttr == nil {
|
||||||
|
c.SysProcAttr = &syscall.SysProcAttr{
|
||||||
|
HideWindow: true,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.SysProcAttr.HideWindow = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -59,7 +59,7 @@ func IsAllLower(str string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IsASCII checks if string is all ASCII char.
|
// IsASCII checks if string is all ASCII char.
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/hfQNPLX0jNa
|
||||||
func IsASCII(str string) bool {
|
func IsASCII(str string) bool {
|
||||||
for i := 0; i < len(str); i++ {
|
for i := 0; i < len(str); i++ {
|
||||||
if str[i] > unicode.MaxASCII {
|
if str[i] > unicode.MaxASCII {
|
||||||
@@ -70,7 +70,7 @@ func IsASCII(str string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IsPrintable checks if string is all printable chars.
|
// IsPrintable checks if string is all printable chars.
|
||||||
// Play: todo
|
// Play: https://go.dev/play/p/Pe1FE2gdtTP
|
||||||
func IsPrintable(str string) bool {
|
func IsPrintable(str string) bool {
|
||||||
for _, r := range str {
|
for _, r := range str {
|
||||||
if !unicode.IsPrint(r) {
|
if !unicode.IsPrint(r) {
|
||||||
@@ -112,7 +112,7 @@ func ContainLetter(str string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IsJSON checks if the string is valid JSON.
|
// IsJSON checks if the string is valid JSON.
|
||||||
// Play: https://go.dev/play/p/sRS6c4K8jGk
|
// Play: https://go.dev/play/p/8Kip1Itjiil
|
||||||
func IsJSON(str string) bool {
|
func IsJSON(str string) bool {
|
||||||
var js json.RawMessage
|
var js json.RawMessage
|
||||||
return json.Unmarshal([]byte(str), &js) == nil
|
return json.Unmarshal([]byte(str), &js) == nil
|
||||||
@@ -369,3 +369,29 @@ func IsGBK(data []byte) bool {
|
|||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsNumberStr check if the value is number(integer, float) or not.
|
||||||
|
// Play: todo
|
||||||
|
func IsNumber(v any) bool {
|
||||||
|
return IsInt(v) || IsFloat(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsFloat check if the value is float(float32, float34) or not.
|
||||||
|
// Play: todo
|
||||||
|
func IsFloat(v any) bool {
|
||||||
|
switch v.(type) {
|
||||||
|
case float32, float64:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsInt check if the value is integer(int, unit) or not.
|
||||||
|
// Play: todo
|
||||||
|
func IsInt(v any) bool {
|
||||||
|
switch v.(type) {
|
||||||
|
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
@@ -285,8 +285,8 @@ func ExampleIsIntStr() {
|
|||||||
func ExampleIsJSON() {
|
func ExampleIsJSON() {
|
||||||
result1 := IsJSON("{}")
|
result1 := IsJSON("{}")
|
||||||
result2 := IsJSON("{\"name\": \"test\"}")
|
result2 := IsJSON("{\"name\": \"test\"}")
|
||||||
result3 := IsIntStr("")
|
result3 := IsJSON("")
|
||||||
result4 := IsIntStr("abc")
|
result4 := IsJSON("abc")
|
||||||
|
|
||||||
fmt.Println(result1)
|
fmt.Println(result1)
|
||||||
fmt.Println(result2)
|
fmt.Println(result2)
|
||||||
@@ -449,3 +449,57 @@ func ExampleIsPrintable() {
|
|||||||
// true
|
// true
|
||||||
// false
|
// false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleIsInt() {
|
||||||
|
result1 := IsInt("")
|
||||||
|
result2 := IsInt("3")
|
||||||
|
result3 := IsInt(0.1)
|
||||||
|
result4 := IsInt(0)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleIsFloat() {
|
||||||
|
result1 := IsFloat("")
|
||||||
|
result2 := IsFloat("3")
|
||||||
|
result3 := IsFloat(0)
|
||||||
|
result4 := IsFloat(0.1)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleIsNumber() {
|
||||||
|
result1 := IsNumber("")
|
||||||
|
result2 := IsNumber("3")
|
||||||
|
result3 := IsNumber(0)
|
||||||
|
result4 := IsNumber(0.1)
|
||||||
|
|
||||||
|
fmt.Println(result1)
|
||||||
|
fmt.Println(result2)
|
||||||
|
fmt.Println(result3)
|
||||||
|
fmt.Println(result4)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
// true
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
|||||||
@@ -100,6 +100,34 @@ func TestIsJSON(t *testing.T) {
|
|||||||
assert.Equal(false, IsJSON("&@#$%^&*"))
|
assert.Equal(false, IsJSON("&@#$%^&*"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIsNumber(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestIsNumber")
|
||||||
|
|
||||||
|
assert.Equal(false, IsNumber(""))
|
||||||
|
assert.Equal(false, IsNumber("3"))
|
||||||
|
assert.Equal(true, IsNumber(0))
|
||||||
|
assert.Equal(true, IsNumber(0.1))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsFloat(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestIsFloat")
|
||||||
|
|
||||||
|
assert.Equal(false, IsFloat(""))
|
||||||
|
assert.Equal(false, IsFloat("3"))
|
||||||
|
assert.Equal(false, IsFloat(0))
|
||||||
|
assert.Equal(true, IsFloat(0.1))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsInt(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestIsInt")
|
||||||
|
|
||||||
|
assert.Equal(false, IsInt(""))
|
||||||
|
assert.Equal(false, IsInt("3"))
|
||||||
|
assert.Equal(false, IsInt(0.1))
|
||||||
|
assert.Equal(true, IsInt(0))
|
||||||
|
assert.Equal(true, IsInt(-1))
|
||||||
|
}
|
||||||
|
|
||||||
func TestIsNumberStr(t *testing.T) {
|
func TestIsNumberStr(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestIsNumberStr")
|
assert := internal.NewAssert(t, "TestIsNumberStr")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user