improve converter feature for package gconv (#3211)

This commit is contained in:
John Guo 2024-01-22 21:52:54 +08:00 committed by GitHub
parent 383937fe69
commit ba39323d30
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
49 changed files with 625 additions and 30 deletions

View File

@ -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 package boot
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package boot
import ( import (
consul "github.com/gogf/gf/contrib/config/consul/v2" 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/consul/api"
"github.com/hashicorp/go-cleanhttp" "github.com/hashicorp/go-cleanhttp"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
) )
func init() { func init() {

View File

@ -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 package main
import ( import (

View File

@ -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 package boot
import ( import (

View File

@ -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 package boot
import ( import (
"k8s.io/client-go/kubernetes"
"github.com/gogf/gf/contrib/config/kubecm/v2" "github.com/gogf/gf/contrib/config/kubecm/v2"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/os/gctx"
"k8s.io/client-go/kubernetes"
) )
const ( const (

View File

@ -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 package main
import ( import (

View File

@ -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 package boot
import ( 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/contrib/config/nacos/v2"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx" "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() { func init() {

View File

@ -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 package nacos
import ( import (

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (
"context" "context"
"fmt" "fmt"
"golang.org/x/time/rate"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/net/ghttp"
"golang.org/x/time/rate"
) )
type HelloReq struct { type HelloReq struct {

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package packed

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -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 package main
import ( import (

View File

@ -280,6 +280,17 @@ func doConvert(in doConvertInput) (convertedValue interface{}) {
} else { } else {
referReflectValue = reflect.ValueOf(in.ReferValue) 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() { defer func() {
if recover() != nil { if recover() != nil {

View File

@ -24,7 +24,7 @@ var customConverters = make(map[converterInType]map[converterOutType]converterFu
// RegisterConverter to register custom converter. // RegisterConverter to register custom converter.
// It must be registered before you use this custom converting feature. // 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: // Note:
// 1. The parameter `fn` must be defined as pattern `func(T1) (T2, error)`. // 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) { !fnReflectType.Out(1).Implements(errType) {
err = gerror.NewCodef( err = gerror.NewCodef(
gcode.CodeInvalidParameter, 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(), fnReflectType.String(),
) )
return return
@ -54,16 +54,16 @@ func RegisterConverter(fn interface{}) (err error) {
if inType.Kind() == reflect.Pointer { if inType.Kind() == reflect.Pointer {
err = gerror.NewCodef( err = gerror.NewCodef(
gcode.CodeInvalidParameter, gcode.CodeInvalidParameter,
"invalid input parameter type `%s`: should not be type of pointer", "invalid converter function `%s`: invalid input parameter type `%s`, should not be type of pointer",
inType.String(), fnReflectType.String(), inType.String(),
) )
return return
} }
if outType.Kind() != reflect.Pointer { if outType.Kind() != reflect.Pointer {
err = gerror.NewCodef( err = gerror.NewCodef(
gcode.CodeInvalidParameter, gcode.CodeInvalidParameter,
"invalid output parameter type `%s`: should be type of pointer", "invalid converter function `%s`: invalid output parameter type `%s` should be type of pointer",
outType.String(), fnReflectType.String(), outType.String(),
) )
return return
} }
@ -85,39 +85,69 @@ func RegisterConverter(fn interface{}) (err error) {
return return
} }
// callCustomConverter call the custom converter. It will try some possible type. func getRegisteredConverterFuncAndSrcType(
func callCustomConverter(srcReflectValue reflect.Value, dstReflectValue reflect.Value) (converted bool, err error) { srcReflectValue, dstReflectValueForRefer reflect.Value,
) (f converterFunc, srcType reflect.Type, ok bool) {
if len(customConverters) == 0 { if len(customConverters) == 0 {
return false, nil return reflect.Value{}, nil, false
} }
var ( srcType = srcReflectValue.Type()
ok bool
srcType = srcReflectValue.Type()
)
for srcType.Kind() == reflect.Pointer { for srcType.Kind() == reflect.Pointer {
srcType = srcType.Elem() srcType = srcType.Elem()
} }
var ( var registeredOutTypeMap map[converterOutType]converterFunc
registeredOutTypeMap map[converterOutType]converterFunc
registeredConverterFunc converterFunc
)
// firstly, it searches the map by input parameter type. // firstly, it searches the map by input parameter type.
registeredOutTypeMap, ok = customConverters[srcType] registeredOutTypeMap, ok = customConverters[srcType]
if !ok { if !ok {
return false, nil return reflect.Value{}, nil, false
} }
var dstType = dstReflectValue.Type() var dstType = dstReflectValueForRefer.Type()
if dstType.Kind() == reflect.Pointer && dstReflectValue.Elem().Kind() == reflect.Pointer { if dstType.Kind() == reflect.Pointer {
dstType = dstReflectValue.Elem().Type() // Might be **struct, which is support as designed.
} else if dstType.Kind() != reflect.Pointer && dstReflectValue.CanAddr() { if dstType.Elem().Kind() == reflect.Pointer {
dstType = dstReflectValue.Addr().Type() 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 // secondly, it searches the input parameter type map
// and finds the result converter function by the output parameter type. // 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 { if !ok {
return false, nil 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. // Converter function calling.
for srcReflectValue.Type() != srcType { for srcReflectValue.Type() != srcType {
srcReflectValue = srcReflectValue.Elem() srcReflectValue = srcReflectValue.Elem()

View File

@ -16,6 +16,52 @@ import (
"github.com/gogf/gf/v2/util/gconv" "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) { func TestConverter_Struct(t *testing.T) {
type tA struct { type tA struct {
Val int Val int