diff --git a/README.md b/README.md index 72579369..25d4be09 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@
![Go version](https://img.shields.io/badge/go-v1.16-9cf) -[![Release](https://img.shields.io/badge/release-1.4.5-green.svg)](https://github.com/duke-git/lancet/releases) +[![Release](https://img.shields.io/badge/release-1.4.6-green.svg)](https://github.com/duke-git/lancet/releases) [![GoDoc](https://godoc.org/github.com//duke-git/lancet?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet) [![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet)](https://goreportcard.com/report/github.com/duke-git/lancet) [![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) @@ -484,6 +484,7 @@ import "github.com/duke-git/lancet/strutil" - [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. diff --git a/README_zh-CN.md b/README_zh-CN.md index 92980862..5b194827 100644 --- a/README_zh-CN.md +++ b/README_zh-CN.md @@ -4,7 +4,7 @@
![Go version](https://img.shields.io/badge/go-v1.16-9cf) -[![Release](https://img.shields.io/badge/release-1.4.5-green.svg)](https://github.com/duke-git/lancet/releases) +[![Release](https://img.shields.io/badge/release-1.4.6-green.svg)](https://github.com/duke-git/lancet/releases) [![GoDoc](https://godoc.org/github.com//duke-git/lancet?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet) [![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet)](https://goreportcard.com/report/github.com/duke-git/lancet) [![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) @@ -486,6 +486,7 @@ import "github.com/duke-git/lancet/strutil" - [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 相关函数。 diff --git a/compare/compare_internal.go b/compare/compare_internal.go index 64a9829c..e363a183 100644 --- a/compare/compare_internal.go +++ b/compare/compare_internal.go @@ -37,7 +37,8 @@ func compareRefValue(operator string, leftObj, rightObj interface{}, kind reflec case reflect.Struct: // compare time - if leftVal.CanConvert(timeType) { + // fix: issue #275 + if canConvert(leftObj, timeType) { timeObj1, ok := leftObj.(time.Time) if !ok { timeObj1 = leftVal.Convert(timeType).Interface().(time.Time) @@ -59,7 +60,7 @@ func compareRefValue(operator string, leftObj, rightObj interface{}, kind reflec case reflect.Slice: // compare []byte - if leftVal.CanConvert(bytesType) { + if canConvert(leftObj, bytesType) { bytesObj1, ok := leftObj.([]byte) if !ok { bytesObj1 = leftVal.Convert(bytesType).Interface().([]byte) @@ -282,3 +283,15 @@ func compareBools(operator string, left, right bool) bool { } 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 +} diff --git a/convertor/convertor_internal.go b/convertor/convertor_internal.go index 796c9d39..0f26a72c 100644 --- a/convertor/convertor_internal.go +++ b/convertor/convertor_internal.go @@ -240,7 +240,8 @@ func setStructField(structObj interface{}, fieldName string, fieldValue interfac if fieldVal.Type() != val.Type() { - if val.CanConvert(fieldVal.Type()) { + // fix: issue #275 + if canConvert(fieldValue, fieldVal.Type()) { fieldVal.Set(val.Convert(fieldVal.Type())) return nil } @@ -284,3 +285,14 @@ func getFieldNameByJsonTag(structObj interface{}, jsonTag string) string { 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 +} diff --git a/docs/strutil.md b/docs/strutil.md index fc9ddbb0..f99210f8 100644 --- a/docs/strutil.md +++ b/docs/strutil.md @@ -66,6 +66,7 @@ import ( - [Rotate](#Rotate) - [TemplateReplace](#TemplateReplace) - [RegexMatchAllGroups](#RegexMatchAllGroups) +- [Cut](#Cut)
@@ -1537,4 +1538,38 @@ func main() { // [john.doe@example.com john.doe example com] // [jane.doe@example.com jane.doe example com] } +``` + +### Cut + +

Splits the string at the first occurrence of separator.

+ +Signature: + +```go +func Cut(str, sep string) (before, after string, found bool) +``` + +example: + +```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 +} ``` \ No newline at end of file diff --git a/docs/strutil_zh-CN.md b/docs/strutil_zh-CN.md index a33c4af3..93dbdc66 100644 --- a/docs/strutil_zh-CN.md +++ b/docs/strutil_zh-CN.md @@ -66,6 +66,7 @@ import ( - [Rotate](#Rotate) - [TemplateReplace](#TemplateReplace) - [RegexMatchAllGroups](#RegexMatchAllGroups) +- [Cut](#Cut)
@@ -1572,4 +1573,37 @@ func main() { // [john.doe@example.com john.doe example com] // [jane.doe@example.com jane.doe example com] } -``` \ No newline at end of file +``` + +### Cut + +

分割字符串。

+ +函数签名: + +```go +func Cut(str, sep string) (before, after string, found bool) +``` + +示例: + +```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 +} \ No newline at end of file diff --git a/strutil/string.go b/strutil/string.go index 870ec8bc..0da6b6c7 100644 --- a/strutil/string.go +++ b/strutil/string.go @@ -535,15 +535,22 @@ func RemoveWhiteSpace(str string, repalceAll bool) string { // SubInBetween return substring between the start and end position(excluded) of source string. func SubInBetween(str string, start string, end string) string { - if _, after, ok := strings.Cut(str, start); ok { - if before, _, ok := strings.Cut(after, end); ok { + if _, after, ok := Cut(str, start); ok { + if before, _, ok := Cut(after, end); ok { return before } } - 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. // 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. diff --git a/strutil/string_test.go b/strutil/string_test.go index 163c1449..424608f0 100644 --- a/strutil/string_test.go +++ b/strutil/string_test.go @@ -668,3 +668,77 @@ func TestRegexMatchAllGroups(t *testing.T) { 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) + }) + } + +} diff --git a/system/os_windows.go b/system/os_windows.go index 6cd36987..f1f34f1c 100644 --- a/system/os_windows.go +++ b/system/os_windows.go @@ -1,4 +1,5 @@ //go:build windows +// +build windows package system