From ba39323d3054a3d5dc17b73d15b9423843c5c537 Mon Sep 17 00:00:00 2001 From: John Guo Date: Mon, 22 Jan 2024 21:52:54 +0800 Subject: [PATCH] improve converter feature for package gconv (#3211) --- example/config/apollo/boot/boot.go | 6 ++ example/config/apollo/main.go | 6 ++ example/config/consul/boot/boot.go | 11 ++- example/config/consul/main.go | 6 ++ example/config/kubecm/boot_in_pod/boot.go | 6 ++ example/config/kubecm/boot_out_pod/boot.go | 9 ++- example/config/kubecm/main.go | 6 ++ example/config/nacos/boot/boot.go | 11 ++- example/config/nacos/main.go | 6 ++ .../alias_type_convert_with_refer/main.go | 58 ++++++++++++++ example/converter/alias_type_scan/main.go | 72 +++++++++++++++++ .../struct_convert_with_refer/main.go | 54 +++++++++++++ example/converter/struct_scan/main.go | 68 ++++++++++++++++ example/httpserver/default_value/main.go | 6 ++ example/httpserver/proxy/main.go | 6 ++ example/httpserver/rate/main.go | 9 ++- .../response_with_json_array/controller.go | 6 ++ .../response_with_json_array/main.go | 6 ++ example/httpserver/swagger/main.go | 6 ++ .../nosql/redis/configuration/basic/main.go | 6 ++ .../nosql/redis/configuration/senior/main.go | 6 ++ example/nosql/redis/expire/main.go | 6 ++ example/nosql/redis/hmset/main.go | 6 ++ example/nosql/redis/hset/main.go | 6 ++ example/nosql/redis/key-value/main.go | 6 ++ example/os/log/rotate/main.go | 6 ++ example/pack/main.go | 6 ++ example/pack/packed/paked.go | 6 ++ example/registry/etcd/http/client/client.go | 6 ++ example/registry/etcd/http/server/server.go | 6 ++ example/registry/file/client/client.go | 6 ++ example/registry/file/server/server.go | 6 ++ example/rpc/grpcx/rawgrpc/client/client.go | 6 ++ example/rpc/grpcx/rawgrpc/server/server.go | 6 ++ example/tcp/server/proxy/main.go | 6 ++ example/trace/grpc_with_db/client/client.go | 6 ++ example/trace/grpc_with_db/server/server.go | 6 ++ example/trace/http/client/client.go | 6 ++ example/trace/http/server/server.go | 6 ++ example/trace/http_with_db/client/client.go | 6 ++ example/trace/http_with_db/server/server.go | 6 ++ example/trace/inprocess/main.go | 6 ++ example/trace/processes/gcmd/main.go | 6 ++ example/trace/processes/gcmd/sub/sub.go | 6 ++ example/trace/processes/gproc/main.go | 6 ++ example/trace/processes/gproc/sub/sub.go | 6 ++ util/gconv/gconv_convert.go | 11 +++ util/gconv/gconv_converter.go | 78 +++++++++++++------ util/gconv/gconv_z_unit_converter_test.go | 46 +++++++++++ 49 files changed, 625 insertions(+), 30 deletions(-) create mode 100644 example/converter/alias_type_convert_with_refer/main.go create mode 100644 example/converter/alias_type_scan/main.go create mode 100644 example/converter/struct_convert_with_refer/main.go create mode 100644 example/converter/struct_scan/main.go diff --git a/example/config/apollo/boot/boot.go b/example/config/apollo/boot/boot.go index 91471fd32..a7584e913 100644 --- a/example/config/apollo/boot/boot.go +++ b/example/config/apollo/boot/boot.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package boot import ( diff --git a/example/config/apollo/main.go b/example/config/apollo/main.go index 12573229d..7e300cfce 100644 --- a/example/config/apollo/main.go +++ b/example/config/apollo/main.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/config/consul/boot/boot.go b/example/config/consul/boot/boot.go index 286e18ce6..7b090a8bd 100644 --- a/example/config/consul/boot/boot.go +++ b/example/config/consul/boot/boot.go @@ -1,12 +1,19 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package boot import ( consul "github.com/gogf/gf/contrib/config/consul/v2" - "github.com/gogf/gf/v2/frame/g" - "github.com/gogf/gf/v2/os/gctx" "github.com/hashicorp/consul/api" "github.com/hashicorp/go-cleanhttp" + + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gctx" ) func init() { diff --git a/example/config/consul/main.go b/example/config/consul/main.go index ad7a96a4a..3967b15bc 100644 --- a/example/config/consul/main.go +++ b/example/config/consul/main.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/config/kubecm/boot_in_pod/boot.go b/example/config/kubecm/boot_in_pod/boot.go index 094aaa24d..da0c2e3d6 100644 --- a/example/config/kubecm/boot_in_pod/boot.go +++ b/example/config/kubecm/boot_in_pod/boot.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package boot import ( diff --git a/example/config/kubecm/boot_out_pod/boot.go b/example/config/kubecm/boot_out_pod/boot.go index 936f68b2d..468bdc270 100644 --- a/example/config/kubecm/boot_out_pod/boot.go +++ b/example/config/kubecm/boot_out_pod/boot.go @@ -1,10 +1,17 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package boot import ( + "k8s.io/client-go/kubernetes" + "github.com/gogf/gf/contrib/config/kubecm/v2" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gctx" - "k8s.io/client-go/kubernetes" ) const ( diff --git a/example/config/kubecm/main.go b/example/config/kubecm/main.go index 31bf83ddc..22d3cd10b 100644 --- a/example/config/kubecm/main.go +++ b/example/config/kubecm/main.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/config/nacos/boot/boot.go b/example/config/nacos/boot/boot.go index 452aa8540..9eb53fa34 100644 --- a/example/config/nacos/boot/boot.go +++ b/example/config/nacos/boot/boot.go @@ -1,11 +1,18 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package boot import ( + "github.com/nacos-group/nacos-sdk-go/common/constant" + "github.com/nacos-group/nacos-sdk-go/vo" + "github.com/gogf/gf/contrib/config/nacos/v2" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gctx" - "github.com/nacos-group/nacos-sdk-go/common/constant" - "github.com/nacos-group/nacos-sdk-go/vo" ) func init() { diff --git a/example/config/nacos/main.go b/example/config/nacos/main.go index f7b38bf42..170369573 100644 --- a/example/config/nacos/main.go +++ b/example/config/nacos/main.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package nacos import ( diff --git a/example/converter/alias_type_convert_with_refer/main.go b/example/converter/alias_type_convert_with_refer/main.go new file mode 100644 index 000000000..d8fa5586a --- /dev/null +++ b/example/converter/alias_type_convert_with_refer/main.go @@ -0,0 +1,58 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package main + +import ( + "fmt" + + "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/util/gconv" +) + +type MyTime = *gtime.Time + +type Src struct { + A MyTime +} + +type Dst struct { + B string +} + +type SrcWrap struct { + Value Src +} + +type DstWrap struct { + Value Dst +} + +// SrcToDstConverter is custom converting function for custom type. +func SrcToDstConverter(src Src) (dst *Dst, err error) { + return &Dst{B: src.A.Format("Y-m-d")}, nil +} + +// SrcToDstConverter is custom converting function for custom type. +func main() { + // register custom converter function. + err := gconv.RegisterConverter(SrcToDstConverter) + if err != nil { + panic(err) + } + + // custom struct converting. + var src = Src{A: gtime.Now()} + dst := gconv.ConvertWithRefer(src, &Dst{}) + fmt.Println("src:", src) + fmt.Println("dst:", dst) + + // custom struct attributes converting. + var srcWrap = SrcWrap{Src{A: gtime.Now()}} + dstWrap := gconv.ConvertWithRefer(srcWrap, &DstWrap{}) + fmt.Println("srcWrap:", srcWrap) + fmt.Println("dstWrap:", dstWrap) +} diff --git a/example/converter/alias_type_scan/main.go b/example/converter/alias_type_scan/main.go new file mode 100644 index 000000000..c81d05069 --- /dev/null +++ b/example/converter/alias_type_scan/main.go @@ -0,0 +1,72 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package main + +import ( + "fmt" + + "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/util/gconv" +) + +type MyTime = *gtime.Time + +type Src struct { + A MyTime +} + +type Dst struct { + B string +} + +type SrcWrap struct { + Value Src +} + +type DstWrap struct { + Value Dst +} + +// SrcToDstConverter is custom converting function for custom type. +func SrcToDstConverter(src Src) (dst *Dst, err error) { + return &Dst{B: src.A.Format("Y-m-d")}, nil +} + +// SrcToDstConverter is custom converting function for custom type. +func main() { + // register custom converter function. + err := gconv.RegisterConverter(SrcToDstConverter) + if err != nil { + panic(err) + } + + // custom struct converting. + var ( + src = Src{A: gtime.Now()} + dst *Dst + ) + err = gconv.Scan(src, &dst) + if err != nil { + panic(err) + } + + fmt.Println("src:", src) + fmt.Println("dst:", dst) + + // custom struct attributes converting. + var ( + srcWrap = SrcWrap{Src{A: gtime.Now()}} + dstWrap *DstWrap + ) + err = gconv.Scan(srcWrap, &dstWrap) + if err != nil { + panic(err) + } + + fmt.Println("srcWrap:", srcWrap) + fmt.Println("dstWrap:", dstWrap) +} diff --git a/example/converter/struct_convert_with_refer/main.go b/example/converter/struct_convert_with_refer/main.go new file mode 100644 index 000000000..bae8b1ca2 --- /dev/null +++ b/example/converter/struct_convert_with_refer/main.go @@ -0,0 +1,54 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package main + +import ( + "fmt" + + "github.com/gogf/gf/v2/util/gconv" +) + +type Src struct { + A int +} + +type Dst struct { + B int +} + +type SrcWrap struct { + Value Src +} + +type DstWrap struct { + Value Dst +} + +// SrcToDstConverter is custom converting function for custom type. +func SrcToDstConverter(src Src) (dst *Dst, err error) { + return &Dst{B: src.A}, nil +} + +func main() { + // register custom converter function. + err := gconv.RegisterConverter(SrcToDstConverter) + if err != nil { + panic(err) + } + + // custom struct converting. + var src = Src{A: 1} + dst := gconv.ConvertWithRefer(src, Dst{}) + fmt.Println("src:", src) + fmt.Println("dst:", dst) + + // custom struct attributes converting. + var srcWrap = SrcWrap{Src{A: 1}} + dstWrap := gconv.ConvertWithRefer(srcWrap, &DstWrap{}) + fmt.Println("srcWrap:", srcWrap) + fmt.Println("dstWrap:", dstWrap) +} diff --git a/example/converter/struct_scan/main.go b/example/converter/struct_scan/main.go new file mode 100644 index 000000000..3bdc4bc3f --- /dev/null +++ b/example/converter/struct_scan/main.go @@ -0,0 +1,68 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package main + +import ( + "fmt" + + "github.com/gogf/gf/v2/util/gconv" +) + +type Src struct { + A int +} + +type Dst struct { + B int +} + +type SrcWrap struct { + Value Src +} + +type DstWrap struct { + Value Dst +} + +func SrcToDstConverter(src Src) (dst *Dst, err error) { + return &Dst{B: src.A}, nil +} + +// SrcToDstConverter is custom converting function for custom type. +func main() { + // register custom converter function. + err := gconv.RegisterConverter(SrcToDstConverter) + if err != nil { + panic(err) + } + + // custom struct converting. + var ( + src = Src{A: 1} + dst *Dst + ) + err = gconv.Scan(src, &dst) + if err != nil { + panic(err) + } + + fmt.Println("src:", src) + fmt.Println("dst:", dst) + + // custom struct attributes converting. + var ( + srcWrap = SrcWrap{Src{A: 1}} + dstWrap *DstWrap + ) + err = gconv.Scan(srcWrap, &dstWrap) + if err != nil { + panic(err) + } + + fmt.Println("srcWrap:", srcWrap) + fmt.Println("dstWrap:", dstWrap) +} diff --git a/example/httpserver/default_value/main.go b/example/httpserver/default_value/main.go index dd6c6e105..59712fa77 100644 --- a/example/httpserver/default_value/main.go +++ b/example/httpserver/default_value/main.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/httpserver/proxy/main.go b/example/httpserver/proxy/main.go index 023d423d1..c39caf0a7 100644 --- a/example/httpserver/proxy/main.go +++ b/example/httpserver/proxy/main.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/httpserver/rate/main.go b/example/httpserver/rate/main.go index 04dfeeb95..88a7c15a7 100644 --- a/example/httpserver/rate/main.go +++ b/example/httpserver/rate/main.go @@ -1,12 +1,19 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( "context" "fmt" + "golang.org/x/time/rate" + "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" - "golang.org/x/time/rate" ) type HelloReq struct { diff --git a/example/httpserver/response_with_json_array/controller.go b/example/httpserver/response_with_json_array/controller.go index 2f34a0bab..2455cfa02 100644 --- a/example/httpserver/response_with_json_array/controller.go +++ b/example/httpserver/response_with_json_array/controller.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/httpserver/response_with_json_array/main.go b/example/httpserver/response_with_json_array/main.go index 7b2de30d7..95f96cadc 100644 --- a/example/httpserver/response_with_json_array/main.go +++ b/example/httpserver/response_with_json_array/main.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/httpserver/swagger/main.go b/example/httpserver/swagger/main.go index b494c73d2..d453588d3 100644 --- a/example/httpserver/swagger/main.go +++ b/example/httpserver/swagger/main.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/nosql/redis/configuration/basic/main.go b/example/nosql/redis/configuration/basic/main.go index 39634afdd..360a7b276 100644 --- a/example/nosql/redis/configuration/basic/main.go +++ b/example/nosql/redis/configuration/basic/main.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/nosql/redis/configuration/senior/main.go b/example/nosql/redis/configuration/senior/main.go index c5d44934f..35c27816e 100644 --- a/example/nosql/redis/configuration/senior/main.go +++ b/example/nosql/redis/configuration/senior/main.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/nosql/redis/expire/main.go b/example/nosql/redis/expire/main.go index 3d29c5ac1..c3b71fef7 100644 --- a/example/nosql/redis/expire/main.go +++ b/example/nosql/redis/expire/main.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/nosql/redis/hmset/main.go b/example/nosql/redis/hmset/main.go index e00f0c5f2..c417e58d4 100644 --- a/example/nosql/redis/hmset/main.go +++ b/example/nosql/redis/hmset/main.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/nosql/redis/hset/main.go b/example/nosql/redis/hset/main.go index 8f7e518fa..fc7889b45 100644 --- a/example/nosql/redis/hset/main.go +++ b/example/nosql/redis/hset/main.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/nosql/redis/key-value/main.go b/example/nosql/redis/key-value/main.go index 39634afdd..360a7b276 100644 --- a/example/nosql/redis/key-value/main.go +++ b/example/nosql/redis/key-value/main.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/os/log/rotate/main.go b/example/os/log/rotate/main.go index 5a3fcbf2f..72e9a8cc1 100644 --- a/example/os/log/rotate/main.go +++ b/example/os/log/rotate/main.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/pack/main.go b/example/pack/main.go index 28256030d..6190273ad 100644 --- a/example/pack/main.go +++ b/example/pack/main.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/pack/packed/paked.go b/example/pack/packed/paked.go index e20ab1e95..4a9a95856 100644 --- a/example/pack/packed/paked.go +++ b/example/pack/packed/paked.go @@ -1 +1,7 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package packed diff --git a/example/registry/etcd/http/client/client.go b/example/registry/etcd/http/client/client.go index e5675b829..cc9f2cb80 100644 --- a/example/registry/etcd/http/client/client.go +++ b/example/registry/etcd/http/client/client.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/registry/etcd/http/server/server.go b/example/registry/etcd/http/server/server.go index 355d9cbb0..3e5772441 100644 --- a/example/registry/etcd/http/server/server.go +++ b/example/registry/etcd/http/server/server.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/registry/file/client/client.go b/example/registry/file/client/client.go index 1f32cc3eb..ca63e2ad3 100644 --- a/example/registry/file/client/client.go +++ b/example/registry/file/client/client.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/registry/file/server/server.go b/example/registry/file/server/server.go index 480d57cf7..ef68159bd 100644 --- a/example/registry/file/server/server.go +++ b/example/registry/file/server/server.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/rpc/grpcx/rawgrpc/client/client.go b/example/rpc/grpcx/rawgrpc/client/client.go index 5a01ee751..b9557d483 100644 --- a/example/rpc/grpcx/rawgrpc/client/client.go +++ b/example/rpc/grpcx/rawgrpc/client/client.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/rpc/grpcx/rawgrpc/server/server.go b/example/rpc/grpcx/rawgrpc/server/server.go index 5ddf4991a..20edb56a6 100644 --- a/example/rpc/grpcx/rawgrpc/server/server.go +++ b/example/rpc/grpcx/rawgrpc/server/server.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/tcp/server/proxy/main.go b/example/tcp/server/proxy/main.go index 13d44321e..92d617107 100644 --- a/example/tcp/server/proxy/main.go +++ b/example/tcp/server/proxy/main.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/trace/grpc_with_db/client/client.go b/example/trace/grpc_with_db/client/client.go index c1b4fcb11..aa7a6dd2b 100644 --- a/example/trace/grpc_with_db/client/client.go +++ b/example/trace/grpc_with_db/client/client.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/trace/grpc_with_db/server/server.go b/example/trace/grpc_with_db/server/server.go index 0a55f2e6b..a3e6615a5 100644 --- a/example/trace/grpc_with_db/server/server.go +++ b/example/trace/grpc_with_db/server/server.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/trace/http/client/client.go b/example/trace/http/client/client.go index 254f47c08..84abb05fd 100644 --- a/example/trace/http/client/client.go +++ b/example/trace/http/client/client.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/trace/http/server/server.go b/example/trace/http/server/server.go index 2e734ace3..975dc27e7 100644 --- a/example/trace/http/server/server.go +++ b/example/trace/http/server/server.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/trace/http_with_db/client/client.go b/example/trace/http_with_db/client/client.go index 676d4de9b..826744382 100644 --- a/example/trace/http_with_db/client/client.go +++ b/example/trace/http_with_db/client/client.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/trace/http_with_db/server/server.go b/example/trace/http_with_db/server/server.go index 7c4139a50..f754f0ea5 100644 --- a/example/trace/http_with_db/server/server.go +++ b/example/trace/http_with_db/server/server.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/trace/inprocess/main.go b/example/trace/inprocess/main.go index b792094bb..a6b3849f0 100644 --- a/example/trace/inprocess/main.go +++ b/example/trace/inprocess/main.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/trace/processes/gcmd/main.go b/example/trace/processes/gcmd/main.go index 4f24898e6..8bf4faaf1 100644 --- a/example/trace/processes/gcmd/main.go +++ b/example/trace/processes/gcmd/main.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/trace/processes/gcmd/sub/sub.go b/example/trace/processes/gcmd/sub/sub.go index 69f451e70..63009235d 100644 --- a/example/trace/processes/gcmd/sub/sub.go +++ b/example/trace/processes/gcmd/sub/sub.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/trace/processes/gproc/main.go b/example/trace/processes/gproc/main.go index ba334cfa0..f408f3990 100644 --- a/example/trace/processes/gproc/main.go +++ b/example/trace/processes/gproc/main.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/example/trace/processes/gproc/sub/sub.go b/example/trace/processes/gproc/sub/sub.go index cd0238a87..b928dda75 100644 --- a/example/trace/processes/gproc/sub/sub.go +++ b/example/trace/processes/gproc/sub/sub.go @@ -1,3 +1,9 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + package main import ( diff --git a/util/gconv/gconv_convert.go b/util/gconv/gconv_convert.go index f13b05272..b3f264f1b 100644 --- a/util/gconv/gconv_convert.go +++ b/util/gconv/gconv_convert.go @@ -280,6 +280,17 @@ func doConvert(in doConvertInput) (convertedValue interface{}) { } else { referReflectValue = reflect.ValueOf(in.ReferValue) } + var fromReflectValue reflect.Value + if v, ok := in.FromValue.(reflect.Value); ok { + fromReflectValue = v + } else { + fromReflectValue = reflect.ValueOf(in.FromValue) + } + + // custom converter. + if dstReflectValue, ok, _ := callCustomConverterWithRefer(fromReflectValue, referReflectValue); ok { + return dstReflectValue.Interface() + } defer func() { if recover() != nil { diff --git a/util/gconv/gconv_converter.go b/util/gconv/gconv_converter.go index a5d7bb72f..0f5615677 100644 --- a/util/gconv/gconv_converter.go +++ b/util/gconv/gconv_converter.go @@ -24,7 +24,7 @@ var customConverters = make(map[converterInType]map[converterOutType]converterFu // RegisterConverter to register custom converter. // It must be registered before you use this custom converting feature. -// It is suggested to do it in boot. +// It is suggested to do it in boot procedure of the process. // // Note: // 1. The parameter `fn` must be defined as pattern `func(T1) (T2, error)`. @@ -40,7 +40,7 @@ func RegisterConverter(fn interface{}) (err error) { !fnReflectType.Out(1).Implements(errType) { err = gerror.NewCodef( gcode.CodeInvalidParameter, - "parameter must be type of function and defined as pattern `func(T1) (T2, error)`, but defined as `%s`", + "parameter must be type of converter function and defined as pattern `func(T1) (T2, error)`, but defined as `%s`", fnReflectType.String(), ) return @@ -54,16 +54,16 @@ func RegisterConverter(fn interface{}) (err error) { if inType.Kind() == reflect.Pointer { err = gerror.NewCodef( gcode.CodeInvalidParameter, - "invalid input parameter type `%s`: should not be type of pointer", - inType.String(), + "invalid converter function `%s`: invalid input parameter type `%s`, should not be type of pointer", + fnReflectType.String(), inType.String(), ) return } if outType.Kind() != reflect.Pointer { err = gerror.NewCodef( gcode.CodeInvalidParameter, - "invalid output parameter type `%s`: should be type of pointer", - outType.String(), + "invalid converter function `%s`: invalid output parameter type `%s` should be type of pointer", + fnReflectType.String(), outType.String(), ) return } @@ -85,39 +85,69 @@ func RegisterConverter(fn interface{}) (err error) { return } -// callCustomConverter call the custom converter. It will try some possible type. -func callCustomConverter(srcReflectValue reflect.Value, dstReflectValue reflect.Value) (converted bool, err error) { +func getRegisteredConverterFuncAndSrcType( + srcReflectValue, dstReflectValueForRefer reflect.Value, +) (f converterFunc, srcType reflect.Type, ok bool) { if len(customConverters) == 0 { - return false, nil + return reflect.Value{}, nil, false } - var ( - ok bool - srcType = srcReflectValue.Type() - ) + srcType = srcReflectValue.Type() for srcType.Kind() == reflect.Pointer { srcType = srcType.Elem() } - var ( - registeredOutTypeMap map[converterOutType]converterFunc - registeredConverterFunc converterFunc - ) + var registeredOutTypeMap map[converterOutType]converterFunc // firstly, it searches the map by input parameter type. registeredOutTypeMap, ok = customConverters[srcType] if !ok { - return false, nil + return reflect.Value{}, nil, false } - var dstType = dstReflectValue.Type() - if dstType.Kind() == reflect.Pointer && dstReflectValue.Elem().Kind() == reflect.Pointer { - dstType = dstReflectValue.Elem().Type() - } else if dstType.Kind() != reflect.Pointer && dstReflectValue.CanAddr() { - dstType = dstReflectValue.Addr().Type() + var dstType = dstReflectValueForRefer.Type() + if dstType.Kind() == reflect.Pointer { + // Might be **struct, which is support as designed. + if dstType.Elem().Kind() == reflect.Pointer { + dstType = dstType.Elem() + } + } else if dstReflectValueForRefer.IsValid() && dstReflectValueForRefer.CanAddr() { + dstType = dstReflectValueForRefer.Addr().Type() + } else { + dstType = reflect.PointerTo(dstType) } // secondly, it searches the input parameter type map // and finds the result converter function by the output parameter type. - registeredConverterFunc, ok = registeredOutTypeMap[dstType] + f, ok = registeredOutTypeMap[dstType] + if !ok { + return reflect.Value{}, nil, false + } + return +} + +func callCustomConverterWithRefer( + srcReflectValue, referReflectValue reflect.Value, +) (dstReflectValue reflect.Value, converted bool, err error) { + registeredConverterFunc, srcType, ok := getRegisteredConverterFuncAndSrcType(srcReflectValue, referReflectValue) + if !ok { + return reflect.Value{}, false, nil + } + dstReflectValue = reflect.New(referReflectValue.Type()).Elem() + converted, err = doCallCustomConverter(srcReflectValue, dstReflectValue, registeredConverterFunc, srcType) + return +} + +// callCustomConverter call the custom converter. It will try some possible type. +func callCustomConverter(srcReflectValue, dstReflectValue reflect.Value) (converted bool, err error) { + registeredConverterFunc, srcType, ok := getRegisteredConverterFuncAndSrcType(srcReflectValue, dstReflectValue) if !ok { return false, nil } + return doCallCustomConverter(srcReflectValue, dstReflectValue, registeredConverterFunc, srcType) +} + +func doCallCustomConverter( + srcReflectValue reflect.Value, + dstReflectValue reflect.Value, + registeredConverterFunc converterFunc, + srcType reflect.Type, +) (converted bool, err error) { // Converter function calling. for srcReflectValue.Type() != srcType { srcReflectValue = srcReflectValue.Elem() diff --git a/util/gconv/gconv_z_unit_converter_test.go b/util/gconv/gconv_z_unit_converter_test.go index d9b39b14e..29c2b7cc7 100644 --- a/util/gconv/gconv_z_unit_converter_test.go +++ b/util/gconv/gconv_z_unit_converter_test.go @@ -16,6 +16,52 @@ import ( "github.com/gogf/gf/v2/util/gconv" ) +func TestConverter_ConvertWithRefer(t *testing.T) { + type tA struct { + Val int + } + + type tB struct { + Val1 int32 + Val2 string + } + + gtest.C(t, func(t *gtest.T) { + err := gconv.RegisterConverter(func(a tA) (b *tB, err error) { + b = &tB{ + Val1: int32(a.Val), + Val2: "abcd", + } + return + }) + t.AssertNil(err) + }) + + gtest.C(t, func(t *gtest.T) { + a := &tA{ + Val: 1, + } + var b tB + result := gconv.ConvertWithRefer(a, &b) + t.Assert(result.(*tB), &tB{ + Val1: 1, + Val2: "abcd", + }) + }) + + gtest.C(t, func(t *gtest.T) { + a := &tA{ + Val: 1, + } + var b tB + result := gconv.ConvertWithRefer(a, b) + t.Assert(result.(tB), tB{ + Val1: 1, + Val2: "abcd", + }) + }) +} + func TestConverter_Struct(t *testing.T) { type tA struct { Val int