mirror of
https://github.com/duke-git/lancet.git
synced 2026-03-01 00:35:28 +08:00
Compare commits
9 Commits
cb7ff904d9
...
v1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
69b34faeec | ||
|
|
9af645606b | ||
|
|
f58b706285 | ||
|
|
0f9683a764 | ||
|
|
4595a94b4c | ||
|
|
e1e15883e9 | ||
|
|
b4e7977feb | ||
|
|
1d3585b22f | ||
|
|
2145808268 |
@@ -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)
|
[](https://pkg.go.dev/github.com/duke-git/lancet)
|
||||||
[](https://goreportcard.com/report/github.com/duke-git/lancet)
|
[](https://goreportcard.com/report/github.com/duke-git/lancet)
|
||||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||||
@@ -108,6 +108,7 @@ import "github.com/duke-git/lancet/convertor"
|
|||||||
- [ToUrlBase64](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#ToUrlBase64)
|
- [ToUrlBase64](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#ToUrlBase64)
|
||||||
- [ToRawStdBase64](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#ToRawStdBase64)
|
- [ToRawStdBase64](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#ToRawStdBase64)
|
||||||
- [ToRawUrlBase64](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#ToRawUrlBase64)
|
- [ToRawUrlBase64](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#ToRawUrlBase64)
|
||||||
|
- [ToBigInt](https://github.com/duke-git/lancet/blob/v1/docs/convertor.md#ToBigInt)
|
||||||
|
|
||||||
### 3. Cryptor package is for data encryption and decryption.
|
### 3. Cryptor package is for data encryption and decryption.
|
||||||
|
|
||||||
@@ -210,6 +211,9 @@ import "github.com/duke-git/lancet/datetime"
|
|||||||
- [TimestampMilli](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#TimestampMilli)
|
- [TimestampMilli](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#TimestampMilli)
|
||||||
- [TimestampMicro](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#TimestampMicro)
|
- [TimestampMicro](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#TimestampMicro)
|
||||||
- [TimestampNano](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#TimestampNano)
|
- [TimestampNano](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#TimestampNano)
|
||||||
|
- [TrackFuncTime](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#TrackFuncTime)
|
||||||
|
- [DaysBetween](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#DaysBetween)
|
||||||
|
- [GenerateDatetimesBetween](https://github.com/duke-git/lancet/blob/v1/docs/datetime.md#GenerateDatetimesBetween)
|
||||||
|
|
||||||
### 5. Fileutil package implements some basic functions for file operations.
|
### 5. Fileutil package implements some basic functions for file operations.
|
||||||
|
|
||||||
@@ -478,6 +482,9 @@ import "github.com/duke-git/lancet/strutil"
|
|||||||
- [Ellipsis](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#Ellipsis)
|
- [Ellipsis](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#Ellipsis)
|
||||||
- [Shuffle](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#Shuffle)
|
- [Shuffle](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#Shuffle)
|
||||||
- [Rotate](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#Rotate)
|
- [Rotate](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#Rotate)
|
||||||
|
- [TemplateReplace](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#TemplateReplace)
|
||||||
|
- [RegexMatchAllGroups](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#RegexMatchAllGroups)
|
||||||
|
- [Cut](https://github.com/duke-git/lancet/blob/v1/docs/strutil.md#Cut)
|
||||||
|
|
||||||
|
|
||||||
### 14. System package contain some functions about os, runtime, shell command.
|
### 14. System package contain some functions about os, runtime, shell command.
|
||||||
|
|||||||
@@ -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)
|
[](https://pkg.go.dev/github.com/duke-git/lancet)
|
||||||
[](https://goreportcard.com/report/github.com/duke-git/lancet)
|
[](https://goreportcard.com/report/github.com/duke-git/lancet)
|
||||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||||
@@ -107,6 +107,7 @@ import "github.com/duke-git/lancet/convertor"
|
|||||||
- [ToUrlBase64](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#ToUrlBase64)
|
- [ToUrlBase64](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#ToUrlBase64)
|
||||||
- [ToRawStdBase64](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#ToRawStdBase64)
|
- [ToRawStdBase64](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#ToRawStdBase64)
|
||||||
- [ToRawUrlBase64](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#ToRawUrlBase64)
|
- [ToRawUrlBase64](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#ToRawUrlBase64)
|
||||||
|
- [ToBigInt](https://github.com/duke-git/lancet/blob/v1/docs/convertor_zh-CN.md#ToBigInt)
|
||||||
|
|
||||||
|
|
||||||
### 3. cryptor 加密包支持数据加密和解密,获取 md5,hash 值。支持 base64, md5, hmac, aes, des, rsa。
|
### 3. cryptor 加密包支持数据加密和解密,获取 md5,hash 值。支持 base64, md5, hmac, aes, des, rsa。
|
||||||
@@ -213,6 +214,9 @@ import "github.com/duke-git/lancet/datetime"
|
|||||||
- [TimestampMilli](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#TimestampMilli)
|
- [TimestampMilli](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#TimestampMilli)
|
||||||
- [TimestampMicro](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#TimestampMicro)
|
- [TimestampMicro](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#TimestampMicro)
|
||||||
- [TimestampNano](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#TimestampNano)
|
- [TimestampNano](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#TimestampNano)
|
||||||
|
- [TrackFuncTime](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#TrackFuncTime)
|
||||||
|
- [DaysBetween](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#DaysBetween)
|
||||||
|
- [GenerateDatetimesBetween](https://github.com/duke-git/lancet/blob/v1/docs/datetime_zh-CN.md#GenerateDatetimesBetween)
|
||||||
|
|
||||||
### 5. fileutil 包支持文件基本操作。
|
### 5. fileutil 包支持文件基本操作。
|
||||||
|
|
||||||
@@ -480,6 +484,9 @@ import "github.com/duke-git/lancet/strutil"
|
|||||||
- [Ellipsis](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#Ellipsis)
|
- [Ellipsis](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#Ellipsis)
|
||||||
- [Shuffle](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#Shuffle)
|
- [Shuffle](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#Shuffle)
|
||||||
- [Rotate](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#Rotate)
|
- [Rotate](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#Rotate)
|
||||||
|
- [TemplateReplace](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#TemplateReplace)
|
||||||
|
- [RegexMatchAllGroups](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#RegexMatchAllGroups)
|
||||||
|
- [Cut](https://github.com/duke-git/lancet/blob/v1/docs/strutil_zh-CN.md#Cut)
|
||||||
|
|
||||||
### 14. system 包含 os, runtime, shell command 相关函数。
|
### 14. system 包含 os, runtime, shell command 相关函数。
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package compare
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"math/big"
|
||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -36,7 +37,8 @@ func compareRefValue(operator string, leftObj, rightObj interface{}, kind reflec
|
|||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
|
|
||||||
// compare time
|
// compare time
|
||||||
if leftVal.CanConvert(timeType) {
|
// fix: issue #275
|
||||||
|
if canConvert(leftObj, timeType) {
|
||||||
timeObj1, ok := leftObj.(time.Time)
|
timeObj1, ok := leftObj.(time.Time)
|
||||||
if !ok {
|
if !ok {
|
||||||
timeObj1 = leftVal.Convert(timeType).Interface().(time.Time)
|
timeObj1 = leftVal.Convert(timeType).Interface().(time.Time)
|
||||||
@@ -58,7 +60,7 @@ func compareRefValue(operator string, leftObj, rightObj interface{}, kind reflec
|
|||||||
|
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
// compare []byte
|
// compare []byte
|
||||||
if leftVal.CanConvert(bytesType) {
|
if canConvert(leftObj, bytesType) {
|
||||||
bytesObj1, ok := leftObj.([]byte)
|
bytesObj1, ok := leftObj.([]byte)
|
||||||
if !ok {
|
if !ok {
|
||||||
bytesObj1 = leftVal.Convert(bytesType).Interface().([]byte)
|
bytesObj1 = leftVal.Convert(bytesType).Interface().([]byte)
|
||||||
@@ -155,169 +157,141 @@ func compareBasicValue(operator string, leftValue, rightValue interface{}) bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch leftVal := leftValue.(type) {
|
switch leftVal := leftValue.(type) {
|
||||||
case json.Number:
|
case int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64:
|
||||||
if left, err := leftVal.Float64(); err == nil {
|
left, err := convertor.ToBigInt(leftValue)
|
||||||
switch rightVal := rightValue.(type) {
|
if err != nil {
|
||||||
case json.Number:
|
return false
|
||||||
if right, err := rightVal.Float64(); err == nil {
|
|
||||||
switch operator {
|
|
||||||
case equal:
|
|
||||||
if left == right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
case lessThan:
|
|
||||||
if left < right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
case greaterThan:
|
|
||||||
if left > right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
case lessOrEqual:
|
|
||||||
if left <= right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
case greaterOrEqual:
|
|
||||||
if left >= right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
case float32, float64, int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64:
|
|
||||||
right, err := convertor.ToFloat(rightValue)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
switch operator {
|
|
||||||
case equal:
|
|
||||||
if left == right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
case lessThan:
|
|
||||||
if left < right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
case greaterThan:
|
|
||||||
if left > right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
case lessOrEqual:
|
|
||||||
if left <= right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
case greaterOrEqual:
|
|
||||||
if left >= right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case float32, float64, int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64:
|
right, err := convertor.ToBigInt(rightValue)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return compareBigInt(operator, left, right)
|
||||||
|
|
||||||
|
case float32, float64:
|
||||||
left, err := convertor.ToFloat(leftValue)
|
left, err := convertor.ToFloat(leftValue)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
switch rightVal := rightValue.(type) {
|
right, err := convertor.ToFloat(rightValue)
|
||||||
case json.Number:
|
if err != nil {
|
||||||
if right, err := rightVal.Float64(); err == nil {
|
return false
|
||||||
switch operator {
|
|
||||||
case equal:
|
|
||||||
if left == right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
case lessThan:
|
|
||||||
if left < right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
case greaterThan:
|
|
||||||
if left > right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
case lessOrEqual:
|
|
||||||
if left <= right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
case greaterOrEqual:
|
|
||||||
if left >= right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case float32, float64, int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64:
|
|
||||||
right, err := convertor.ToFloat(rightValue)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
switch operator {
|
|
||||||
case equal:
|
|
||||||
if left == right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
case lessThan:
|
|
||||||
if left < right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
case greaterThan:
|
|
||||||
if left > right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
case lessOrEqual:
|
|
||||||
if left <= right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
case greaterOrEqual:
|
|
||||||
if left >= right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return compareFloats(operator, left, right)
|
||||||
|
|
||||||
case string:
|
case string:
|
||||||
left := leftVal
|
left := leftVal
|
||||||
switch right := rightValue.(type) {
|
switch right := rightValue.(type) {
|
||||||
case string:
|
case string:
|
||||||
switch operator {
|
return compareStrings(operator, left, right)
|
||||||
case equal:
|
|
||||||
if left == right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
case lessThan:
|
|
||||||
if left < right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
case greaterThan:
|
|
||||||
if left > right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
case lessOrEqual:
|
|
||||||
if left <= right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
case greaterOrEqual:
|
|
||||||
if left >= right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case bool:
|
case bool:
|
||||||
left := leftVal
|
left := leftVal
|
||||||
switch right := rightValue.(type) {
|
switch right := rightValue.(type) {
|
||||||
case bool:
|
case bool:
|
||||||
switch operator {
|
return compareBools(operator, left, right)
|
||||||
case equal:
|
|
||||||
if left == right {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case json.Number:
|
||||||
|
if left, err := leftVal.Float64(); err == nil {
|
||||||
|
switch rightVal := rightValue.(type) {
|
||||||
|
case json.Number:
|
||||||
|
if right, err := rightVal.Float64(); err == nil {
|
||||||
|
return compareFloats(operator, left, right)
|
||||||
|
}
|
||||||
|
case float32, float64:
|
||||||
|
right, err := convertor.ToFloat(rightValue)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return compareFloats(operator, left, right)
|
||||||
|
|
||||||
|
case int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64:
|
||||||
|
right, err := convertor.ToBigInt(rightValue)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
left, err := convertor.ToBigInt(left)
|
||||||
|
return compareBigInt(operator, left, right)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// compareBigInt compares two big.Int values based on the operator
|
||||||
|
func compareBigInt(operator string, left, right *big.Int) bool {
|
||||||
|
switch operator {
|
||||||
|
case equal:
|
||||||
|
return left.Cmp(right) == 0
|
||||||
|
case lessThan:
|
||||||
|
return left.Cmp(right) < 0
|
||||||
|
case greaterThan:
|
||||||
|
return left.Cmp(right) > 0
|
||||||
|
case lessOrEqual:
|
||||||
|
return left.Cmp(right) <= 0
|
||||||
|
case greaterOrEqual:
|
||||||
|
return left.Cmp(right) >= 0
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// compareFloats compares two float64 values based on the operator
|
||||||
|
func compareFloats(operator string, left, right float64) bool {
|
||||||
|
switch operator {
|
||||||
|
case equal:
|
||||||
|
return left == right
|
||||||
|
case lessThan:
|
||||||
|
return left < right
|
||||||
|
case greaterThan:
|
||||||
|
return left > right
|
||||||
|
case lessOrEqual:
|
||||||
|
return left <= right
|
||||||
|
case greaterOrEqual:
|
||||||
|
return left >= right
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// compareStrings compares two string values based on the operator
|
||||||
|
func compareStrings(operator string, left, right string) bool {
|
||||||
|
switch operator {
|
||||||
|
case equal:
|
||||||
|
return left == right
|
||||||
|
case lessThan:
|
||||||
|
return left < right
|
||||||
|
case greaterThan:
|
||||||
|
return left > right
|
||||||
|
case lessOrEqual:
|
||||||
|
return left <= right
|
||||||
|
case greaterOrEqual:
|
||||||
|
return left >= right
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// compareBools compares two boolean values based on the operator
|
||||||
|
func compareBools(operator string, left, right bool) bool {
|
||||||
|
switch operator {
|
||||||
|
case equal:
|
||||||
|
return left == right
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// canConvert checks if the value can be converted to the target type
|
||||||
|
func canConvert(value interface{}, targetType reflect.Type) bool {
|
||||||
|
v := reflect.ValueOf(value)
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
v.Convert(targetType)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package compare
|
package compare
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -70,18 +71,28 @@ func TestEqualValue(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestLessThan(t *testing.T) {
|
func TestLessThan(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
assert := internal.NewAssert(t, "TestLessThan")
|
assert := internal.NewAssert(t, "TestLessThan")
|
||||||
|
|
||||||
assert.Equal(true, LessThan(1, 2))
|
tests := []struct {
|
||||||
assert.Equal(true, LessThan(1.1, 2.2))
|
left interface{}
|
||||||
assert.Equal(true, LessThan("a", "b"))
|
right interface{}
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
{1, 2, true},
|
||||||
|
{1.1, 2.2, true},
|
||||||
|
{"a", "b", true},
|
||||||
|
{time.Now(), time.Now().Add(time.Second), true},
|
||||||
|
{[]byte("hello1"), []byte("hello2"), true},
|
||||||
|
{json.Number("123"), json.Number("124"), true},
|
||||||
|
{645680099112988673, 645680099112988675, true},
|
||||||
|
{1, 1, false},
|
||||||
|
{1, int64(1), false},
|
||||||
|
}
|
||||||
|
|
||||||
time1 := time.Now()
|
for _, tt := range tests {
|
||||||
time2 := time1.Add(time.Second)
|
assert.Equal(tt.want, LessThan(tt.left, tt.right))
|
||||||
assert.Equal(true, LessThan(time1, time2))
|
}
|
||||||
|
|
||||||
assert.Equal(false, LessThan(1, 1))
|
|
||||||
assert.Equal(false, LessThan(1, int64(1)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGreaterThan(t *testing.T) {
|
func TestGreaterThan(t *testing.T) {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
|
"math/big"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -460,3 +461,36 @@ func ToRawUrlBase64(value interface{}) string {
|
|||||||
return base64.RawURLEncoding.EncodeToString(marshal)
|
return base64.RawURLEncoding.EncodeToString(marshal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToBigInt converts an integer of any supported type (int, int64, uint64, etc.) to *big.Int
|
||||||
|
// Play: todo
|
||||||
|
func ToBigInt(v interface{}) (*big.Int, error) {
|
||||||
|
result := new(big.Int)
|
||||||
|
|
||||||
|
switch v := (v).(type) {
|
||||||
|
case int:
|
||||||
|
result.SetInt64(int64(v))
|
||||||
|
case int8:
|
||||||
|
result.SetInt64(int64(v))
|
||||||
|
case int16:
|
||||||
|
result.SetInt64(int64(v))
|
||||||
|
case int32:
|
||||||
|
result.SetInt64(int64(v))
|
||||||
|
case int64:
|
||||||
|
result.SetInt64(v)
|
||||||
|
case uint:
|
||||||
|
result.SetUint64(uint64(v))
|
||||||
|
case uint8:
|
||||||
|
result.SetUint64(uint64(v))
|
||||||
|
case uint16:
|
||||||
|
result.SetUint64(uint64(v))
|
||||||
|
case uint32:
|
||||||
|
result.SetUint64(uint64(v))
|
||||||
|
case uint64:
|
||||||
|
result.SetUint64(v)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unsupported type: %T", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -240,7 +240,8 @@ func setStructField(structObj interface{}, fieldName string, fieldValue interfac
|
|||||||
|
|
||||||
if fieldVal.Type() != val.Type() {
|
if fieldVal.Type() != val.Type() {
|
||||||
|
|
||||||
if val.CanConvert(fieldVal.Type()) {
|
// fix: issue #275
|
||||||
|
if canConvert(fieldValue, fieldVal.Type()) {
|
||||||
fieldVal.Set(val.Convert(fieldVal.Type()))
|
fieldVal.Set(val.Convert(fieldVal.Type()))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -284,3 +285,14 @@ func getFieldNameByJsonTag(structObj interface{}, jsonTag string) string {
|
|||||||
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func canConvert(value interface{}, targetType reflect.Type) bool {
|
||||||
|
v := reflect.ValueOf(value)
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
v.Convert(targetType)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"math/big"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
@@ -684,3 +685,83 @@ func TestToRawUrlBase64(t *testing.T) {
|
|||||||
d15, _ := base64.RawURLEncoding.DecodeString(r15)
|
d15, _ := base64.RawURLEncoding.DecodeString(r15)
|
||||||
assert.Equal("4+3/4?=", string(d15))
|
assert.Equal("4+3/4?=", string(d15))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestToBigInt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
assert := internal.NewAssert(t, "TestToBigInt")
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
input interface{}
|
||||||
|
want *big.Int
|
||||||
|
hasErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "int",
|
||||||
|
input: 42,
|
||||||
|
want: big.NewInt(42),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "int8",
|
||||||
|
input: int8(127),
|
||||||
|
want: big.NewInt(127),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "int16",
|
||||||
|
input: int16(32000),
|
||||||
|
want: big.NewInt(32000),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "int32",
|
||||||
|
input: int32(123456),
|
||||||
|
want: big.NewInt(123456),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "int64",
|
||||||
|
input: int64(987654321),
|
||||||
|
want: big.NewInt(987654321),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "uint",
|
||||||
|
input: uint(987654321),
|
||||||
|
want: big.NewInt(987654321),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "uint8",
|
||||||
|
input: uint8(255),
|
||||||
|
want: big.NewInt(255),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "uint16",
|
||||||
|
input: uint16(65535),
|
||||||
|
want: big.NewInt(65535),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "uint32",
|
||||||
|
input: uint32(4294967295),
|
||||||
|
want: big.NewInt(4294967295),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "uint64",
|
||||||
|
input: uint64(18446744073709551615),
|
||||||
|
want: new(big.Int).SetUint64(18446744073709551615),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "unsupported type",
|
||||||
|
input: 3.14, // Unsupported type
|
||||||
|
hasErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := ToBigInt(tt.input)
|
||||||
|
if (err != nil) != tt.hasErr {
|
||||||
|
t.Errorf("ToBigInt() error = %v, hasErr %v", err, tt.hasErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(tt.want, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ package datetime
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -321,3 +322,61 @@ func TimestampNano(timezone ...string) int64 {
|
|||||||
|
|
||||||
return t.UnixNano()
|
return t.UnixNano()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TrackFuncTime track the time of function execution.
|
||||||
|
// call it at top of the func like `defer TrackFuncTime(time.Now())()`
|
||||||
|
func TrackFuncTime(pre time.Time) func() {
|
||||||
|
callerName := getCallerName()
|
||||||
|
return func() {
|
||||||
|
elapsed := time.Since(pre)
|
||||||
|
fmt.Printf("Function %s execution time:\t %v", callerName, elapsed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCallerName() string {
|
||||||
|
pc, _, _, ok := runtime.Caller(2)
|
||||||
|
if !ok {
|
||||||
|
return "Unknown"
|
||||||
|
}
|
||||||
|
fn := runtime.FuncForPC(pc)
|
||||||
|
if fn == nil {
|
||||||
|
return "Unknown"
|
||||||
|
}
|
||||||
|
|
||||||
|
fullName := fn.Name()
|
||||||
|
if lastDot := strings.LastIndex(fullName, "."); lastDot != -1 {
|
||||||
|
return fullName[lastDot+1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
return fullName
|
||||||
|
}
|
||||||
|
|
||||||
|
// DaysBetween returns the number of days between two times.
|
||||||
|
func DaysBetween(start, end time.Time) int {
|
||||||
|
duration := end.Sub(start)
|
||||||
|
days := int(duration.Hours() / 24)
|
||||||
|
|
||||||
|
return days
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateDatetimesBetween returns a slice of strings between two times.
|
||||||
|
// layout: the format of the datetime string
|
||||||
|
// interval: the interval between two datetimes
|
||||||
|
func GenerateDatetimesBetween(start, end time.Time, layout string, interval string) ([]string, error) {
|
||||||
|
var result []string
|
||||||
|
|
||||||
|
if start.After(end) {
|
||||||
|
start, end = end, start
|
||||||
|
}
|
||||||
|
|
||||||
|
duration, err := time.ParseDuration(interval)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for current := start; !current.After(end); current = current.Add(duration) {
|
||||||
|
result = append(result, current.Format(layout))
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -333,3 +333,114 @@ func TestTimestamp(t *testing.T) {
|
|||||||
ts4 := TimestampNano()
|
ts4 := TimestampNano()
|
||||||
t.Log(ts4)
|
t.Log(ts4)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTrackFuncTime(t *testing.T) {
|
||||||
|
defer TrackFuncTime(time.Now())()
|
||||||
|
|
||||||
|
var n int
|
||||||
|
for i := 0; i < 5000000; i++ {
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDaysBetween(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
assert := internal.NewAssert(t, "TestDaysBetween")
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
start time.Time
|
||||||
|
end time.Time
|
||||||
|
expected int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
start: time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC),
|
||||||
|
end: time.Date(2024, time.September, 10, 0, 0, 0, 0, time.UTC),
|
||||||
|
expected: 9,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
start: time.Date(2024, time.September, 10, 0, 0, 0, 0, time.UTC),
|
||||||
|
end: time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC),
|
||||||
|
expected: -9,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
start: time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC),
|
||||||
|
end: time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC),
|
||||||
|
expected: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
start: time.Date(2024, time.January, 1, 0, 0, 0, 0, time.UTC),
|
||||||
|
end: time.Date(2024, time.December, 31, 0, 0, 0, 0, time.UTC),
|
||||||
|
expected: 365,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
start: time.Date(2024, time.March, 1, 0, 0, 0, 0, time.UTC),
|
||||||
|
end: time.Date(2024, time.March, 31, 0, 0, 0, 0, time.UTC),
|
||||||
|
expected: 30,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
result := DaysBetween(tt.start, tt.end)
|
||||||
|
assert.Equal(tt.expected, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGenerateDatetimesBetween(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
assert := internal.NewAssert(t, "TestGenerateDatetimesBetween")
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
start time.Time
|
||||||
|
end time.Time
|
||||||
|
layout string
|
||||||
|
interval string
|
||||||
|
expected []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
start: time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC),
|
||||||
|
end: time.Date(2024, time.September, 1, 2, 0, 0, 0, time.UTC),
|
||||||
|
layout: "2006-01-02 15:04:05",
|
||||||
|
interval: "30m",
|
||||||
|
expected: []string{
|
||||||
|
"2024-09-01 00:00:00",
|
||||||
|
"2024-09-01 00:30:00",
|
||||||
|
"2024-09-01 01:00:00",
|
||||||
|
"2024-09-01 01:30:00",
|
||||||
|
"2024-09-01 02:00:00",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
start: time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC),
|
||||||
|
end: time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC),
|
||||||
|
layout: "2006-01-02 15:04:05",
|
||||||
|
interval: "1h",
|
||||||
|
expected: []string{"2024-09-01 00:00:00"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
start: time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC),
|
||||||
|
end: time.Date(2024, time.September, 1, 3, 0, 0, 0, time.UTC),
|
||||||
|
layout: "2006-01-02 15:04:05",
|
||||||
|
interval: "2h",
|
||||||
|
expected: []string{
|
||||||
|
"2024-09-01 00:00:00",
|
||||||
|
"2024-09-01 02:00:00",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
result, err := GenerateDatetimesBetween(tt.start, tt.end, tt.layout, tt.interval)
|
||||||
|
|
||||||
|
assert.Equal(tt.expected, result)
|
||||||
|
assert.IsNil(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("Invalid interval", func(t *testing.T) {
|
||||||
|
_, err := GenerateDatetimesBetween(time.Now(), time.Now(), "2006-01-02 15:04:05", "invalid")
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("Expected error, got nil")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ import (
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func Equal(left, right any) bool
|
func Equal(left, right interface{}) bool
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
@@ -91,7 +91,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func EqualValue(left, right any) bool
|
func EqualValue(left, right interface{}) bool
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
@@ -130,7 +130,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func LessThan(left, right any) bool
|
func LessThan(left, right interface{}) bool
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
@@ -179,7 +179,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func GreaterThan(left, right any) bool
|
func GreaterThan(left, right interface{}) bool
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
@@ -231,7 +231,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func LessOrEqual(left, right any) bool
|
func LessOrEqual(left, right interface{}) bool
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
@@ -280,7 +280,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func GreaterOrEqual(left, right any) bool
|
func GreaterOrEqual(left, right interface{}) bool
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ import (
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func Equal(left, right any) bool
|
func Equal(left, right interface{}) bool
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
@@ -91,7 +91,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func EqualValue(left, right any) bool
|
func EqualValue(left, right interface{}) bool
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
@@ -130,7 +130,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func LessThan(left, right any) bool
|
func LessThan(left, right interface{}) bool
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
@@ -179,7 +179,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func GreaterThan(left, right any) bool
|
func GreaterThan(left, right interface{}) bool
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
@@ -231,7 +231,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func LessOrEqual(left, right any) bool
|
func LessOrEqual(left, right interface{}) bool
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
@@ -280,7 +280,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func GreaterOrEqual(left, right any) bool
|
func GreaterOrEqual(left, right interface{}) bool
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ import (
|
|||||||
- [ToUrlBase64](#ToUrlBase64)
|
- [ToUrlBase64](#ToUrlBase64)
|
||||||
- [ToRawStdBase64](#ToRawStdBase64)
|
- [ToRawStdBase64](#ToRawStdBase64)
|
||||||
- [ToRawUrlBase64](#ToRawUrlBase64)
|
- [ToRawUrlBase64](#ToRawUrlBase64)
|
||||||
|
- [ToBigInt](#ToBigInt)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -454,7 +454,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func EncodeByte(data any) ([]byte, error)
|
func EncodeByte(data interface{}) ([]byte, error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
@@ -480,7 +480,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func DecodeByte(data []byte, target any) error
|
func DecodeByte(data []byte, target interface{}) error
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
@@ -508,7 +508,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func DeepClone[T any](src T) T
|
func DeepClone[T interface{}](src T) T
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
@@ -753,7 +753,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func ToStdBase64(value any) string
|
func ToStdBase64(value interface{}) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
@@ -785,7 +785,7 @@ func main() {
|
|||||||
afterEncode = convertor.ToStdBase64(intVal)
|
afterEncode = convertor.ToStdBase64(intVal)
|
||||||
fmt.Println(afterEncode)
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
mapVal := map[string]interface{}{"a": "hi", "b": 2, "c": struct {
|
||||||
A string
|
A string
|
||||||
B int
|
B int
|
||||||
}{"hello", 3}}
|
}{"hello", 3}}
|
||||||
@@ -825,7 +825,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func ToUrlBase64(value any) string
|
func ToUrlBase64(value interface{}) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
@@ -855,7 +855,7 @@ func main() {
|
|||||||
afterEncode = convertor.ToUrlBase64(intVal)
|
afterEncode = convertor.ToUrlBase64(intVal)
|
||||||
fmt.Println(afterEncode)
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
mapVal := map[string]interface{}{"a": "hi", "b": 2, "c": struct {
|
||||||
A string
|
A string
|
||||||
B int
|
B int
|
||||||
}{"hello", 3}}
|
}{"hello", 3}}
|
||||||
@@ -894,7 +894,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func ToRawStdBase64(value any) string
|
func ToRawStdBase64(value interface{}) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
@@ -921,7 +921,7 @@ func main() {
|
|||||||
afterEncode = convertor.ToRawStdBase64(intVal)
|
afterEncode = convertor.ToRawStdBase64(intVal)
|
||||||
fmt.Println(afterEncode)
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
mapVal := map[string]interface{}{"a": "hi", "b": 2, "c": struct {
|
||||||
A string
|
A string
|
||||||
B int
|
B int
|
||||||
}{"hello", 3}}
|
}{"hello", 3}}
|
||||||
@@ -958,7 +958,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func ToRawUrlBase64(value any) string
|
func ToRawUrlBase64(value interface{}) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
@@ -985,7 +985,7 @@ func main() {
|
|||||||
afterEncode = convertor.ToRawUrlBase64(intVal)
|
afterEncode = convertor.ToRawUrlBase64(intVal)
|
||||||
fmt.Println(afterEncode)
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
mapVal := map[string]interface{}{"a": "hi", "b": 2, "c": struct {
|
||||||
A string
|
A string
|
||||||
B int
|
B int
|
||||||
}{"hello", 3}}
|
}{"hello", 3}}
|
||||||
@@ -1013,4 +1013,34 @@ func main() {
|
|||||||
// dHJ1ZQ
|
// dHJ1ZQ
|
||||||
// ZXJy
|
// ZXJy
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ToBigInt">ToBigInt</span>
|
||||||
|
|
||||||
|
<p>Convert value to bigInt.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ToBigInt(v interface{}) (*big.Int, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/convertor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
n := 9876543210
|
||||||
|
bigInt, _ := convertor.ToBigInt(n)
|
||||||
|
|
||||||
|
fmt.Println(bigInt)
|
||||||
|
// Output:
|
||||||
|
// 9876543210
|
||||||
|
}
|
||||||
```
|
```
|
||||||
@@ -45,6 +45,7 @@ import (
|
|||||||
- [ToUrlBase64](#ToUrlBase64)
|
- [ToUrlBase64](#ToUrlBase64)
|
||||||
- [ToRawStdBase64](#ToRawStdBase64)
|
- [ToRawStdBase64](#ToRawStdBase64)
|
||||||
- [ToRawUrlBase64](#ToRawUrlBase64)
|
- [ToRawUrlBase64](#ToRawUrlBase64)
|
||||||
|
- [ToBigInt](#ToBigInt)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -453,7 +454,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func EncodeByte(data any) ([]byte, error)
|
func EncodeByte(data interface{}) ([]byte, error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
@@ -479,7 +480,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func DecodeByte(data []byte, target any) error
|
func DecodeByte(data []byte, target interface{}) error
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
@@ -507,7 +508,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func DeepClone[T any](src T) T
|
func DeepClone[T interface{}](src T) T
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
@@ -753,7 +754,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func ToStdBase64(value any) string
|
func ToStdBase64(value interface{}) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
@@ -763,7 +764,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/convertor"
|
"github.com/duke-git/lancet/convertor"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -785,7 +786,7 @@ func main() {
|
|||||||
afterEncode = convertor.ToStdBase64(intVal)
|
afterEncode = convertor.ToStdBase64(intVal)
|
||||||
fmt.Println(afterEncode)
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
mapVal := map[string]interface{}{"a": "hi", "b": 2, "c": struct {
|
||||||
A string
|
A string
|
||||||
B int
|
B int
|
||||||
}{"hello", 3}}
|
}{"hello", 3}}
|
||||||
@@ -825,7 +826,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func ToUrlBase64(value any) string
|
func ToUrlBase64(value interface{}) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
@@ -835,7 +836,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/convertor"
|
"github.com/duke-git/lancet/convertor"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -855,7 +856,7 @@ func main() {
|
|||||||
afterEncode = convertor.ToUrlBase64(intVal)
|
afterEncode = convertor.ToUrlBase64(intVal)
|
||||||
fmt.Println(afterEncode)
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
mapVal := map[string]interface{}{"a": "hi", "b": 2, "c": struct {
|
||||||
A string
|
A string
|
||||||
B int
|
B int
|
||||||
}{"hello", 3}}
|
}{"hello", 3}}
|
||||||
@@ -894,7 +895,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func ToRawStdBase64(value any) string
|
func ToRawStdBase64(value interface{}) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
@@ -904,7 +905,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/convertor"
|
"github.com/duke-git/lancet/convertor"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -921,7 +922,7 @@ func main() {
|
|||||||
afterEncode = convertor.ToRawStdBase64(intVal)
|
afterEncode = convertor.ToRawStdBase64(intVal)
|
||||||
fmt.Println(afterEncode)
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
mapVal := map[string]interface{}{"a": "hi", "b": 2, "c": struct {
|
||||||
A string
|
A string
|
||||||
B int
|
B int
|
||||||
}{"hello", 3}}
|
}{"hello", 3}}
|
||||||
@@ -958,7 +959,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func ToRawUrlBase64(value any) string
|
func ToRawUrlBase64(value interface{}) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:</b>
|
<b>示例:</b>
|
||||||
@@ -968,7 +969,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/convertor"
|
"github.com/duke-git/lancet/convertor"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -985,7 +986,7 @@ func main() {
|
|||||||
afterEncode = convertor.ToRawUrlBase64(intVal)
|
afterEncode = convertor.ToRawUrlBase64(intVal)
|
||||||
fmt.Println(afterEncode)
|
fmt.Println(afterEncode)
|
||||||
|
|
||||||
mapVal := map[string]any{"a": "hi", "b": 2, "c": struct {
|
mapVal := map[string]interface{}{"a": "hi", "b": 2, "c": struct {
|
||||||
A string
|
A string
|
||||||
B int
|
B int
|
||||||
}{"hello", 3}}
|
}{"hello", 3}}
|
||||||
@@ -1013,4 +1014,34 @@ func main() {
|
|||||||
// dHJ1ZQ
|
// dHJ1ZQ
|
||||||
// ZXJy
|
// ZXJy
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="ToBigInt">ToBigInt</span>
|
||||||
|
|
||||||
|
<p>将整数值转换为bigInt。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func ToBigInt(v interface{}) (*big.Int, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/convertor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
n := 9876543210
|
||||||
|
bigInt, _ := convertor.ToBigInt(n)
|
||||||
|
|
||||||
|
fmt.Println(bigInt)
|
||||||
|
// Output:
|
||||||
|
// 9876543210
|
||||||
|
}
|
||||||
```
|
```
|
||||||
106
docs/datetime.md
106
docs/datetime.md
@@ -62,6 +62,9 @@ import (
|
|||||||
- [TimestampMilli](#TimestampMilli)
|
- [TimestampMilli](#TimestampMilli)
|
||||||
- [TimestampMicro](#TimestampMicro)
|
- [TimestampMicro](#TimestampMicro)
|
||||||
- [TimestampNano](#TimestampNano)
|
- [TimestampNano](#TimestampNano)
|
||||||
|
- [TrackFuncTime](#TrackFuncTime)
|
||||||
|
- [DaysBetween](#DaysBetween)
|
||||||
|
- [GenerateDatetimesBetween](#GenerateDatetimesBetween)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -1360,3 +1363,106 @@ func main() {
|
|||||||
// 1690363051331788000
|
// 1690363051331788000
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="TrackFuncTime">TrackFuncTime</span>
|
||||||
|
|
||||||
|
<p>Tracks function execution time.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func TrackFuncTime(pre time.Time) func()
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/datetime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
defer datetime.TrackFuncTime(time.Now())()
|
||||||
|
|
||||||
|
var n int
|
||||||
|
for i := 0; i < 5000000; i++ {
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(1) // Function main execution time: 1.460287ms
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="DaysBetween">DaysBetween</span>
|
||||||
|
|
||||||
|
<p>Returns the number of days between two times.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func DaysBetween(start, end time.Time) int
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/datetime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
start := time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC)
|
||||||
|
end := time.Date(2024, time.September, 10, 0, 0, 0, 0, time.UTC)
|
||||||
|
|
||||||
|
result := datetime.DaysBetween(start, end)
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 9
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="GenerateDatetimesBetween">GenerateDatetimesBetween</span>
|
||||||
|
|
||||||
|
<p>Returns a slice of strings between two times. `layout`: the format of the datetime string.`interval`: the interval between two datetimes.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func GenerateDatetimesBetween(start, end time.Time, layout string, interval string) ([]string, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/datetime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
start := time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC)
|
||||||
|
end := time.Date(2024, time.September, 1, 2, 0, 0, 0, time.UTC)
|
||||||
|
|
||||||
|
layout := "2006-01-02 15:04:05"
|
||||||
|
interval := "1h"
|
||||||
|
|
||||||
|
result, err := datetime.GenerateDatetimesBetween(start, end, layout, interval)
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
fmt.Println(err)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [2024-09-01 00:00:00 2024-09-01 01:00:00 2024-09-01 02:00:00]
|
||||||
|
// <nil>
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -62,6 +62,10 @@ import (
|
|||||||
- [TimestampMilli](#TimestampMilli)
|
- [TimestampMilli](#TimestampMilli)
|
||||||
- [TimestampMicro](#TimestampMicro)
|
- [TimestampMicro](#TimestampMicro)
|
||||||
- [TimestampNano](#TimestampNano)
|
- [TimestampNano](#TimestampNano)
|
||||||
|
- [TrackFuncTime](#TrackFuncTime)
|
||||||
|
- [DaysBetween](#DaysBetween)
|
||||||
|
- [GenerateDatetimesBetween](#GenerateDatetimesBetween)
|
||||||
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -1279,4 +1283,108 @@ func main() {
|
|||||||
// Output:
|
// Output:
|
||||||
// 1690363051331788000
|
// 1690363051331788000
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="TrackFuncTime">TrackFuncTime</span>
|
||||||
|
|
||||||
|
<p>返回两个日期之间的天数差。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func TrackFuncTime(pre time.Time) func()
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/datetime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
defer datetime.TrackFuncTime(time.Now())()
|
||||||
|
|
||||||
|
var n int
|
||||||
|
for i := 0; i < 5000000; i++ {
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Function main execution time: 1.608195ms
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="DaysBetween">DaysBetween</span>
|
||||||
|
|
||||||
|
<p>返回两个日期之间的天数差。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func DaysBetween(start, end time.Time) int
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/datetime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
start := time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC)
|
||||||
|
end := time.Date(2024, time.September, 10, 0, 0, 0, 0, time.UTC)
|
||||||
|
|
||||||
|
result := datetime.DaysBetween(start, end)
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 9
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="GenerateDatetimesBetween">GenerateDatetimesBetween</span>
|
||||||
|
|
||||||
|
<p>生成从start到end的所有日期时间的字符串列表。layout参数表示时间格式,例如"2006-01-02 15:04:05",interval参数表示时间间隔,例如"1h"表示1小时,"30m"表示30分钟。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func GenerateDatetimesBetween(start, end time.Time, layout string, interval string) ([]string, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/datetime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
start := time.Date(2024, time.September, 1, 0, 0, 0, 0, time.UTC)
|
||||||
|
end := time.Date(2024, time.September, 1, 2, 0, 0, 0, time.UTC)
|
||||||
|
|
||||||
|
layout := "2006-01-02 15:04:05"
|
||||||
|
interval := "1h"
|
||||||
|
|
||||||
|
result, err := datetime.GenerateDatetimesBetween(start, end, layout, interval)
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
fmt.Println(err)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [2024-09-01 00:00:00 2024-09-01 01:00:00 2024-09-01 02:00:00]
|
||||||
|
// <nil>
|
||||||
|
}
|
||||||
```
|
```
|
||||||
@@ -902,7 +902,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/fileutil"
|
"github.com/duke-git/lancet/fileutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@@ -900,7 +900,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/fileutil"
|
"github.com/duke-git/lancet/fileutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ Param should be number or numberic string.</p>
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func Comma(value interface{}, symbol string) string
|
func Comma(value interface{}, prefixSymbol string) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:</b>
|
<b>Example:</b>
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ import (
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func Comma(v interface{}, symbol string) string
|
func Comma(v interface{}, prefixSymbol string) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>例子:</b>
|
<b>例子:</b>
|
||||||
|
|||||||
106
docs/strutil.md
106
docs/strutil.md
@@ -64,6 +64,9 @@ import (
|
|||||||
- [Ellipsis](#Ellipsis)
|
- [Ellipsis](#Ellipsis)
|
||||||
- [Shuffle](#Shuffle)
|
- [Shuffle](#Shuffle)
|
||||||
- [Rotate](#Rotate)
|
- [Rotate](#Rotate)
|
||||||
|
- [TemplateReplace](#TemplateReplace)
|
||||||
|
- [RegexMatchAllGroups](#RegexMatchAllGroups)
|
||||||
|
- [Cut](#Cut)
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -1468,4 +1471,105 @@ func main() {
|
|||||||
// Hello
|
// Hello
|
||||||
// oHell
|
// oHell
|
||||||
// loHel
|
// loHel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
### <span id="TemplateReplace">TemplateReplace</span>
|
||||||
|
|
||||||
|
<p>Replaces the placeholders in the template string with the corresponding values in the data map.The placeholders are enclosed in curly braces, e.g. {key}. for example, the template string is "Hello, {name}!", and the data map is {"name": "world"}, the result will be "Hello, world!".</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func TemplateReplace(template string, data map[string]string string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
template := `Hello, my name is {name}, I'm {age} years old.`
|
||||||
|
data := map[string]string{
|
||||||
|
"name": "Bob",
|
||||||
|
"age": "20",
|
||||||
|
}
|
||||||
|
|
||||||
|
result := strutil.TemplateReplace(template, data)
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Hello, my name is Bob, I'm 20 years old.
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="RegexMatchAllGroups">RegexMatchAllGroups</span>
|
||||||
|
|
||||||
|
<p>Matches all subgroups in a string using a regular expression and returns the result.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func RegexMatchAllGroups(pattern, str string) [][]string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
pattern := `(\w+\.+\w+)@(\w+)\.(\w+)`
|
||||||
|
str := "Emails: john.doe@example.com and jane.doe@example.com"
|
||||||
|
|
||||||
|
result := strutil.RegexMatchAllGroups(pattern, str)
|
||||||
|
|
||||||
|
fmt.Println(result[0])
|
||||||
|
fmt.Println(result[1])
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [john.doe@example.com john.doe example com]
|
||||||
|
// [jane.doe@example.com jane.doe example com]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Cut">Cut</span>
|
||||||
|
|
||||||
|
<p>Splits the string at the first occurrence of separator.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Cut(str, sep string) (before, after string, found bool)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
str := "hello-world"
|
||||||
|
|
||||||
|
before, after, found := strutil.Cut("hello-world", "-")
|
||||||
|
|
||||||
|
fmt.Println(before)
|
||||||
|
fmt.Println(after)
|
||||||
|
fmt.Println(found)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// hello
|
||||||
|
// world
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -64,6 +64,9 @@ import (
|
|||||||
- [Ellipsis](#Ellipsis)
|
- [Ellipsis](#Ellipsis)
|
||||||
- [Shuffle](#Shuffle)
|
- [Shuffle](#Shuffle)
|
||||||
- [Rotate](#Rotate)
|
- [Rotate](#Rotate)
|
||||||
|
- [TemplateReplace](#TemplateReplace)
|
||||||
|
- [RegexMatchAllGroups](#RegexMatchAllGroups)
|
||||||
|
- [Cut](#Cut)
|
||||||
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
@@ -1503,4 +1506,104 @@ func main() {
|
|||||||
// oHell
|
// oHell
|
||||||
// loHel
|
// loHel
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="TemplateReplace">TemplateReplace</span>
|
||||||
|
|
||||||
|
<p>将模板字符串中的占位符替换为数据映射中的相应值。占位符括在花括号中,例如 {key}。例如,模板字符串为“Hello, {name}!”,数据映射为{"name": "world"},结果将为“Hello, world!”。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func TemplateReplace(template string, data map[string]string) string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
template := `Hello, my name is {name}, I'm {age} years old.`
|
||||||
|
data := map[string]string{
|
||||||
|
"name": "Bob",
|
||||||
|
"age": "20",
|
||||||
|
}
|
||||||
|
|
||||||
|
result := strutil.TemplateReplace(template, data)
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Hello, my name is Bob, I'm 20 years old.
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="RegexMatchAllGroups">RegexMatchAllGroups</span>
|
||||||
|
|
||||||
|
<p>使用正则表达式匹配字符串中的所有子组并返回结果。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func RegexMatchAllGroups(pattern, str string) [][]string
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
pattern := `(\w+\.+\w+)@(\w+)\.(\w+)`
|
||||||
|
str := "Emails: john.doe@example.com and jane.doe@example.com"
|
||||||
|
|
||||||
|
result := strutil.RegexMatchAllGroups(pattern, str)
|
||||||
|
|
||||||
|
fmt.Println(result[0])
|
||||||
|
fmt.Println(result[1])
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [john.doe@example.com john.doe example com]
|
||||||
|
// [jane.doe@example.com jane.doe example com]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### <span id="Cut">Cut</span>
|
||||||
|
|
||||||
|
<p>分割字符串。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func Cut(str, sep string) (before, after string, found bool)
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
str := "hello-world"
|
||||||
|
|
||||||
|
before, after, found := strutil.Cut("hello-world", "-")
|
||||||
|
|
||||||
|
fmt.Println(before)
|
||||||
|
fmt.Println(after)
|
||||||
|
fmt.Println(found)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// hello
|
||||||
|
// world
|
||||||
|
// true
|
||||||
|
}
|
||||||
@@ -1225,7 +1225,7 @@ func IsMasterCard(v string) bool
|
|||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/duke-git/lancet/v2/validator"
|
"github.com/duke-git/lancet/validator"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@@ -16,10 +16,10 @@ import (
|
|||||||
"github.com/duke-git/lancet/convertor"
|
"github.com/duke-git/lancet/convertor"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Comma add comma to a number value by every 3 numbers from right. ahead by symbol char.
|
// Comma add comma to a number value by every 3 numbers from right. ahead by prefix symbol char.
|
||||||
// if value is invalid number string eg "aa", return empty string
|
// if value is invalid number string eg "aa", return empty string
|
||||||
// Comma("12345", "$") => "$12,345", Comma(12345, "$") => "$12,345"
|
// Comma("12345", "$") => "$12,345", Comma(12345, "$") => "$12,345"
|
||||||
func Comma(value interface{}, symbol string) string {
|
func Comma(value interface{}, prefixSymbol string) string {
|
||||||
numString := convertor.ToString(value)
|
numString := convertor.ToString(value)
|
||||||
|
|
||||||
_, err := strconv.ParseFloat(numString, 64)
|
_, err := strconv.ParseFloat(numString, 64)
|
||||||
@@ -27,17 +27,26 @@ func Comma(value interface{}, symbol string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isNegative := strings.HasPrefix(numString, "-")
|
||||||
|
if isNegative {
|
||||||
|
numString = numString[1:]
|
||||||
|
}
|
||||||
|
|
||||||
index := strings.Index(numString, ".")
|
index := strings.Index(numString, ".")
|
||||||
if index == -1 {
|
if index == -1 {
|
||||||
index = len(numString)
|
index = len(numString)
|
||||||
}
|
}
|
||||||
|
|
||||||
for index > 3 {
|
for index > 3 {
|
||||||
index = index - 3
|
index -= 3
|
||||||
numString = numString[:index] + "," + numString[index:]
|
numString = numString[:index] + "," + numString[index:]
|
||||||
}
|
}
|
||||||
|
|
||||||
return symbol + numString
|
if isNegative {
|
||||||
|
numString = "-" + numString
|
||||||
|
}
|
||||||
|
|
||||||
|
return prefixSymbol + numString
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pretty data to JSON string.
|
// Pretty data to JSON string.
|
||||||
|
|||||||
@@ -26,6 +26,10 @@ func TestComma(t *testing.T) {
|
|||||||
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, ""))
|
||||||
|
|
||||||
|
assert.Equal("-999", Comma(-999, ""))
|
||||||
|
assert.Equal("-1,000", Comma(-1000, ""))
|
||||||
|
assert.Equal("-1,234,567", Comma(-1234567, ""))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPretty(t *testing.T) {
|
func TestPretty(t *testing.T) {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MaximumCapacity = math.MaxInt>>1 + 1
|
MaximumCapacity = math.MaxInt32>>1 + 1
|
||||||
Numeral = "0123456789"
|
Numeral = "0123456789"
|
||||||
LowwerLetters = "abcdefghijklmnopqrstuvwxyz"
|
LowwerLetters = "abcdefghijklmnopqrstuvwxyz"
|
||||||
UpperLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
UpperLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
|||||||
@@ -360,7 +360,6 @@ func StringToBytes(str string) (b []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// BytesToString converts a byte slice to string without a memory allocation.
|
// BytesToString converts a byte slice to string without a memory allocation.
|
||||||
// Play: todo
|
|
||||||
func BytesToString(bytes []byte) string {
|
func BytesToString(bytes []byte) string {
|
||||||
return *(*string)(unsafe.Pointer(&bytes))
|
return *(*string)(unsafe.Pointer(&bytes))
|
||||||
}
|
}
|
||||||
@@ -536,15 +535,22 @@ func RemoveWhiteSpace(str string, repalceAll bool) string {
|
|||||||
|
|
||||||
// SubInBetween return substring between the start and end position(excluded) of source string.
|
// SubInBetween return substring between the start and end position(excluded) of source string.
|
||||||
func SubInBetween(str string, start string, end string) string {
|
func SubInBetween(str string, start string, end string) string {
|
||||||
if _, after, ok := strings.Cut(str, start); ok {
|
if _, after, ok := Cut(str, start); ok {
|
||||||
if before, _, ok := strings.Cut(after, end); ok {
|
if before, _, ok := Cut(after, end); ok {
|
||||||
return before
|
return before
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cut splits the string at the first occurrence of separator.
|
||||||
|
func Cut(str, sep string) (before, after string, found bool) {
|
||||||
|
if i := strings.Index(str, sep); i >= 0 {
|
||||||
|
return str[:i], str[i+len(sep):], true
|
||||||
|
}
|
||||||
|
return str, "", false
|
||||||
|
}
|
||||||
|
|
||||||
// HammingDistance calculates the Hamming distance between two strings.
|
// HammingDistance calculates the Hamming distance between two strings.
|
||||||
// The Hamming distance is the number of positions at which the corresponding symbols are different.
|
// The Hamming distance is the number of positions at which the corresponding symbols are different.
|
||||||
// This func returns an error if the input strings are of unequal lengths.
|
// This func returns an error if the input strings are of unequal lengths.
|
||||||
@@ -642,3 +648,32 @@ func Rotate(str string, shift int) string {
|
|||||||
|
|
||||||
return sb.String()
|
return sb.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TemplateReplace replaces the placeholders in the template string with the corresponding values in the data map.
|
||||||
|
// The placeholders are enclosed in curly braces, e.g. {key}.
|
||||||
|
// for example, the template string is "Hello, {name}!", and the data map is {"name": "world"},
|
||||||
|
// the result will be "Hello, world!".
|
||||||
|
func TemplateReplace(template string, data map[string]string) string {
|
||||||
|
re := regexp.MustCompile(`\{(\w+)\}`)
|
||||||
|
|
||||||
|
result := re.ReplaceAllStringFunc(template, func(s string) string {
|
||||||
|
key := strings.Trim(s, "{}")
|
||||||
|
if val, ok := data[key]; ok {
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
})
|
||||||
|
|
||||||
|
result = strings.ReplaceAll(result, "{{", "{")
|
||||||
|
result = strings.ReplaceAll(result, "}}", "}")
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegexMatchAllGroups Matches all subgroups in a string using a regular expression and returns the result.
|
||||||
|
func RegexMatchAllGroups(pattern, str string) [][]string {
|
||||||
|
re := regexp.MustCompile(pattern)
|
||||||
|
matches := re.FindAllStringSubmatch(str, -1)
|
||||||
|
return matches
|
||||||
|
}
|
||||||
|
|||||||
@@ -581,3 +581,164 @@ func TestRotate(t *testing.T) {
|
|||||||
assert.Equal(tt.expected, Rotate(tt.input, tt.shift))
|
assert.Equal(tt.expected, Rotate(tt.input, tt.shift))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTemplateReplace(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
assert := internal.NewAssert(t, "TestTemplateReplace")
|
||||||
|
|
||||||
|
t.Run("basic", func(t *testing.T) {
|
||||||
|
template := `Hello, my name is {name}, I'm {age} years old.`
|
||||||
|
data := map[string]string{
|
||||||
|
"name": "Bob",
|
||||||
|
"age": "20",
|
||||||
|
}
|
||||||
|
|
||||||
|
expected := `Hello, my name is Bob, I'm 20 years old.`
|
||||||
|
result := TemplateReplace(template, data)
|
||||||
|
|
||||||
|
assert.Equal(expected, result)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("not found", func(t *testing.T) {
|
||||||
|
template := `Hello, my name is {name}, I'm {age} years old.`
|
||||||
|
data := map[string]string{
|
||||||
|
"name": "Bob",
|
||||||
|
}
|
||||||
|
|
||||||
|
expected := `Hello, my name is Bob, I'm {age} years old.`
|
||||||
|
result := TemplateReplace(template, data)
|
||||||
|
|
||||||
|
assert.Equal(expected, result)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("brackets", func(t *testing.T) {
|
||||||
|
template := `Hello, my name is {name}, I'm {{age}} years old.`
|
||||||
|
data := map[string]string{
|
||||||
|
"name": "Bob",
|
||||||
|
"age": "20",
|
||||||
|
}
|
||||||
|
|
||||||
|
expected := `Hello, my name is Bob, I'm {20} years old.`
|
||||||
|
result := TemplateReplace(template, data)
|
||||||
|
|
||||||
|
assert.Equal(expected, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRegexMatchAllGroups(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
assert := internal.NewAssert(t, "TestRegexMatchAllGroups")
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
pattern string
|
||||||
|
str string
|
||||||
|
expected [][]string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
pattern: `(\w+\.+\w+)@(\w+)\.(\w+)`,
|
||||||
|
str: "Emails: john.doe@example.com and jane.doe@example.com",
|
||||||
|
expected: [][]string{{"john.doe@example.com", "john.doe", "example", "com"}, {"jane.doe@example.com", "jane.doe", "example", "com"}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: `(\d+)`,
|
||||||
|
str: "No numbers here!",
|
||||||
|
expected: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: `(\d{3})-(\d{2})-(\d{4})`,
|
||||||
|
str: "My number is 123-45-6789",
|
||||||
|
expected: [][]string{{"123-45-6789", "123", "45", "6789"}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: `(\w+)\s(\d+)`,
|
||||||
|
str: "Item A 123, Item B 456",
|
||||||
|
expected: [][]string{{"A 123", "A", "123"}, {"B 456", "B", "456"}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: `(\d{2})-(\d{2})-(\d{4})`,
|
||||||
|
str: "Dates: 01-01-2020, 12-31-1999",
|
||||||
|
expected: [][]string{{"01-01-2020", "01", "01", "2020"}, {"12-31-1999", "12", "31", "1999"}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
result := RegexMatchAllGroups(tt.pattern, tt.str)
|
||||||
|
assert.Equal(tt.expected, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCut(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
assert := internal.NewAssert(t, "TestCut")
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
s string
|
||||||
|
sep string
|
||||||
|
before string
|
||||||
|
after string
|
||||||
|
found bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "test with separator",
|
||||||
|
s: "hello-world",
|
||||||
|
sep: "-",
|
||||||
|
before: "hello",
|
||||||
|
after: "world",
|
||||||
|
found: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "test without separator",
|
||||||
|
s: "helloworld",
|
||||||
|
sep: "-",
|
||||||
|
before: "helloworld",
|
||||||
|
after: "",
|
||||||
|
found: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "test empty string",
|
||||||
|
s: "",
|
||||||
|
sep: "-",
|
||||||
|
before: "",
|
||||||
|
after: "",
|
||||||
|
found: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "test separator at the beginning",
|
||||||
|
s: "-hello",
|
||||||
|
sep: "-",
|
||||||
|
before: "",
|
||||||
|
after: "hello",
|
||||||
|
found: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "test separator at the end",
|
||||||
|
s: "hello-",
|
||||||
|
sep: "-",
|
||||||
|
before: "hello",
|
||||||
|
after: "",
|
||||||
|
found: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "test multiple separators",
|
||||||
|
s: "a-b-c-d",
|
||||||
|
sep: "-",
|
||||||
|
before: "a",
|
||||||
|
after: "b-c-d",
|
||||||
|
found: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
before, after, found := Cut(tt.s, tt.sep)
|
||||||
|
assert.Equal(tt.before, before)
|
||||||
|
assert.Equal(tt.after, after)
|
||||||
|
assert.Equal(tt.found, found)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
//go:build windows
|
//go:build windows
|
||||||
|
// +build windows
|
||||||
|
|
||||||
package system
|
package system
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user