diff --git a/README.md b/README.md index bf6d5df..25b85cf 100644 --- a/README.md +++ b/README.md @@ -1125,6 +1125,10 @@ import "github.com/duke-git/lancet/v2/maputil" - **FindValuesBy** : returns a slice of values from the map that satisfy the given predicate function. [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#FindValuesBy)] [[play](https://go.dev/play/p/bvNwNBZDm6v)] +- **ToMarkdownTable** : Convert a map slice data to a Markdown table string. It supports custom header display names and column display order. + [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/maputil.md#ToMarkdownTable)] + [[play](https://go.dev/play/p/todo)] +
获取结构体类型名。
+ +函数签名: + +```go +func (s *Struct) TypeName() string +``` + +示例:[运行](https://go.dev/play/p/todo) + +```go +package main + +import ( + "fmt" + "github.com/duke-git/lancet/v2/structs" +) + +func main() { + type Parent struct { + Name string + Age int + } + + p := &Parent{Age: 11} + s := structs.New(p1) + + fmt.Println(s.TypeName()) + + // Output: + // Parent +} +``` + ### IsSlice判断属性是否是切片
@@ -507,7 +550,7 @@ func main() { func (f *Field) IsSlice() bool ``` -示例: +示例:[运行](https://go.dev/play/p/MKz4CgBIUrU) ```go package main @@ -544,7 +587,7 @@ func main() { func (f *Field) IsTargetType(targetType reflect.Kind) bool ``` -示例: +示例:[运行](https://go.dev/play/p/Ig75P-agN39) ```go package main diff --git a/docs/api/packages/validator.md b/docs/api/packages/validator.md index b354ce0..35a81d6 100644 --- a/docs/api/packages/validator.md +++ b/docs/api/packages/validator.md @@ -65,6 +65,8 @@ import ( - [IsAmericanExpress](#IsAmericanExpress) - [IsUnionPay](#IsUnionPay) - [IsChinaUnionPay](#IsChinaUnionPay) +- [IsPassport](#IsPassport) +- [IsChineseHMPassport](#IsChineseHMPassport) @@ -844,20 +846,20 @@ import ( func main() { result1 := validator.IsAlphaNumeric("ABC") - result2 := validator.IsAlphaNumeric("123") - result3 := validator.IsAlphaNumeric("abc123") - result4 := validator.IsAlphaNumeric("abc123@#$") + result2 := validator.IsAlphaNumeric("123") + result3 := validator.IsAlphaNumeric("abc123") + result4 := validator.IsAlphaNumeric("abc123@#$") - fmt.Println(result1) - fmt.Println(result2) - fmt.Println(result3) - fmt.Println(result4) + fmt.Println(result1) + fmt.Println(result2) + fmt.Println(result3) + fmt.Println(result4) - // Output: - // true - // true - // true - // false + // Output: + // true + // true + // true + // false } ``` @@ -1567,3 +1569,80 @@ func main() { // false } ``` + +### IsPassport + +判断护照(正则判断)。
+ +函数签名: + +```go +func IsPassport(passport, country string) bool +``` + +示例:[运行](https://go.dev/play/p/todo) + +```go +import ( + "fmt" + "github.com/duke-git/lancet/v2/validator" +) + +func main() { + result1 := validator.IsPassport("P123456789", "CN") + result2 := validator.IsPassport("123456789", "US") + result3 := validator.IsPassport("AB1234567", "RU") + result4 := validator.IsPassport("123456789", "CN") + + fmt.Println(result1) + fmt.Println(result2) + fmt.Println(result3) + fmt.Println(result4) + + // Output: + // true + // true + // true + // false +} +``` + +### IsChineseHMPassport + +判断港澳台通行证(正则判断)。
+ +函数签名: + +```go +func IsChineseHMPassport(hmPassport string) bool +``` + +示例:[运行](https://go.dev/play/p/todo) + +```go +import ( + "fmt" + "github.com/duke-git/lancet/v2/validator" +) + +func main() { + result1 := validator.IsChineseHMPassport("C12345678") + result2 := validator.IsChineseHMPassport("C00000000") + result3 := validator.IsChineseHMPassport("M12345678") + result4 := validator.IsChineseHMPassport("c12345678") + result5 := validator.IsChineseHMPassport("C1234567") + + fmt.Println(result1) + fmt.Println(result2) + fmt.Println(result3) + fmt.Println(result4) + fmt.Println(result5) + + // Output: + // true + // true + // true + // false + // false +} +``` \ No newline at end of file diff --git a/docs/en/api/packages/maputil.md b/docs/en/api/packages/maputil.md index 9288c49..ec5e87f 100644 --- a/docs/en/api/packages/maputil.md +++ b/docs/en/api/packages/maputil.md @@ -79,6 +79,8 @@ import ( - [SortByKey](#SortByKey) - [GetOrDefault](#GetOrDefault) - [FindValuesBy](#FindValuesBy) +- [ToMarkdownTable](#ToMarkdownTable) + @@ -2363,3 +2365,69 @@ func main() { // [b d] } ``` + +### ToMarkdownTable + +Convert a map slice data to a Markdown table string. It supports custom header display names and column display order.
+ +Signature: + +```go +编辑 +func ToMarkdownTable(data []map[string]interface{}, headerMap map[string]string, columnOrder []string) string +``` +Example:[Run](https://go.dev/play/p/todo) + + +```go +package main + +import ( + "fmt" + "github.com/duke-git/lancet/v2/maputil" +) + +func main() { + // basic usage: automatically extract column names from data as table headers + + data := []map[string]interface{}{ + {"name": "Alice", "age": 25, "salary": 50000}, + {"name": "Bob", "age": 30, "salary": 60000}, + } + + result := maputil.ToMarkdownTable(data, nil, nil) + fmt.Println(result) + + // output: + // |name|age|salary| + // |---|---|---| + // |Alice|25|50000| + // |Bob|30|60000| + + // custom header name + headerMap := map[string]string{ + "name": "n", + "age": "a", + "salary": "s", + } + result = maputil.ToMarkdownTable(data, headerMap, nil) + fmt.Println(result) + + // ouput: + // |m|a|s| + // |---|---|---| + // |Alice|25|50000| + // |Bob|30|60000| + + // custom column display order + columnOrder := []string{"salary", "name"} + result = maputil.ToMarkdownTable(data, nil, columnOrder) + fmt.Println(result) + + // 输出: + // |salary|name| + // |---|---| + // |50000|Alice| + // |60000|Bob| +} +``` \ No newline at end of file diff --git a/docs/en/api/packages/struct.md b/docs/en/api/packages/struct.md index 51534e9..31503e3 100644 --- a/docs/en/api/packages/struct.md +++ b/docs/en/api/packages/struct.md @@ -31,6 +31,7 @@ import ( - [IsStruct](#IsStruct) - [Tag](#Tag) - [Name](#Name) +- [TypeName](#TypeName) - [Value](#Value) - [Kind](#Kind) - [IsEmbedded](#IsEmbedded) @@ -53,12 +54,13 @@ import ( func New(value any, tagName ...string) *Struct ``` -Example: +Example:[Run](https://go.dev/play/p/O29l8kk-Z17) ```go package main import ( + "fmt" "github.com/duke-git/lancet/v2/structs" ) @@ -68,7 +70,11 @@ func main() { } p1 := &People{Name: "11"} s := structs.New(p1) - // to do something + + fmt.Println(s.ToMap()) + + // Output: + // map[name:11]Return struct type name.
+ +Signature: + +```go +func (s *Struct) TypeName() string +``` + +Example:[Run](https://go.dev/play/p/todo) + +```go +package main + +import ( + "fmt" + "github.com/duke-git/lancet/v2/structs" +) + +func main() { + type Parent struct { + Name string + Age int + } + + p := &Parent{Age: 11} + s := structs.New(p1) + + fmt.Println(s.TypeName()) + + // Output: + // Parent +} +``` + ### IsSliceCheck if the field is a slice
@@ -508,7 +552,7 @@ func main() { func (f *Field) IsSlice() bool ``` -Example: +Example:[Run](https://go.dev/play/p/MKz4CgBIUrU) ```go package main @@ -545,7 +589,7 @@ func main() { func (f *Field) IsTargetType(targetType reflect.Kind) bool ``` -Example: +Example:[Run](https://go.dev/play/p/Ig75P-agN39) ```go package main diff --git a/docs/en/api/packages/validator.md b/docs/en/api/packages/validator.md index 2ab510d..eb674dc 100644 --- a/docs/en/api/packages/validator.md +++ b/docs/en/api/packages/validator.md @@ -65,6 +65,8 @@ import ( - [IsAmericanExpress](#IsAmericanExpress) - [IsUnionPay](#IsUnionPay) - [IsChinaUnionPay](#IsChinaUnionPay) +- [IsPassport](#IsPassport) +- [IsChineseHMPassport](#IsChineseHMPassport) @@ -1569,3 +1571,80 @@ func main() { // false } ``` + +### IsPassport + +Passport validation(using regex).
+ +Signature: + +```go +func IsPassport(passport, country string) bool +``` + +Example:[Run](https://go.dev/play/p/todo) + +```go +import ( + "fmt" + "github.com/duke-git/lancet/v2/validator" +) + +func main() { + result1 := validator.IsPassport("P123456789", "CN") + result2 := validator.IsPassport("123456789", "US") + result3 := validator.IsPassport("AB1234567", "RU") + result4 := validator.IsPassport("123456789", "CN") + + fmt.Println(result1) + fmt.Println(result2) + fmt.Println(result3) + fmt.Println(result4) + + // Output: + // true + // true + // true + // false +} +``` + +### IsChineseHMPassport + +Mainland travel permit for Hong Kong, Macao validation (using regex).
+ +Signature: + +```go +func IsChineseHMPassport(hmPassport string) bool +``` + +Example:[Run](https://go.dev/play/p/todo) + +```go +import ( + "fmt" + "github.com/duke-git/lancet/v2/validator" +) + +func main() { + result1 := validator.IsChineseHMPassport("C12345678") + result2 := validator.IsChineseHMPassport("C00000000") + result3 := validator.IsChineseHMPassport("M12345678") + result4 := validator.IsChineseHMPassport("c12345678") + result5 := validator.IsChineseHMPassport("C1234567") + + fmt.Println(result1) + fmt.Println(result2) + fmt.Println(result3) + fmt.Println(result4) + fmt.Println(result5) + + // Output: + // true + // true + // true + // false + // false +} +``` \ No newline at end of file diff --git a/maputil/map.go b/maputil/map.go index 7598116..93943c5 100644 --- a/maputil/map.go +++ b/maputil/map.go @@ -683,6 +683,7 @@ func FindValuesBy[K comparable, V any](m map[K]V, predicate func(key K, value V) } // ToMarkdownTable converts a slice of maps to a Markdown table. +// Play: ttps://go.dev/play/p/todo func ToMarkdownTable(data []map[string]interface{}, headerMap map[string]string, columnOrder []string) string { if len(data) == 0 { return "| |\n|---|\n" diff --git a/structs/field.go b/structs/field.go index cff2f43..1a5e5e8 100644 --- a/structs/field.go +++ b/structs/field.go @@ -26,26 +26,31 @@ func newField(v reflect.Value, f reflect.StructField, tagName string) *Field { } // Tag returns the value that the key in the tag string. +// Play: https://go.dev/play/p/DVrx5HvvUJr func (f *Field) Tag() *Tag { return f.tag } // Value returns the underlying value of the field. +// Play: https://go.dev/play/p/qufYEU2o4Oi func (f *Field) Value() any { return f.rvalue.Interface() } // IsEmbedded returns true if the given field is an embedded field. +// Play: https://go.dev/play/p/wV2PrbYm3Ec func (f *Field) IsEmbedded() bool { return len(f.field.Index) > 1 } // IsExported returns true if the given field is exported. +// Play: https://go.dev/play/p/csK4AXYaNbJ func (f *Field) IsExported() bool { return f.field.IsExported() } // IsZero returns true if the given field is zero value. +// Play: https://go.dev/play/p/RzqpGISf87r func (f *Field) IsZero() bool { z := reflect.Zero(f.rvalue.Type()).Interface() v := f.Value() @@ -63,22 +68,26 @@ func (f *Field) IsNil() bool { } // Name returns the name of the given field +// Play: https://go.dev/play/p/zfIGlqsatee func (f *Field) Name() string { return f.field.Name } // Kind returns the field's kind +// Play: https://go.dev/play/p/wg4NlcUNG5o func (f *Field) Kind() reflect.Kind { return f.rvalue.Kind() } // IsSlice check if a struct field type is slice or not +// Play: https://go.dev/play/p/MKz4CgBIUrU func (f *Field) IsSlice() bool { k := f.rvalue.Kind() return k == reflect.Slice } // IsTargetType check if a struct field type is target type or not +// Play: https://go.dev/play/p/Ig75P-agN39 func (f *Field) IsTargetType(targetType reflect.Kind) bool { return f.rvalue.Kind() == targetType } diff --git a/structs/struct.go b/structs/struct.go index 1760c02..f10fe62 100644 --- a/structs/struct.go +++ b/structs/struct.go @@ -20,6 +20,7 @@ type Struct struct { } // New returns a new *Struct +// Play: https://go.dev/play/p/O29l8kk-Z17 func New(value any, tagName ...string) *Struct { value = pointer.ExtractPointer(value) v := reflect.ValueOf(value) @@ -60,6 +61,7 @@ func New(value any, tagName ...string) *Struct { // Name string `json:"myName"` // // ToMap convert the exported fields of a struct to map. +// Play: https://go.dev/play/p/qQbLySBgerZ func (s *Struct) ToMap() (map[string]any, error) { if !s.IsStruct() { return nil, fmt.Errorf("invalid struct %v", s) @@ -87,6 +89,7 @@ func (s *Struct) ToMap() (map[string]any, error) { } // Fields returns all the struct fields within a slice +// Play: https://go.dev/play/p/w3Kk_CyVY7D func (s *Struct) Fields() []*Field { fieldNum := s.rvalue.NumField() fields := make([]*Field, 0, fieldNum) @@ -100,6 +103,7 @@ func (s *Struct) Fields() []*Field { } // Field returns a Field if the given field name was found +// Play: https://go.dev/play/p/KocZMSYarza func (s *Struct) Field(name string) (*Field, bool) { f, ok := s.rtype.FieldByName(name) if !ok { @@ -109,6 +113,7 @@ func (s *Struct) Field(name string) (*Field, bool) { } // IsStruct returns true if the given rvalue is a struct +// Play: https://go.dev/play/p/bU2FSdkbK1C func (s *Struct) IsStruct() bool { k := s.rvalue.Kind() if k == reflect.Invalid { @@ -119,11 +124,13 @@ func (s *Struct) IsStruct() bool { // ToMap convert struct to map, only convert exported struct field // map key is specified same as struct field tag `json` value. +// Play: https://go.dev/play/p/qQbLySBgerZ func ToMap(v any) (map[string]any, error) { return New(v).ToMap() } // TypeName return struct type name +// Play: https://go.dev/play/p/todo func (s *Struct) TypeName() string { return s.rtype.Name() }