mirror of
https://github.com/guonaihong/gout
synced 2025-12-24 12:58:00 +08:00
完成该功能 (#308)
This commit is contained in:
@@ -51,7 +51,7 @@ func BytesToString(b []byte) string {
|
||||
// StringToBytes 没有内存开销的转换
|
||||
func StringToBytes(s string) (b []byte) {
|
||||
bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
|
||||
sh := *(*reflect.StringHeader)(unsafe.Pointer(&s))
|
||||
sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
|
||||
bh.Data = sh.Data
|
||||
bh.Len = sh.Len
|
||||
bh.Cap = sh.Len
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/guonaihong/gout/core"
|
||||
)
|
||||
|
||||
// ErrUnsupported Unsupported type error returned
|
||||
@@ -41,10 +43,12 @@ func Encode(in interface{}, a Adder) error {
|
||||
case reflect.Map:
|
||||
iter := v.MapRange()
|
||||
for iter.Next() {
|
||||
if err := a.Add(valToStr(iter.Key(), emptyField), iter.Value(), emptyField); err != nil {
|
||||
keyName := valToStr(iter.Key(), emptyField)
|
||||
if err := setMoreTypes(iter.Value(), emptyField, a, keyName); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
case reflect.Struct:
|
||||
@@ -64,7 +68,8 @@ func Encode(in interface{}, a Adder) error {
|
||||
|
||||
for i, l := 0, v.Len(); i < l; i += 2 {
|
||||
|
||||
if err := a.Add(valToStr(v.Index(i), emptyField), v.Index(i+1), emptyField); err != nil {
|
||||
keyName := valToStr(v.Index(i), emptyField)
|
||||
if err := setMoreTypes(v.Index(i+1), emptyField, a, keyName); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -131,6 +136,27 @@ func valToStr(v reflect.Value, sf reflect.StructField) string {
|
||||
return fmt.Sprint(v.Interface())
|
||||
}
|
||||
|
||||
func setMoreTypes(val reflect.Value, sf reflect.StructField, a Adder, tagName string) error {
|
||||
switch val.Interface().(type) {
|
||||
case string, []byte, core.FormMem, core.FormFile:
|
||||
default:
|
||||
if val.Kind() == reflect.Interface {
|
||||
val = val.Elem()
|
||||
}
|
||||
|
||||
switch val.Kind() {
|
||||
case reflect.Slice, reflect.Array:
|
||||
for i, l := 0, val.Len(); i < l; i++ {
|
||||
if err := a.Add(tagName, val.Index(i), sf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return a.Add(tagName, val, sf)
|
||||
}
|
||||
|
||||
func parseTagAndSet(val reflect.Value, sf reflect.StructField, a Adder) error {
|
||||
|
||||
tagName := sf.Tag.Get(a.Name())
|
||||
@@ -148,7 +174,7 @@ func parseTagAndSet(val reflect.Value, sf reflect.StructField, a Adder) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
return a.Add(tagName, val, sf)
|
||||
return setMoreTypes(val, sf, a, tagName)
|
||||
}
|
||||
|
||||
func encode(val reflect.Value, sf reflect.StructField, a Adder) error {
|
||||
|
||||
@@ -79,13 +79,19 @@ func checkForm(t *testing.T, boundary string, out *bytes.Buffer, caseID int, nee
|
||||
}
|
||||
|
||||
if needCheckFileName && p.FileName() != "" {
|
||||
assert.Equal(t, p.FileName(), "voice.pcm", fmt.Sprintf("-->test case id:%d", caseID))
|
||||
b := assert.Equal(t, p.FileName(), "voice.pcm", fmt.Sprintf("-->test case id:%d", caseID))
|
||||
if !b {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// key
|
||||
key := p.FormName()
|
||||
if key == "voice" || key == "voice2" {
|
||||
assert.NotEqual(t, len(p.FileName()), 0, fmt.Sprintf("filename is empty:%d", caseID))
|
||||
b := assert.NotEqual(t, len(p.FileName()), 0, fmt.Sprintf("filename is empty:%d", caseID))
|
||||
if !b {
|
||||
return
|
||||
}
|
||||
}
|
||||
// slurp is value
|
||||
v := need[key]
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
package encode
|
||||
|
||||
import (
|
||||
"github.com/guonaihong/gout/setting"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/guonaihong/gout/core"
|
||||
"github.com/guonaihong/gout/setting"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// 测试[]string类型
|
||||
func TestQueryStringSlice(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", "/", nil)
|
||||
|
||||
@@ -21,6 +24,7 @@ func TestQueryStringSlice(t *testing.T) {
|
||||
assert.Equal(t, q.End(), "q1=v1&q2=v2&q3=v3")
|
||||
}
|
||||
|
||||
// 测试map[string]interface{}
|
||||
func TestQueryMap(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", "/", nil)
|
||||
|
||||
@@ -41,6 +45,7 @@ type testQuery struct {
|
||||
Q5 time.Time `query:"q5" time_format:"unixNano"`
|
||||
}
|
||||
|
||||
// 测试结构体
|
||||
func TestQueryStruct(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", "/", nil)
|
||||
|
||||
@@ -55,3 +60,29 @@ func TestQueryStruct(t *testing.T) {
|
||||
|
||||
assert.Equal(t, q.End(), "q1=v1&q2=v2&q3=v3&q4="+strconv.FormatInt(unixTime.Unix(), 10)+"&q5="+strconv.FormatInt(unixNano.UnixNano(), 10))
|
||||
}
|
||||
|
||||
// 结构体带[]string
|
||||
type queryWithSlice struct {
|
||||
A []string `query:"a"`
|
||||
B string `query:"b"`
|
||||
}
|
||||
|
||||
func TestQueryFieldWithSlice(t *testing.T) {
|
||||
|
||||
for _, v := range []interface{}{
|
||||
queryWithSlice{A: []string{"1", "2", "3"}, B: "b"},
|
||||
core.H{"a": []string{"1", "2", "3"}, "b": "b"},
|
||||
core.A{"a", []string{"1", "2", "3"}, "b", "b"},
|
||||
} {
|
||||
|
||||
req, _ := http.NewRequest("GET", "/", nil)
|
||||
|
||||
q := NewQueryEncode(req, setting.Setting{})
|
||||
|
||||
err := Encode(v, q)
|
||||
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, q.End(), "a=1&a=2&a=3&b=b")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,11 +6,49 @@ import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/guonaihong/gout/dataflow"
|
||||
)
|
||||
|
||||
type queryWithSlice struct {
|
||||
A []string `query:"a" form:"a"`
|
||||
B string `query:"b" form:"b"`
|
||||
}
|
||||
|
||||
func testQueryWithSliceServer(t *testing.T) *httptest.Server {
|
||||
|
||||
r := gin.New()
|
||||
|
||||
need := queryWithSlice{A: []string{"1", "2", "3"}, B: "b"}
|
||||
r.GET("/query", func(c *gin.Context) {
|
||||
|
||||
got := queryWithSlice{}
|
||||
err := c.ShouldBindQuery(&got)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, need, got)
|
||||
})
|
||||
|
||||
return httptest.NewServer(http.HandlerFunc(r.ServeHTTP))
|
||||
}
|
||||
|
||||
// 测试query接口,带slice的情况
|
||||
func TestQuery_slice(t *testing.T) {
|
||||
|
||||
ts := testQueryWithSliceServer(t)
|
||||
|
||||
for _, v := range []interface{}{
|
||||
queryWithSlice{A: []string{"1", "2", "3"}, B: "b"},
|
||||
H{"a": []string{"1", "2", "3"}, "b": "b"},
|
||||
A{"a", []string{"1", "2", "3"}, "b", "b"},
|
||||
} {
|
||||
|
||||
err := GET(ts.URL + "/query").Debug(true).SetQuery(v).Do()
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestQuery_NotIgnoreEmpty(t *testing.T) {
|
||||
|
||||
total := int32(0)
|
||||
|
||||
Reference in New Issue
Block a user