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

Compare commits

...

13 Commits

Author SHA1 Message Date
dudaodong
3beb769f09 release v2.2.0 2023-05-18 10:53:02 +08:00
dudaodong
8af02ff95b doc: update readme file 2023-05-18 10:51:33 +08:00
dudaodong
ba4485d8c0 merge main 2023-05-18 10:32:36 +08:00
dudaodong
8a1dd40738 doc: add doc for AddYear function 2023-05-18 10:27:37 +08:00
dudaodong
85e2806531 doc: add doc for FindLast 2023-05-18 10:21:24 +08:00
will
1616d3d1be feat:addFindLast for stream (#95)
Co-authored-by: sunyaoyao <sunyaoyao@kezaihui.com>
2023-05-18 10:17:15 +08:00
tlei995
aa8e0d5c12 feat:add AddYear func (#96)
Co-authored-by: leitao <leitao@kezaihui.com>
2023-05-18 10:14:23 +08:00
dudaodong
f05477d9cf fix: update logic of Percent function 2023-05-18 10:11:48 +08:00
dudaodong
cd91e16b26 doc: update document for strutil and convertor package 2023-05-11 10:06:32 +08:00
dudaodong
9fcf046fb3 feat: add Trim and SplitAndTrim 2023-05-10 10:53:17 +08:00
dudaodong
c3f1bc39d7 feat: add ReplaceWithMap 2023-05-10 10:29:26 +08:00
dudaodong
f5784b0f46 feat: add ReplaceByMap 2023-05-10 10:03:13 +08:00
dudaodong
c86a8a479d feat: add ToInterface 2023-05-09 12:01:57 +08:00
27 changed files with 799 additions and 38 deletions

View File

@@ -4,7 +4,7 @@
<br/> <br/>
![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf) ![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf)
[![Release](https://img.shields.io/badge/release-2.1.20-green.svg)](https://github.com/duke-git/lancet/releases) [![Release](https://img.shields.io/badge/release-2.2.0-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2) [![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2) [![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
[![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml) [![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
@@ -200,7 +200,7 @@ import "github.com/duke-git/lancet/v2/condition"
[[play](https://go.dev/play/p/W1SSUmt6pvr)] [[play](https://go.dev/play/p/W1SSUmt6pvr)]
- **<big>Or</big>** : returns false if neither a nor b is truthy. - **<big>Or</big>** : returns false if neither a nor b is truthy.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Or)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Or)]
[[play](https://go.dev/play/p/UlQTxHaeEkq)] [[play](https://go.dev/play/p/UlQTxHaeEkq)]
- **<big>Xor</big>** : returns true if a or b but not both is truthy. - **<big>Xor</big>** : returns true if a or b but not both is truthy.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Xor)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/condition.md#Xor)]
[[play](https://go.dev/play/p/gObZrW7ZbG8)] [[play](https://go.dev/play/p/gObZrW7ZbG8)]
@@ -279,6 +279,8 @@ import "github.com/duke-git/lancet/v2/convertor"
- **<big>CopyProperties</big>** : copies each field from the source struct into the destination struct. - **<big>CopyProperties</big>** : copies each field from the source struct into the destination struct.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#CopyProperties)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#CopyProperties)]
[[play](https://go.dev/play/p/oZujoB5Sgg5)] [[play](https://go.dev/play/p/oZujoB5Sgg5)]
- **<big>ToInterface</big>** : converts reflect value to its interface type.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor.md#ToInterface)]
### 6. Cryptor package is for data encryption and decryption. ### 6. Cryptor package is for data encryption and decryption.
@@ -401,6 +403,8 @@ import "github.com/duke-git/lancet/v2/datetime"
- **<big>AddMinute</big>** : add or sub day to the time. - **<big>AddMinute</big>** : add or sub day to the time.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddMinute)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddMinute)]
[[play](https://go.dev/play/p/nT1heB1KUUK)] [[play](https://go.dev/play/p/nT1heB1KUUK)]
- **<big>AddYear</big>** : add or sub year to the time.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#AddYear)]
- **<big>BeginOfMinute</big>** : return the date time at the begin of minute of specific date. - **<big>BeginOfMinute</big>** : return the date time at the begin of minute of specific date.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMinute)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#BeginOfMinute)]
[[play](https://go.dev/play/p/ieOLVJ9CiFT)] [[play](https://go.dev/play/p/ieOLVJ9CiFT)]
@@ -482,6 +486,8 @@ import "github.com/duke-git/lancet/v2/datetime"
- **<big>ToIso8601</big>** : return iso8601 time string. - **<big>ToIso8601</big>** : return iso8601 time string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToIso8601)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#ToIso8601)]
[[play](https://go.dev/play/p/mkhOHQkdeA2)] [[play](https://go.dev/play/p/mkhOHQkdeA2)]
- **<big>IsLeapYear</big>** : check if param `year` is leap year or not.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime.md#IsLeapYear)]
### 8. Datastructure package constains some common data structure. eg. list, linklist, stack, queue, set, tree, graph. ### 8. Datastructure package constains some common data structure. eg. list, linklist, stack, queue, set, tree, graph.
@@ -787,6 +793,10 @@ import "github.com/duke-git/lancet/v2/mathutil"
- **<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)] [[play](https://go.dev/play/p/Rdd8UTHZJ7u)]
- **<big>GCD</big>** : return greatest common divisor (GCD) of integers.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#GCD)]
- **<big>LCM</big>** : return Least Common Multiple (LCM) of integers.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil.md#LCM)]
### 14. Netutil package contains functions to get net information and send http request. ### 14. Netutil package contains functions to get net information and send http request.
@@ -1193,6 +1203,8 @@ import "github.com/duke-git/lancet/v2/stream"
- **<big>FindFirst</big>** : returns the first element of this stream and true, or zero value and false if the stream is empty. - **<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)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#FindFirst)]
[[play](https://go.dev/play/p/9xEf0-6C1e3)] [[play](https://go.dev/play/p/9xEf0-6C1e3)]
- **<big>FindLast</big>** : returns the last element of this stream and true, or zero value and false if the stream is empty.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#FindLast)]
- **<big>Max</big>** : returns the maximum element of this stream according to the provided less function. less fuction: a > b - **<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)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/stream.md#Max)]
[[play](https://go.dev/play/p/fm-1KOPtGzn)] [[play](https://go.dev/play/p/fm-1KOPtGzn)]
@@ -1345,6 +1357,12 @@ import "github.com/duke-git/lancet/v2/strutil"
- **<big>IndexOffset</big>** : returns the index of the first instance of substr in string after offsetting the string by `idxFrom`. - **<big>IndexOffset</big>** : returns the index of the first instance of substr in string after offsetting the string by `idxFrom`.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#IndexOffset)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#IndexOffset)]
[[play](https://go.dev/play/p/qZo4lV2fomB)] [[play](https://go.dev/play/p/qZo4lV2fomB)]
- **<big>ReplaceWithMap</big>** : returns a copy of `str`, which is replaced by a map in unordered way, case-sensitively.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#ReplaceWithMap)]
- **<big>Trim</big>** : strips whitespace (or other characters) from the beginning and end of a string.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Trim)]
- **<big>SplitAndTrim</big>** : splits string `str` by a string `delimiter` to a slice, and calls Trim to every element of slice.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SplitAndTrim)]
### 21. System package contain some functions about os, runtime, shell command. ### 21. System package contain some functions about os, runtime, shell command.

View File

@@ -4,7 +4,7 @@
<br/> <br/>
![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf) ![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf)
[![Release](https://img.shields.io/badge/release-2.1.20-green.svg)](https://github.com/duke-git/lancet/releases) [![Release](https://img.shields.io/badge/release-2.2.0-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2) [![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2) [![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
[![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml) [![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
@@ -208,7 +208,7 @@ import "github.com/duke-git/lancet/v2/condition"
[[play](https://go.dev/play/p/g2j08F_zZky)] [[play](https://go.dev/play/p/g2j08F_zZky)]
- **<big>Xnor</big>** : 如果 a 和 b 都是真的或 a 和 b 均是假的,则返回 true。 - **<big>Xnor</big>** : 如果 a 和 b 都是真的或 a 和 b 均是假的,则返回 true。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Xnor)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Xnor)]
[[play](https://go.dev/play/p/OuDB9g51643)] [[play](https://go.dev/play/p/OuDB9g51643)]
- **<big>Nand</big>** : 如果 a 和 b 都为真,返回 false否则返回 true - **<big>Nand</big>** : 如果 a 和 b 都为真,返回 false否则返回 true
[[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Nand)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/condition_zh-CN.md#Nand)]
[[play](https://go.dev/play/p/vSRMLxLIbq8)] [[play](https://go.dev/play/p/vSRMLxLIbq8)]
@@ -278,6 +278,8 @@ import "github.com/duke-git/lancet/v2/convertor"
- **<big>CopyProperties</big>** : 拷贝不同结构体之间的同名字段。 - **<big>CopyProperties</big>** : 拷贝不同结构体之间的同名字段。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#CopyProperties)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#CopyProperties)]
[[play](https://go.dev/play/p/oZujoB5Sgg5)] [[play](https://go.dev/play/p/oZujoB5Sgg5)]
- **<big>ToInterface</big>** : 将反射值转换成对应的 interface 类型。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/convertor_zh-CN.md#ToInterface)]
### 6. cryptor 加密包支持数据加密和解密,获取 md5hash 值。支持 base64, md5, hmac, aes, des, rsa。 ### 6. cryptor 加密包支持数据加密和解密,获取 md5hash 值。支持 base64, md5, hmac, aes, des, rsa。
@@ -400,6 +402,8 @@ import "github.com/duke-git/lancet/v2/datetime"
- **<big>AddMinute</big>** : 将日期加/减分钟数。 - **<big>AddMinute</big>** : 将日期加/减分钟数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddMinute)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddMinute)]
[[play](https://go.dev/play/p/nT1heB1KUUK)] [[play](https://go.dev/play/p/nT1heB1KUUK)]
- **<big>AddYear</big>** : 将日期加/减分年数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#AddYear)]
- **<big>BeginOfMinute</big>** : 返回指定时间的分钟开始时间。 - **<big>BeginOfMinute</big>** : 返回指定时间的分钟开始时间。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#BeginOfMinute)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#BeginOfMinute)]
[[play](https://go.dev/play/p/ieOLVJ9CiFT)] [[play](https://go.dev/play/p/ieOLVJ9CiFT)]
@@ -475,12 +479,14 @@ import "github.com/duke-git/lancet/v2/datetime"
- **<big>ToFormat</big>** : 返回格式'yyyy-mm-dd hh:mm:ss'的日期字符串。 - **<big>ToFormat</big>** : 返回格式'yyyy-mm-dd hh:mm:ss'的日期字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToFormat)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToFormat)]
[[play](https://go.dev/play/p/VkW08ZOaXPZ)] [[play](https://go.dev/play/p/VkW08ZOaXPZ)]
- **<big>ToFormatForTpl</big>** : 返回 tpl 格式指定的日期字符串。 - **<big>ToFormatForTpl</big>** : 返回tpl格式指定的日期字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToFormatForTpl)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToFormatForTpl)]
[[play](https://go.dev/play/p/nyXxXcQJ8L5)] [[play](https://go.dev/play/p/nyXxXcQJ8L5)]
- **<big>ToIso8601</big>** : 返回 iso8601 日期字符串。 - **<big>ToIso8601</big>** : 返回iso8601日期字符串。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToIso8601)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#ToIso8601)]
[[play](https://go.dev/play/p/mkhOHQkdeA2)] [[play](https://go.dev/play/p/mkhOHQkdeA2)]
- **<big>IsLeapYear</big>** :验证是否是闰年。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/datetime_zh-CN.md#IsLeapYear)]
### 8. datastructure 包含一些普通的数据结构实现。例如list, linklist, stack, queue, set, tree, graph. ### 8. datastructure 包含一些普通的数据结构实现。例如list, linklist, stack, queue, set, tree, graph.
@@ -786,6 +792,10 @@ import "github.com/duke-git/lancet/v2/mathutil"
- **<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)] [[play](https://go.dev/play/p/Rdd8UTHZJ7u)]
- **<big>GCD</big>** : 求最大公约数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#GCD)]
- **<big>LCM</big>** : 求最小公倍数。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/mathutil_zh-CN.md#LCM)]
### 14. netutil 网络包支持获取 ip 地址,发送 http 请求。 ### 14. netutil 网络包支持获取 ip 地址,发送 http 请求。
@@ -1130,7 +1140,7 @@ 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)]
### 18. Stream 流,该包仅验证简单的 stream 实现,功能有限。 ### 18. Stream流该包仅验证简单的stream实现功能有限。
```go ```go
import "github.com/duke-git/lancet/v2/stream" import "github.com/duke-git/lancet/v2/stream"
@@ -1189,9 +1199,11 @@ import "github.com/duke-git/lancet/v2/stream"
- **<big>Reduce</big>** : 使用关联累加函数对 stream 的元素执行 reduce 操作,并 reduce 操作结果(如果有)。 - **<big>Reduce</big>** : 使用关联累加函数对 stream 的元素执行 reduce 操作,并 reduce 操作结果(如果有)。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Reduce)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Reduce)]
[[play](https://go.dev/play/p/6uzZjq_DJLU)] [[play](https://go.dev/play/p/6uzZjq_DJLU)]
- **<big>FindFirst</big>** : 返回此 stream 的第一个元素和 true,如果 stream 为空,则返回零值和 false。 - **<big>FindFirst</big>** : 返回此 stream的第一个元素如果 stream 为空,则返回零值和 false。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#FindFirst)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#FindFirst)]
[[play](https://go.dev/play/p/9xEf0-6C1e3)] [[play](https://go.dev/play/p/9xEf0-6C1e3)]
- **<big>FindLast</big>** : 返回此 stream的最后一个元素如果 stream 为空,则返回零值和 false。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#FindLast)]
- **<big>Max</big>** : 根据提供的 less 函数返回 stream 的最大元素。less 函数: a > b - **<big>Max</big>** : 根据提供的 less 函数返回 stream 的最大元素。less 函数: a > b
[[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Max)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/stream_zh-CN.md#Max)]
[[play](https://go.dev/play/p/fm-1KOPtGzn)] [[play](https://go.dev/play/p/fm-1KOPtGzn)]
@@ -1347,6 +1359,12 @@ import "github.com/duke-git/lancet/v2/strutil"
- **<big>IndexOffset</big>** : 将字符串偏移 idxFrom 后,返回字符串中第一个 substr 实例的索引。 - **<big>IndexOffset</big>** : 将字符串偏移 idxFrom 后,返回字符串中第一个 substr 实例的索引。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#IndexOffset)] [[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#IndexOffset)]
[[play](https://go.dev/play/p/qZo4lV2fomB)] [[play](https://go.dev/play/p/qZo4lV2fomB)]
- **<big>ReplaceWithMap</big>** : 返回 string 的副本,以无序的方式被 map 替换,区分大小写。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#ReplaceWithMap)]
- **<big>Trim</big>** : 从字符串的开头和结尾去除空格(或其他字符)。 可选参数 characterMask 指定额外的剥离字符。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Trim)]
- **<big>SplitAndTrim</big>** : 将字符串str按字符串delimiter拆分为一个切片并对该数组的每个元素调用Trim。忽略Trim后为空的元素。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#SplitAndTrim)]
### 21. system 包含 os, runtime, shell command 的相关函数。 ### 21. system 包含 os, runtime, shell command 的相关函数。

View File

@@ -347,3 +347,31 @@ func CopyProperties[T, U any](dst T, src U) error {
return nil return nil
} }
// ToInterface converts reflect value to its interface type.
// Play: todo
func ToInterface(v reflect.Value) (value interface{}, ok bool) {
if v.IsValid() && v.CanInterface() {
return v.Interface(), true
}
switch v.Kind() {
case reflect.Bool:
return v.Bool(), true
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return v.Int(), true
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return v.Uint(), true
case reflect.Float32, reflect.Float64:
return v.Float(), true
case reflect.Complex64, reflect.Complex128:
return v.Complex(), true
case reflect.String:
return v.String(), true
case reflect.Ptr:
return ToInterface(v.Elem())
case reflect.Interface:
return ToInterface(v.Elem())
default:
return nil, false
}
}

View File

@@ -2,6 +2,7 @@ package convertor
import ( import (
"fmt" "fmt"
"reflect"
"strconv" "strconv"
) )
@@ -349,3 +350,17 @@ func ExampleCopyProperties() {
// 127.0.0.1 // 127.0.0.1
// 3 // 3
} }
func ExampleToInterface() {
val := reflect.ValueOf("abc")
iVal, ok := ToInterface(val)
fmt.Printf("%T\n", iVal)
fmt.Printf("%v\n", iVal)
fmt.Println(ok)
// Output:
// string
// abc
// true
}

View File

@@ -367,3 +367,32 @@ func TestCopyProperties(t *testing.T) {
assert.Equal("127.0.0.1", indicatorVO.Ip) assert.Equal("127.0.0.1", indicatorVO.Ip)
assert.Equal(3, len(indicatorVO.Disk)) assert.Equal(3, len(indicatorVO.Disk))
} }
func TestToInterface(t *testing.T) {
assert := internal.NewAssert(t, "TestToInterface")
cases := []reflect.Value{
reflect.ValueOf("abc"),
reflect.ValueOf(int(0)), reflect.ValueOf(int8(1)), reflect.ValueOf(int16(-1)), reflect.ValueOf(int32(123)), reflect.ValueOf(int64(123)),
reflect.ValueOf(uint(123)), reflect.ValueOf(uint8(123)), reflect.ValueOf(uint16(123)), reflect.ValueOf(uint32(123)), reflect.ValueOf(uint64(123)),
reflect.ValueOf(float64(12.3)), reflect.ValueOf(float32(12.3)),
reflect.ValueOf(true), reflect.ValueOf(false),
}
expected := []interface{}{
"abc",
0, int8(1), int16(-1), int32(123), int64(123),
uint(123), uint8(123), uint16(123), uint32(123), uint64(123),
float64(12.3), float32(12.3),
true, false,
}
for i := 0; i < len(cases); i++ {
actual, _ := ToInterface(cases[i])
assert.Equal(expected[i], actual)
}
nilVal, ok := ToInterface(reflect.ValueOf(nil))
assert.EqualValues(nil, nilVal)
assert.Equal(false, ok)
}

View File

@@ -72,6 +72,12 @@ func AddDay(t time.Time, day int64) time.Time {
return t.Add(24 * time.Hour * time.Duration(day)) return t.Add(24 * time.Hour * time.Duration(day))
} }
// AddYear add or sub year to the time.
// Play: todo
func AddYear(t time.Time, year int64) time.Time {
return t.Add(365 * 24 * time.Hour * time.Duration(year))
}
// GetNowDate return format yyyy-mm-dd of current date. // GetNowDate return format yyyy-mm-dd of current date.
// Play: https://go.dev/play/p/PvfkPpcpBBf // Play: https://go.dev/play/p/PvfkPpcpBBf
func GetNowDate() string { func GetNowDate() string {

View File

@@ -57,6 +57,23 @@ func ExampleAddMinute() {
// -2m0s // -2m0s
} }
func ExampleAddYear() {
now := time.Now()
after1Year := AddYear(now, 1)
diff1 := after1Year.Sub(now)
before1Year := AddYear(now, -1)
diff2 := before1Year.Sub(now)
fmt.Println(diff1)
fmt.Println(diff2)
// Output:
// 8760h0m0s
// -8760h0m0s
}
func ExampleGetNowDate() { func ExampleGetNowDate() {
result := GetNowDate() result := GetNowDate()

View File

@@ -7,6 +7,19 @@ import (
"github.com/duke-git/lancet/v2/internal" "github.com/duke-git/lancet/v2/internal"
) )
func TestAddYear(t *testing.T) {
assert := internal.NewAssert(t, "TestAddDay")
now := time.Now()
after2Years := AddYear(now, 1)
diff1 := after2Years.Sub(now)
assert.Equal(float64(8760), diff1.Hours())
before2Years := AddYear(now, -1)
diff2 := before2Years.Sub(now)
assert.Equal(float64(-8760), diff2.Hours())
}
func TestAddDay(t *testing.T) { func TestAddDay(t *testing.T) {
assert := internal.NewAssert(t, "TestAddDay") assert := internal.NewAssert(t, "TestAddDay")

View File

@@ -40,6 +40,7 @@ import (
- [DecodeByte](#DecodeByte) - [DecodeByte](#DecodeByte)
- [DeepClone](#DeepClone) - [DeepClone](#DeepClone)
- [CopyProperties](#CopyProperties) - [CopyProperties](#CopyProperties)
- [ToInterface](#ToInterface)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -629,7 +630,6 @@ func main() {
} }
``` ```
### <span id="DeepClone">DeepClone</span> ### <span id="DeepClone">DeepClone</span>
<p>Creates a deep copy of passed item, can't clone unexported field of struct.</p> <p>Creates a deep copy of passed item, can't clone unexported field of struct.</p>
@@ -694,7 +694,6 @@ func main() {
} }
``` ```
### <span id="CopyProperties">CopyProperties</span> ### <span id="CopyProperties">CopyProperties</span>
<p>Copies each field from the source struct into the destination struct. Use json.Marshal/Unmarshal, so json tag should be set for fields of dst and src struct.</p> <p>Copies each field from the source struct into the destination struct. Use json.Marshal/Unmarshal, so json tag should be set for fields of dst and src struct.</p>
@@ -772,4 +771,39 @@ func main() {
// 127.0.0.1 // 127.0.0.1
// 3 // 3
} }
```
### <span id="ToInterface">ToInterface</span>
<p>Converts reflect value to its interface type.</p>
<b>Signature:</b>
```go
func ToInterface(v reflect.Value) (value interface{}, ok bool)
```
<b>Example:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
val := reflect.ValueOf("abc")
iVal, ok := convertor.ToInterface(val)
fmt.Printf("%T\n", iVal)
fmt.Printf("%v\n", iVal)
fmt.Println(ok)
// Output:
// string
// abc
// true
}
``` ```

View File

@@ -40,7 +40,7 @@ import (
- [DecodeByte](#DecodeByte) - [DecodeByte](#DecodeByte)
- [DeepClone](#DeepClone) - [DeepClone](#DeepClone)
- [CopyProperties](#CopyProperties) - [CopyProperties](#CopyProperties)
- [ToInterface](#ToInterface)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -771,4 +771,39 @@ func main() {
// 127.0.0.1 // 127.0.0.1
// 3 // 3
} }
``` ```
### <span id="ToInterface">ToInterface</span>
<p>将反射值转换成对应的interface类型。</p>
<b>函数签名:</b>
```go
func ToInterface(v reflect.Value) (value interface{}, ok bool)
```
<b>示例:</b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/convertor"
)
func main() {
val := reflect.ValueOf("abc")
iVal, ok := convertor.ToInterface(val)
fmt.Printf("%T\n", iVal)
fmt.Printf("%v\n", iVal)
fmt.Println(ok)
// Output:
// string
// abc
// true
}
```

View File

@@ -26,6 +26,7 @@ import (
- [AddDay](#AddDay) - [AddDay](#AddDay)
- [AddHour](#AddHour) - [AddHour](#AddHour)
- [AddMinute](#AddMinute) - [AddMinute](#AddMinute)
- [AddYear](#AddYear)
- [BeginOfMinute](#BeginOfMinute) - [BeginOfMinute](#BeginOfMinute)
- [BeginOfHour](#BeginOfHour) - [BeginOfHour](#BeginOfHour)
- [BeginOfDay](#BeginOfDay) - [BeginOfDay](#BeginOfDay)
@@ -199,6 +200,45 @@ func main() {
} }
``` ```
### <span id="AddYear">AddYear</span>
<p>Add or sub year to the time.</p>
<b>Signature:</b>
```go
func AddYear(t time.Time, year int64) time.Time
```
<b>Example:</b>
```go
package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
now := time.Now()
after1Year := AddYear(now, 1)
diff1 := after1Year.Sub(now)
before1Year := AddYear(now, -1)
diff2 := before1Year.Sub(now)
fmt.Println(diff1)
fmt.Println(diff2)
// Output:
// 8760h0m0s
// -8760h0m0s
}
```
### <span id="BeginOfMinute">BeginOfMinute</span> ### <span id="BeginOfMinute">BeginOfMinute</span>
<p>Return beginning minute time of day.</p> <p>Return beginning minute time of day.</p>
@@ -1064,7 +1104,6 @@ func main() {
} }
``` ```
### <span id="IsLeapYear">IsLeapYear</span> ### <span id="IsLeapYear">IsLeapYear</span>
<p>check if param `year` is leap year or not.</p> <p>check if param `year` is leap year or not.</p>
@@ -1096,4 +1135,4 @@ func main() {
// true // true
// false // false
} }
``` ```

View File

@@ -25,6 +25,7 @@ import (
- [AddDay](#AddDay) - [AddDay](#AddDay)
- [AddHour](#AddHour) - [AddHour](#AddHour)
- [AddMinute](#AddMinute) - [AddMinute](#AddMinute)
- [AddYear](#AddYear)
- [BeginOfMinute](#BeginOfMinute) - [BeginOfMinute](#BeginOfMinute)
- [BeginOfHour](#BeginOfHour) - [BeginOfHour](#BeginOfHour)
- [BeginOfDay](#BeginOfDay) - [BeginOfDay](#BeginOfDay)
@@ -198,6 +199,45 @@ func main() {
} }
``` ```
### <span id="AddYear">AddYear</span>
<p>将日期加/减年数。</p>
<b>函数签名:</b>
```go
func AddYear(t time.Time, year int64) time.Time
```
<b>示例:</b>
```go
package main
import (
"fmt"
"time"
"github.com/duke-git/lancet/v2/datetime"
)
func main() {
now := time.Now()
after1Year := AddYear(now, 1)
diff1 := after1Year.Sub(now)
before1Year := AddYear(now, -1)
diff2 := before1Year.Sub(now)
fmt.Println(diff1)
fmt.Println(diff2)
// Output:
// 8760h0m0s
// -8760h0m0s
}
```
### <span id="BeginOfMinute">BeginOfMinute</span> ### <span id="BeginOfMinute">BeginOfMinute</span>
<p>返回指定时间的分钟开始时间。</p> <p>返回指定时间的分钟开始时间。</p>
@@ -1095,4 +1135,4 @@ func main() {
// true // true
// false // false
} }
``` ```

View File

@@ -365,15 +365,18 @@ import (
) )
func main() { func main() {
result1 := mathutil.Percent(1, 2, 2) result1 := Percent(1, 2, 2)
result2 := mathutil.Percent(0.1, 0.3, 2) result2 := Percent(0.1, 0.3, 2)
result3 := Percent(-30305, 408420, 2)
fmt.Println(result1) fmt.Println(result1)
fmt.Println(result2) fmt.Println(result2)
fmt.Println(result3)
// Output: // Output:
// 0.5 // 50
// 0.33 // 33.33
// -7.42
} }
``` ```

View File

@@ -365,15 +365,18 @@ import (
) )
func main() { func main() {
result1 := mathutil.Percent(1, 2, 2) result1 := Percent(1, 2, 2)
result2 := mathutil.Percent(0.1, 0.3, 2) result2 := Percent(0.1, 0.3, 2)
result3 := Percent(-30305, 408420, 2)
fmt.Println(result1) fmt.Println(result1)
fmt.Println(result2) fmt.Println(result2)
fmt.Println(result3)
// Output: // Output:
// 0.5 // 50
// 0.33 // 33.33
// -7.42
} }
``` ```

View File

@@ -40,6 +40,7 @@ import (
- [ForEach](#ForEach) - [ForEach](#ForEach)
- [Reduce](#Reduce) - [Reduce](#Reduce)
- [FindFirst](#FindFirst) - [FindFirst](#FindFirst)
- [FindLast](#FindLast)
- [Max](#Max) - [Max](#Max)
- [Min](#Min) - [Min](#Min)
- [AllMatch](#AllMatch) - [AllMatch](#AllMatch)
@@ -667,6 +668,38 @@ func main() {
} }
``` ```
### <span id="FindLast">FindLast</span>
<p>Returns the last 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]) FindLast() (T, bool)
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := FromSlice([]int{3, 2, 1})
result, ok := original.FindLast()
fmt.Println(result)
fmt.Println(ok)
// Output:
// 1
// true
}
```
### <span id="Max">Max</span> ### <span id="Max">Max</span>
<p>Returns the maximum element of this stream according to the provided less function. less fuction: a > b</p> <p>Returns the maximum element of this stream according to the provided less function. less fuction: a > b</p>

View File

@@ -40,6 +40,7 @@ import (
- [ForEach](#ForEach) - [ForEach](#ForEach)
- [Reduce](#Reduce) - [Reduce](#Reduce)
- [FindFirst](#FindFirst) - [FindFirst](#FindFirst)
- [FindLast](#FindLast)
- [Max](#Max) - [Max](#Max)
- [Min](#Min) - [Min](#Min)
- [AllMatch](#AllMatch) - [AllMatch](#AllMatch)
@@ -667,6 +668,38 @@ func main() {
} }
``` ```
### <span id="FindLast">FindLast</span>
<p>返回此stream最后一个元素和true如果stream为空则返回零值和false。</p>
<b>函数签名:</b>
```go
func (s stream[T]) FindLast() (T, bool)
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/stream"
)
func main() {
original := FromSlice([]int{3, 2, 1})
result, ok := original.FindLast()
fmt.Println(result)
fmt.Println(ok)
// Output:
// 1
// true
}
```
### <span id="Max">Max</span> ### <span id="Max">Max</span>
<p>根据提供的less函数返回stream的最大元素。less 函数: a > b</p> <p>根据提供的less函数返回stream的最大元素。less 函数: a > b</p>

View File

@@ -52,6 +52,9 @@ import (
- [HasPrefixAny](#HasPrefixAny) - [HasPrefixAny](#HasPrefixAny)
- [HasSuffixAny](#HasSuffixAny) - [HasSuffixAny](#HasSuffixAny)
- [IndexOffset](#IndexOffset) - [IndexOffset](#IndexOffset)
- [ReplaceWithMap](#ReplaceWithMap)
- [Trim](#Trim)
- [SplitAndTrim](#SplitAndTrim)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -1076,7 +1079,7 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func HasPrefixAny(str string, prefixes []string) bool func ReplaceWithMap(str string, replaces map[string]string) string
``` ```
<b>Example:</b> <b>Example:</b>
@@ -1163,7 +1166,7 @@ func main() {
fmt.Println(result3) fmt.Println(result3)
fmt.Println(result4) fmt.Println(result4)
fmt.Println(result5) fmt.Println(result5)
// Output: // Output:
// 12 // 12
// 1 // 1
@@ -1172,3 +1175,107 @@ func main() {
// -1 // -1
} }
``` ```
### <span id="ReplaceWithMap">ReplaceWithMap</span>
<p>Returns a copy of `str`, which is replaced by a map in unordered way, case-sensitively.</p>
<b>Signature:</b>
```go
func ReplaceWithMap(str string, replaces map[string]string) string
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
str := "ac ab ab ac"
replaces := map[string]string{
"a": "1",
"b": "2",
}
result := strutil.ReplaceWithMap(str, replaces)
fmt.Println(result)
// Output:
// 1c 12 12 1c
}
```
### <span id="Trim">Trim</span>
<p>Strips whitespace (or other characters) from the beginning and end of a string. The optional parameter `characterMask` specifies the additional stripped characters.</p>
<b>Signature:</b>
```go
func Trim(str string, characterMask ...string) string
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
result1 := strutil.Trim("\nabcd")
str := "$ ab cd $ "
result2 := strutil.Trim(str)
result3 := strutil.Trim(str, "$")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// abcd
// $ ab cd $
// ab cd
}
```
### <span id="SplitAndTrim">SplitAndTrim</span>
<p>Splits string `str` by a string `delimiter` to a slice, and calls Trim to every element of slice. It ignores the elements which are empty after Trim.</p>
<b>Signature:</b>
```go
func SplitAndTrim(str, delimiter string, characterMask ...string) []string
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
str := " a,b, c,d,$1 "
result1 := strutil.SplitAndTrim(str, ",")
result2 := strutil.SplitAndTrim(str, ",", "$")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// [a b c d $1]
// [a b c d 1]
}
```

View File

@@ -52,6 +52,9 @@ import (
- [HasPrefixAny](#HasPrefixAny) - [HasPrefixAny](#HasPrefixAny)
- [HasSuffixAny](#HasSuffixAny) - [HasSuffixAny](#HasSuffixAny)
- [IndexOffset](#IndexOffset) - [IndexOffset](#IndexOffset)
- [ReplaceWithMap](#ReplaceWithMap)
- [Trim](#Trim)
- [SplitAndTrim](#SplitAndTrim)
<div STYLE="page-break-after: always;"></div> <div STYLE="page-break-after: always;"></div>
@@ -1171,3 +1174,108 @@ func main() {
// -1 // -1
} }
``` ```
### <span id="ReplaceWithMap">ReplaceWithMap</span>
<p>返回`str`的副本以无序的方式被map替换区分大小写。</p>
<b>函数签名:</b>
```go
func ReplaceWithMap(str string, replaces map[string]string) string
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
str := "ac ab ab ac"
replaces := map[string]string{
"a": "1",
"b": "2",
}
result := strutil.ReplaceWithMap(str, replaces)
fmt.Println(result)
// Output:
// 1c 12 12 1c
}
```
### <span id="Trim">Trim</span>
<p>从字符串的开头和结尾去除空格(或其他字符)。 可选参数 characterMask 指定额外的剥离字符。</p>
<b>函数签名:</b>
```go
func Trim(str string, characterMask ...string) string
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
result1 := strutil.Trim("\nabcd")
str := "$ ab cd $ "
result2 := strutil.Trim(str)
result3 := strutil.Trim(str, "$")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// abcd
// $ ab cd $
// ab cd
}
```
### <span id="SplitAndTrim">SplitAndTrim</span>
<p>将字符串str按字符串delimiter拆分为一个切片并对该数组的每个元素调用Trim。忽略Trim后为空的元素。</p>
<b>函数签名:</b>
```go
func SplitAndTrim(str, delimiter string, characterMask ...string) []string
```
<b>示例:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
str := " a,b, c,d,$1 "
result1 := strutil.SplitAndTrim(str, ",")
result2 := strutil.SplitAndTrim(str, ",", "$")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// [a b c d $1]
// [a b c d 1]
}
```

View File

@@ -60,7 +60,7 @@ func Percent(val, total float64, n int) float64 {
if total == 0 { if total == 0 {
return float64(0) return float64(0)
} }
tmp := val / total tmp := val / total * 100
result := RoundToFloat(tmp, n) result := RoundToFloat(tmp, n)
return result return result

View File

@@ -53,13 +53,16 @@ func ExampleFactorial() {
func ExamplePercent() { func ExamplePercent() {
result1 := Percent(1, 2, 2) result1 := Percent(1, 2, 2)
result2 := Percent(0.1, 0.3, 2) result2 := Percent(0.1, 0.3, 2)
result3 := Percent(-30305, 408420, 2)
fmt.Println(result1) fmt.Println(result1)
fmt.Println(result2) fmt.Println(result2)
fmt.Println(result3)
// Output: // Output:
// 0.5 // 50
// 0.33 // 33.33
// -7.42
} }
func ExampleRoundToFloat() { func ExampleRoundToFloat() {

View File

@@ -36,8 +36,9 @@ func TestFactorial(t *testing.T) {
func TestPercent(t *testing.T) { func TestPercent(t *testing.T) {
assert := internal.NewAssert(t, "TestPercent") assert := internal.NewAssert(t, "TestPercent")
assert.Equal(0.5, Percent(1, 2, 2)) assert.EqualValues(50, Percent(1, 2, 2))
assert.Equal(0.33, Percent(0.1, 0.3, 2)) assert.EqualValues(33.33, Percent(0.1, 0.3, 2))
assert.EqualValues(-7.42, Percent(-30305, 408420, 2))
} }
func TestRoundToFloat(t *testing.T) { func TestRoundToFloat(t *testing.T) {

View File

@@ -295,6 +295,18 @@ func (s stream[T]) FindFirst() (T, bool) {
return s.source[0], true return s.source[0], true
} }
// FindLast returns the last 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]) FindLast() (T, bool) {
var result T
if s.source == nil || len(s.source) == 0 {
return result, false
}
return s.source[len(s.source)-1], true
}
// 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 // Play: https://go.dev/play/p/A8_zkJnLHm4
func (s stream[T]) Reverse() stream[T] { func (s stream[T]) Reverse() stream[T] {

View File

@@ -290,6 +290,19 @@ func ExampleStream_FindFirst() {
// true // true
} }
func ExampleStream_FindLast() {
original := FromSlice([]int{3, 2, 1})
result, ok := original.FindLast()
fmt.Println(result)
fmt.Println(ok)
// Output:
// 1
// true
}
func ExampleStream_Reverse() { func ExampleStream_Reverse() {
original := FromSlice([]int{1, 2, 3}) original := FromSlice([]int{1, 2, 3})

View File

@@ -273,6 +273,24 @@ func TestStream_FindFirst(t *testing.T) {
assert.Equal(true, ok) assert.Equal(true, ok)
} }
func TestStream_FindLast(t *testing.T) {
assert := internal.NewAssert(t, "TestStream_FindLast")
stream := FromSlice([]int{3, 2, 1})
result, ok := stream.FindLast()
assert.Equal(1, result)
assert.Equal(true, ok)
stream2 := FromSlice([]int{})
result, ok = stream2.FindLast()
assert.Equal(0, result)
assert.Equal(false, ok)
}
func TestStream_Reverse(t *testing.T) { func TestStream_Reverse(t *testing.T) {
assert := internal.NewAssert(t, "TestStream_Reverse") assert := internal.NewAssert(t, "TestStream_Reverse")

View File

@@ -407,7 +407,7 @@ func IsBlank(str string) bool {
return true return true
} }
// HasPrefixAny check if a string starts with any of an array of specified strings. // HasPrefixAny check if a string starts with any of a slice of specified strings.
// Play: https://go.dev/play/p/8UUTl2C5slo // Play: https://go.dev/play/p/8UUTl2C5slo
func HasPrefixAny(str string, prefixes []string) bool { func HasPrefixAny(str string, prefixes []string) bool {
if len(str) == 0 || len(prefixes) == 0 { if len(str) == 0 || len(prefixes) == 0 {
@@ -421,7 +421,7 @@ func HasPrefixAny(str string, prefixes []string) bool {
return false return false
} }
// HasSuffixAny check if a string ends with any of an array of specified strings. // HasSuffixAny check if a string ends with any of a slice of specified strings.
// Play: https://go.dev/play/p/sKWpCQdOVkx // Play: https://go.dev/play/p/sKWpCQdOVkx
func HasSuffixAny(str string, suffixes []string) bool { func HasSuffixAny(str string, suffixes []string) bool {
if len(str) == 0 || len(suffixes) == 0 { if len(str) == 0 || len(suffixes) == 0 {
@@ -445,3 +445,57 @@ func IndexOffset(str string, substr string, idxFrom int) int {
return strings.Index(str[idxFrom:], substr) + idxFrom return strings.Index(str[idxFrom:], substr) + idxFrom
} }
// ReplaceWithMap returns a copy of `str`,
// which is replaced by a map in unordered way, case-sensitively.
// Play: todo
func ReplaceWithMap(str string, replaces map[string]string) string {
for k, v := range replaces {
str = strings.ReplaceAll(str, k, v)
}
return str
}
// SplitAndTrim splits string `str` by a string `delimiter` to a slice,
// and calls Trim to every element of this slice. It ignores the elements
// which are empty after Trim.
func SplitAndTrim(str, delimiter string, characterMask ...string) []string {
result := make([]string, 0)
for _, v := range strings.Split(str, delimiter) {
v = Trim(v, characterMask...)
if v != "" {
result = append(result, v)
}
}
return result
}
var (
// DefaultTrimChars are the characters which are stripped by Trim* functions in default.
DefaultTrimChars = string([]byte{
'\t', // Tab.
'\v', // Vertical tab.
'\n', // New line (line feed).
'\r', // Carriage return.
'\f', // New page.
' ', // Ordinary space.
0x00, // NUL-byte.
0x85, // Delete.
0xA0, // Non-breaking space.
})
)
// Trim strips whitespace (or other characters) from the beginning and end of a string.
// The optional parameter `characterMask` specifies the additional stripped characters.
func Trim(str string, characterMask ...string) string {
trimChars := DefaultTrimChars
if len(characterMask) > 0 {
trimChars += characterMask[0]
}
return strings.Trim(str, trimChars)
}

View File

@@ -525,3 +525,49 @@ func ExampleIndexOffset() {
// -1 // -1
// -1 // -1
} }
func ExampleReplaceWithMap() {
str := "ac ab ab ac"
replaces := map[string]string{
"a": "1",
"b": "2",
}
result := ReplaceWithMap(str, replaces)
fmt.Println(result)
// Output:
// 1c 12 12 1c
}
func ExampleTrim() {
result1 := Trim("\nabcd")
str := "$ ab cd $ "
result2 := Trim(str)
result3 := Trim(str, "$")
fmt.Println(result1)
fmt.Println(result2)
fmt.Println(result3)
// Output:
// abcd
// $ ab cd $
// ab cd
}
func ExampleSplitAndTrim() {
str := " a,b, c,d,$1 "
result1 := SplitAndTrim(str, ",")
result2 := SplitAndTrim(str, ",", "$")
fmt.Println(result1)
fmt.Println(result2)
// Output:
// [a b c d $1]
// [a b c d 1]
}

View File

@@ -397,3 +397,38 @@ func TestIndexOffset(t *testing.T) {
assert.Equal(IndexOffset(str, "d", len(str)), -1) assert.Equal(IndexOffset(str, "d", len(str)), -1)
assert.Equal(IndexOffset(str, "f", -1), -1) assert.Equal(IndexOffset(str, "f", -1), -1)
} }
func TestReplaceWithMap(t *testing.T) {
assert := internal.NewAssert(t, "TestReplaceWithMap")
str := "ac ab ab ac"
replaces := map[string]string{
"a": "1",
"b": "2",
}
assert.Equal(str, "ac ab ab ac")
assert.Equal(ReplaceWithMap(str, replaces), "1c 12 12 1c")
}
func TestTrim(t *testing.T) {
assert := internal.NewAssert(t, "TestTrim")
str1 := "$ ab cd $ "
assert.Equal("$ ab cd $", Trim(str1))
assert.Equal("ab cd", Trim(str1, "$"))
assert.Equal("abcd", Trim("\nabcd"))
}
func TestSplitAndTrim(t *testing.T) {
assert := internal.NewAssert(t, "TestTrim")
str := " a,b, c,d,$1 "
result1 := SplitAndTrim(str, ",")
result2 := SplitAndTrim(str, ",", "$")
assert.Equal([]string{"a", "b", "c", "d", "$1"}, result1)
assert.Equal([]string{"a", "b", "c", "d", "1"}, result2)
}