Repository: gogf/gf (Go)

Issue:
util/gconv: After conversion, the interface{} type becomes *interface {}
### Go version

go version go1.18 windows/amd64

### GoFrame version

v2.7.2

### Can this bug be reproduced with the latest release?

Option Yes

### What did you do?

``` go
package main

import (
	"fmt"

	"github.com/gogf/gf/v2/util/gconv"
)

func main() {
	req := map[string]any{
		"id": "123",
		"doc": map[string]any{
			"craft": nil,
		},
		"fields": []string{"_id"},
	}

	var args *UpdateByIdReq
	err := gconv.Struct(req, &args)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%T", args.Doc["craft"])
}

type UpdateByIdReq struct {
	Id     string                 `json:"id" v:"required|length:24,24#id长度错误"`
	Doc    map[string]interface{} `json:"doc" v:"required"`
	Fields []string               `json:"fields"`
}

```

### What did you see happen?

输出 `*interface {}`

### What did you expect to see?

应该是 `interface{}`


Discussion:
```go
package main

import (
	"fmt"

	"github.com/gogf/gf/v2/util/gconv"
)

func main() {
	dataMap := map[string]any{
		"doc": map[string]any{
			"craft": nil,
		},
	}

	var args *Data
	err := gconv.Struct(dataMap, &args)
	if err != nil {
		panic(err)
	}
	fmt.Printf("args: %T\n", args.Doc["craft"])
	fmt.Printf("dataMap: %T\n", dataMap["doc"].(map[string]any)["craft"])
}

type Data struct {
	Doc map[string]interface{} `json:"doc"`
}
```

Shouldn't your expected output here be `nil`?
In Go, when you assign nil to a variable of type interface{}, that variable is actually an interface{} pointer to nil.
So, when you try to print ARGS. Doc["craft"], it appears as *interface{}, indicating that the value is nil, and the interface{} type holds a pointer to nil.
``` go
func main() {
	req := map[string]any{
		"id": "123",
		"doc": map[string]any{
			"craft": nil,
		},
		"fields": []string{"_id"},
	}

	var args *UpdateByIdReq
	err := gconv.Struct(req, &args)
	if err != nil {
		panic(err)
	}
	var abc interface{}
	abc = nil
	fmt.Printf("%T, %T", args.Doc["craft"], abc)
}
```
output  
```
 *interface {}, <nil>
```


If I check args.Doc["craft"] == nil here, it returns false. Isn't this counterintuitive?

You should expect the output to be `<nil>`, right?
> 您应该期望输出是 ，对吧？`<nil>`

yes
 
> Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑‍🤝‍🧑👫🧑🏿‍🤝‍🧑🏻👩🏾‍🤝‍👨🏿👬🏿         
----    
> You should expect the output to be , right? `<nil>`

yes  
      
my fix should be correct
> my fix should be correct

Is this a bug?
yes
> In Go, when you assign nil to a variable of type interface{}, that variable is actually an interface{} pointer to nil. So, when you try to print ARGS. Doc["craft"], it appears as *interface{}, indicating that the value is nil, and the interface{} type holds a pointer to nil.

Thank you. My expected type is `<nil>`, so that it's easier to make subsequent checks, such as `value == nil`.
> yes

Thank you



Patch:
diff --git a/util/gconv/gconv_convert.go b/util/gconv/gconv_convert.go
index 2ff5b1a94a4..49bb32b1fd3 100644
--- a/util/gconv/gconv_convert.go
+++ b/util/gconv/gconv_convert.go
@@ -266,10 +266,10 @@ func doConvert(in doConvertInput) (convertedValue interface{}) {
 	case "map[string]string":
 		return MapStrStr(in.FromValue)
 
-	case "map[string]interface{}":
+	case "map[string]interface {}":
 		return Map(in.FromValue)
 
-	case "[]map[string]interface{}":
+	case "[]map[string]interface {}":
 		return Maps(in.FromValue)
 
 	case "RawMessage", "json.RawMessage":


Test patch:
diff --git a/util/gconv/gconv_z_unit_issue_test.go b/util/gconv/gconv_z_unit_issue_test.go
index e5f5e7a4473..7fc0f161e56 100644
--- a/util/gconv/gconv_z_unit_issue_test.go
+++ b/util/gconv/gconv_z_unit_issue_test.go
@@ -7,6 +7,7 @@
 package gconv_test
 
 import (
+	"fmt"
 	"math/big"
 	"testing"
 	"time"
@@ -366,3 +367,23 @@ func TestIssue3006(t *testing.T) {
 		t.Assert(ff.Val3["val3"], []byte(`{"hello":"world"}`))
 	})
 }
+
+// https://github.com/gogf/gf/issues/3731
+func TestIssue3731(t *testing.T) {
+	type Data struct {
+		Doc map[string]interface{} `json:"doc"`
+	}
+
+	gtest.C(t, func(t *gtest.T) {
+		dataMap := map[string]any{
+			"doc": map[string]any{
+				"craft": nil,
+			},
+		}
+
+		var args Data
+		err := gconv.Struct(dataMap, &args)
+		t.AssertNil(err)
+		t.AssertEQ("<nil>", fmt.Sprintf("%T", args.Doc["craft"]))
+	})
+}