diff --git a/container/gmap/gmap_hash_any_any_map.go b/container/gmap/gmap_hash_any_any_map.go index f6abe77d7..e51da00d1 100644 --- a/container/gmap/gmap_hash_any_any_map.go +++ b/container/gmap/gmap_hash_any_any_map.go @@ -265,25 +265,25 @@ func (m *AnyAnyMap) GetOrSetFuncLock(key interface{}, f func() interface{}) inte // GetVar returns a Var with the value by given . // The returned Var is un-concurrent safe. -func (m *AnyAnyMap) GetVar(key interface{}) *gvar.Var { +func (m *AnyAnyMap) GetVar(key interface{}) gvar.Var { return gvar.New(m.Get(key)) } // GetVarOrSet returns a Var with result from GetVarOrSet. // The returned Var is un-concurrent safe. -func (m *AnyAnyMap) GetVarOrSet(key interface{}, value interface{}) *gvar.Var { +func (m *AnyAnyMap) GetVarOrSet(key interface{}, value interface{}) gvar.Var { return gvar.New(m.GetOrSet(key, value)) } // GetVarOrSetFunc returns a Var with result from GetOrSetFunc. // The returned Var is un-concurrent safe. -func (m *AnyAnyMap) GetVarOrSetFunc(key interface{}, f func() interface{}) *gvar.Var { +func (m *AnyAnyMap) GetVarOrSetFunc(key interface{}, f func() interface{}) gvar.Var { return gvar.New(m.GetOrSetFunc(key, f)) } // GetVarOrSetFuncLock returns a Var with result from GetOrSetFuncLock. // The returned Var is un-concurrent safe. -func (m *AnyAnyMap) GetVarOrSetFuncLock(key interface{}, f func() interface{}) *gvar.Var { +func (m *AnyAnyMap) GetVarOrSetFuncLock(key interface{}, f func() interface{}) gvar.Var { return gvar.New(m.GetOrSetFuncLock(key, f)) } diff --git a/container/gmap/gmap_hash_int_any_map.go b/container/gmap/gmap_hash_int_any_map.go index a4a155770..4b4b93520 100644 --- a/container/gmap/gmap_hash_int_any_map.go +++ b/container/gmap/gmap_hash_int_any_map.go @@ -263,25 +263,25 @@ func (m *IntAnyMap) GetOrSetFuncLock(key int, f func() interface{}) interface{} // GetVar returns a Var with the value by given . // The returned Var is un-concurrent safe. -func (m *IntAnyMap) GetVar(key int) *gvar.Var { +func (m *IntAnyMap) GetVar(key int) gvar.Var { return gvar.New(m.Get(key)) } // GetVarOrSet returns a Var with result from GetVarOrSet. // The returned Var is un-concurrent safe. -func (m *IntAnyMap) GetVarOrSet(key int, value interface{}) *gvar.Var { +func (m *IntAnyMap) GetVarOrSet(key int, value interface{}) gvar.Var { return gvar.New(m.GetOrSet(key, value)) } // GetVarOrSetFunc returns a Var with result from GetOrSetFunc. // The returned Var is un-concurrent safe. -func (m *IntAnyMap) GetVarOrSetFunc(key int, f func() interface{}) *gvar.Var { +func (m *IntAnyMap) GetVarOrSetFunc(key int, f func() interface{}) gvar.Var { return gvar.New(m.GetOrSetFunc(key, f)) } // GetVarOrSetFuncLock returns a Var with result from GetOrSetFuncLock. // The returned Var is un-concurrent safe. -func (m *IntAnyMap) GetVarOrSetFuncLock(key int, f func() interface{}) *gvar.Var { +func (m *IntAnyMap) GetVarOrSetFuncLock(key int, f func() interface{}) gvar.Var { return gvar.New(m.GetOrSetFuncLock(key, f)) } diff --git a/container/gmap/gmap_hash_str_any_map.go b/container/gmap/gmap_hash_str_any_map.go index 906537809..b5cd53ba1 100644 --- a/container/gmap/gmap_hash_str_any_map.go +++ b/container/gmap/gmap_hash_str_any_map.go @@ -259,25 +259,25 @@ func (m *StrAnyMap) GetOrSetFuncLock(key string, f func() interface{}) interface // GetVar returns a Var with the value by given . // The returned Var is un-concurrent safe. -func (m *StrAnyMap) GetVar(key string) *gvar.Var { +func (m *StrAnyMap) GetVar(key string) gvar.Var { return gvar.New(m.Get(key)) } // GetVarOrSet returns a Var with result from GetVarOrSet. // The returned Var is un-concurrent safe. -func (m *StrAnyMap) GetVarOrSet(key string, value interface{}) *gvar.Var { +func (m *StrAnyMap) GetVarOrSet(key string, value interface{}) gvar.Var { return gvar.New(m.GetOrSet(key, value)) } // GetVarOrSetFunc returns a Var with result from GetOrSetFunc. // The returned Var is un-concurrent safe. -func (m *StrAnyMap) GetVarOrSetFunc(key string, f func() interface{}) *gvar.Var { +func (m *StrAnyMap) GetVarOrSetFunc(key string, f func() interface{}) gvar.Var { return gvar.New(m.GetOrSetFunc(key, f)) } // GetVarOrSetFuncLock returns a Var with result from GetOrSetFuncLock. // The returned Var is un-concurrent safe. -func (m *StrAnyMap) GetVarOrSetFuncLock(key string, f func() interface{}) *gvar.Var { +func (m *StrAnyMap) GetVarOrSetFuncLock(key string, f func() interface{}) gvar.Var { return gvar.New(m.GetOrSetFuncLock(key, f)) } diff --git a/container/gmap/gmap_list_map.go b/container/gmap/gmap_list_map.go index 9a6e97ae2..0e6f5f6de 100644 --- a/container/gmap/gmap_list_map.go +++ b/container/gmap/gmap_list_map.go @@ -332,25 +332,25 @@ func (m *ListMap) GetOrSetFuncLock(key interface{}, f func() interface{}) interf // GetVar returns a Var with the value by given . // The returned Var is un-concurrent safe. -func (m *ListMap) GetVar(key interface{}) *gvar.Var { +func (m *ListMap) GetVar(key interface{}) gvar.Var { return gvar.New(m.Get(key)) } // GetVarOrSet returns a Var with result from GetVarOrSet. // The returned Var is un-concurrent safe. -func (m *ListMap) GetVarOrSet(key interface{}, value interface{}) *gvar.Var { +func (m *ListMap) GetVarOrSet(key interface{}, value interface{}) gvar.Var { return gvar.New(m.GetOrSet(key, value)) } // GetVarOrSetFunc returns a Var with result from GetOrSetFunc. // The returned Var is un-concurrent safe. -func (m *ListMap) GetVarOrSetFunc(key interface{}, f func() interface{}) *gvar.Var { +func (m *ListMap) GetVarOrSetFunc(key interface{}, f func() interface{}) gvar.Var { return gvar.New(m.GetOrSetFunc(key, f)) } // GetVarOrSetFuncLock returns a Var with result from GetOrSetFuncLock. // The returned Var is un-concurrent safe. -func (m *ListMap) GetVarOrSetFuncLock(key interface{}, f func() interface{}) *gvar.Var { +func (m *ListMap) GetVarOrSetFuncLock(key interface{}, f func() interface{}) gvar.Var { return gvar.New(m.GetOrSetFuncLock(key, f)) } diff --git a/container/gtree/gtree_avltree.go b/container/gtree/gtree_avltree.go index aa195aa1c..48b0efb2f 100644 --- a/container/gtree/gtree_avltree.go +++ b/container/gtree/gtree_avltree.go @@ -173,25 +173,25 @@ func (tree *AVLTree) GetOrSetFuncLock(key interface{}, f func() interface{}) int // GetVar returns a gvar.Var with the value by given . // The returned gvar.Var is un-concurrent safe. -func (tree *AVLTree) GetVar(key interface{}) *gvar.Var { +func (tree *AVLTree) GetVar(key interface{}) gvar.Var { return gvar.New(tree.Get(key)) } // GetVarOrSet returns a gvar.Var with result from GetVarOrSet. // The returned gvar.Var is un-concurrent safe. -func (tree *AVLTree) GetVarOrSet(key interface{}, value interface{}) *gvar.Var { +func (tree *AVLTree) GetVarOrSet(key interface{}, value interface{}) gvar.Var { return gvar.New(tree.GetOrSet(key, value)) } // GetVarOrSetFunc returns a gvar.Var with result from GetOrSetFunc. // The returned gvar.Var is un-concurrent safe. -func (tree *AVLTree) GetVarOrSetFunc(key interface{}, f func() interface{}) *gvar.Var { +func (tree *AVLTree) GetVarOrSetFunc(key interface{}, f func() interface{}) gvar.Var { return gvar.New(tree.GetOrSetFunc(key, f)) } // GetVarOrSetFuncLock returns a gvar.Var with result from GetOrSetFuncLock. // The returned gvar.Var is un-concurrent safe. -func (tree *AVLTree) GetVarOrSetFuncLock(key interface{}, f func() interface{}) *gvar.Var { +func (tree *AVLTree) GetVarOrSetFuncLock(key interface{}, f func() interface{}) gvar.Var { return gvar.New(tree.GetOrSetFuncLock(key, f)) } diff --git a/container/gtree/gtree_btree.go b/container/gtree/gtree_btree.go index 05c567591..33e4e219b 100644 --- a/container/gtree/gtree_btree.go +++ b/container/gtree/gtree_btree.go @@ -171,25 +171,25 @@ func (tree *BTree) GetOrSetFuncLock(key interface{}, f func() interface{}) inter // GetVar returns a gvar.Var with the value by given . // The returned gvar.Var is un-concurrent safe. -func (tree *BTree) GetVar(key interface{}) *gvar.Var { +func (tree *BTree) GetVar(key interface{}) gvar.Var { return gvar.New(tree.Get(key)) } // GetVarOrSet returns a gvar.Var with result from GetVarOrSet. // The returned gvar.Var is un-concurrent safe. -func (tree *BTree) GetVarOrSet(key interface{}, value interface{}) *gvar.Var { +func (tree *BTree) GetVarOrSet(key interface{}, value interface{}) gvar.Var { return gvar.New(tree.GetOrSet(key, value)) } // GetVarOrSetFunc returns a gvar.Var with result from GetOrSetFunc. // The returned gvar.Var is un-concurrent safe. -func (tree *BTree) GetVarOrSetFunc(key interface{}, f func() interface{}) *gvar.Var { +func (tree *BTree) GetVarOrSetFunc(key interface{}, f func() interface{}) gvar.Var { return gvar.New(tree.GetOrSetFunc(key, f)) } // GetVarOrSetFuncLock returns a gvar.Var with result from GetOrSetFuncLock. // The returned gvar.Var is un-concurrent safe. -func (tree *BTree) GetVarOrSetFuncLock(key interface{}, f func() interface{}) *gvar.Var { +func (tree *BTree) GetVarOrSetFuncLock(key interface{}, f func() interface{}) gvar.Var { return gvar.New(tree.GetOrSetFuncLock(key, f)) } diff --git a/container/gtree/gtree_redblacktree.go b/container/gtree/gtree_redblacktree.go index f23d7838d..343d05221 100644 --- a/container/gtree/gtree_redblacktree.go +++ b/container/gtree/gtree_redblacktree.go @@ -213,25 +213,25 @@ func (tree *RedBlackTree) GetOrSetFuncLock(key interface{}, f func() interface{} // GetVar returns a gvar.Var with the value by given . // The returned gvar.Var is un-concurrent safe. -func (tree *RedBlackTree) GetVar(key interface{}) *gvar.Var { +func (tree *RedBlackTree) GetVar(key interface{}) gvar.Var { return gvar.New(tree.Get(key)) } // GetVarOrSet returns a gvar.Var with result from GetVarOrSet. // The returned gvar.Var is un-concurrent safe. -func (tree *RedBlackTree) GetVarOrSet(key interface{}, value interface{}) *gvar.Var { +func (tree *RedBlackTree) GetVarOrSet(key interface{}, value interface{}) gvar.Var { return gvar.New(tree.GetOrSet(key, value)) } // GetVarOrSetFunc returns a gvar.Var with result from GetOrSetFunc. // The returned gvar.Var is un-concurrent safe. -func (tree *RedBlackTree) GetVarOrSetFunc(key interface{}, f func() interface{}) *gvar.Var { +func (tree *RedBlackTree) GetVarOrSetFunc(key interface{}, f func() interface{}) gvar.Var { return gvar.New(tree.GetOrSetFunc(key, f)) } // GetVarOrSetFuncLock returns a gvar.Var with result from GetOrSetFuncLock. // The returned gvar.Var is un-concurrent safe. -func (tree *RedBlackTree) GetVarOrSetFuncLock(key interface{}, f func() interface{}) *gvar.Var { +func (tree *RedBlackTree) GetVarOrSetFuncLock(key interface{}, f func() interface{}) gvar.Var { return gvar.New(tree.GetOrSetFuncLock(key, f)) } diff --git a/container/gvar/gvar.go b/container/gvar/gvar.go index c573a5b32..0059bd251 100644 --- a/container/gvar/gvar.go +++ b/container/gvar/gvar.go @@ -8,251 +8,75 @@ package gvar import ( - "encoding/json" - "time" - - "github.com/gogf/gf/internal/empty" - - "github.com/gogf/gf/container/gtype" + "github.com/gogf/gf/internal/intstore" "github.com/gogf/gf/os/gtime" - "github.com/gogf/gf/util/gconv" + "reflect" + "time" ) -// Var is an universal variable type. -type Var struct { - value interface{} // Underlying value. - safe bool // Concurrent safe or not. +// Var is a universal variable interface, like generics. +type Var interface { + IsEmpty() bool + IsNil() bool + + Val() interface{} + Set(value interface{}) (old interface{}) + Interface() interface{} + String() string + + Bool() bool + + Int() int + Int16() int16 + Int32() int32 + Int64() int64 + Int8() int8 + + Uint() uint + Uint16() uint16 + Uint32() uint32 + Uint64() uint64 + Uint8() uint8 + + Float32() float32 + Float64() float64 + + Ints() []int + Uints() []uint + Vars() []Var + Bytes() []byte + Floats() []float64 + Array() []interface{} + Slice() []interface{} + Strings() []string + Interfaces() []interface{} + + Map(tags ...string) map[string]interface{} + MapDeep(tags ...string) map[string]interface{} + MapStrStr(tags ...string) map[string]string + MapStrStrDeep(tags ...string) map[string]string + MapStrVar(tags ...string) map[string]Var + MapStrVarDeep(tags ...string) map[string]Var + MapToMap(pointer interface{}, mapping ...map[string]string) (err error) + MapToMapDeep(pointer interface{}, mapping ...map[string]string) (err error) + MapToMaps(pointer interface{}, mapping ...map[string]string) (err error) + MapToMapsDeep(pointer interface{}, mapping ...map[string]string) (err error) + + Struct(pointer interface{}, mapping ...map[string]string) error + StructDeep(pointer interface{}, mapping ...map[string]string) error + Structs(pointer interface{}, mapping ...map[string]string) (err error) + StructsDeep(pointer interface{}, mapping ...map[string]string) (err error) + + Time(format ...string) time.Time + Duration() time.Duration + GTime(format ...string) *gtime.Time + + MarshalJSON() ([]byte, error) + UnmarshalJSON(b []byte) error + UnmarshalValue(value interface{}) error } -// New creates and returns a new *Var with given . -// The optional parameter specifies whether Var is used in concurrent-safety, -// which is false in default. -func New(value interface{}, safe ...bool) *Var { - v := Create(value, safe...) - return &v -} - -// Create creates and returns a new Var with given . -// The optional parameter specifies whether Var is used in concurrent-safety, -// which is false in default. -func Create(value interface{}, safe ...bool) Var { - v := Var{} - if len(safe) > 0 && !safe[0] { - v.safe = true - v.value = gtype.NewInterface(value) - } else { - v.value = value - } - return v -} - -// Clone does a shallow copy of current Var and returns a pointer to this Var. -func (v *Var) Clone() *Var { - return New(v.Val(), v.safe) -} - -// Set sets to , and returns the old value. -func (v *Var) Set(value interface{}) (old interface{}) { - if v.safe { - if t, ok := v.value.(*gtype.Interface); ok { - old = t.Set(value) - return - } - } - old = v.value - v.value = value - return -} - -// Val returns the current value of . -func (v *Var) Val() interface{} { - if v == nil { - return nil - } - if v.safe { - if t, ok := v.value.(*gtype.Interface); ok { - return t.Val() - } - } - return v.value -} - -// Interface is alias of Val. -func (v *Var) Interface() interface{} { - return v.Val() -} - -// IsNil checks whether is nil. -func (v *Var) IsNil() bool { - return v.Val() == nil -} - -// IsEmpty checks whether is empty. -func (v *Var) IsEmpty() bool { - return empty.IsEmpty(v.Val()) -} - -// Bytes converts and returns as []byte. -func (v *Var) Bytes() []byte { - return gconv.Bytes(v.Val()) -} - -// String converts and returns as string. -func (v *Var) String() string { - return gconv.String(v.Val()) -} - -// Bool converts and returns as bool. -func (v *Var) Bool() bool { - return gconv.Bool(v.Val()) -} - -// Int converts and returns as int. -func (v *Var) Int() int { - return gconv.Int(v.Val()) -} - -// Ints converts and returns as []int. -func (v *Var) Ints() []int { - return gconv.Ints(v.Val()) -} - -// Int8 converts and returns as int8. -func (v *Var) Int8() int8 { - return gconv.Int8(v.Val()) -} - -// Int16 converts and returns as int16. -func (v *Var) Int16() int16 { - return gconv.Int16(v.Val()) -} - -// Int32 converts and returns as int32. -func (v *Var) Int32() int32 { - return gconv.Int32(v.Val()) -} - -// Int64 converts and returns as int64. -func (v *Var) Int64() int64 { - return gconv.Int64(v.Val()) -} - -// Uint converts and returns as uint. -func (v *Var) Uint() uint { - return gconv.Uint(v.Val()) -} - -// Uints converts and returns as []uint. -func (v *Var) Uints() []uint { - return gconv.Uints(v.Val()) -} - -// Uint8 converts and returns as uint8. -func (v *Var) Uint8() uint8 { - return gconv.Uint8(v.Val()) -} - -// Uint16 converts and returns as uint16. -func (v *Var) Uint16() uint16 { - return gconv.Uint16(v.Val()) -} - -// Uint32 converts and returns as uint32. -func (v *Var) Uint32() uint32 { - return gconv.Uint32(v.Val()) -} - -// Uint64 converts and returns as uint64. -func (v *Var) Uint64() uint64 { - return gconv.Uint64(v.Val()) -} - -// Float32 converts and returns as float32. -func (v *Var) Float32() float32 { - return gconv.Float32(v.Val()) -} - -// Float64 converts and returns as float64. -func (v *Var) Float64() float64 { - return gconv.Float64(v.Val()) -} - -// Floats converts and returns as []float64. -func (v *Var) Floats() []float64 { - return gconv.Floats(v.Val()) -} - -// Strings converts and returns as []string. -func (v *Var) Strings() []string { - return gconv.Strings(v.Val()) -} - -// Interfaces converts and returns as []interfaces{}. -func (v *Var) Interfaces() []interface{} { - return gconv.Interfaces(v.Val()) -} - -// Slice is alias of Interfaces. -func (v *Var) Slice() []interface{} { - return v.Interfaces() -} - -// Array is alias of Interfaces. -func (v *Var) Array() []interface{} { - return v.Interfaces() -} - -// Vars converts and returns as []*Var. -func (v *Var) Vars() []*Var { - array := gconv.Interfaces(v.Val()) - if len(array) == 0 { - return nil - } - vars := make([]*Var, len(array)) - for k, v := range array { - vars[k] = New(v) - } - return vars -} - -// Time converts and returns as time.Time. -// The parameter specifies the format of the time string using gtime, -// eg: Y-m-d H:i:s. -func (v *Var) Time(format ...string) time.Time { - return gconv.Time(v.Val(), format...) -} - -// Duration converts and returns as time.Duration. -// If value of is string, then it uses time.ParseDuration for conversion. -func (v *Var) Duration() time.Duration { - return gconv.Duration(v.Val()) -} - -// GTime converts and returns as *gtime.Time. -// The parameter specifies the format of the time string using gtime, -// eg: Y-m-d H:i:s. -func (v *Var) GTime(format ...string) *gtime.Time { - return gconv.GTime(v.Val(), format...) -} - -// MarshalJSON implements the interface MarshalJSON for json.Marshal. -func (v *Var) MarshalJSON() ([]byte, error) { - return json.Marshal(v.Val()) -} - -// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal. -func (v *Var) UnmarshalJSON(b []byte) error { - var i interface{} - err := json.Unmarshal(b, &i) - if err != nil { - return err - } - v.Set(i) - return nil -} - -// UnmarshalValue is an interface implement which sets any type of value for Var. -func (v *Var) UnmarshalValue(value interface{}) error { - v.Set(value) - return nil +func init() { + // Register the type of gvar.VarImp to local variable. + intstore.ReflectTypeVarImp = reflect.TypeOf(VarImp{}) } diff --git a/container/gvar/gvar_imp.go b/container/gvar/gvar_imp.go new file mode 100644 index 000000000..31783de39 --- /dev/null +++ b/container/gvar/gvar_imp.go @@ -0,0 +1,264 @@ +// Copyright 2018-2019 gf Author(https://github.com/gogf/gf). 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 gvar + +import ( + "encoding/json" + "time" + + "github.com/gogf/gf/internal/empty" + + "github.com/gogf/gf/container/gtype" + "github.com/gogf/gf/os/gtime" + "github.com/gogf/gf/util/gconv" +) + +// VarImp is an universal variable type implementer. +type VarImp struct { + value interface{} // Underlying value. + safe bool // Concurrent safe or not. +} + +// New creates and returns a new Var with given . +// The optional parameter specifies whether Var is used in concurrent-safety, +// which is false in default. +func New(value interface{}, safe ...bool) Var { + v := VarImp{} + if len(safe) > 0 && !safe[0] { + v.safe = true + v.value = gtype.NewInterface(value) + } else { + v.value = value + } + return &v +} + +// Create creates and returns a new VarImp with given . +// The optional parameter specifies whether Var is used in concurrent-safety, +// which is false in default. +// Deprecated. +func Create(value interface{}, safe ...bool) VarImp { + v := VarImp{} + if len(safe) > 0 && !safe[0] { + v.safe = true + v.value = gtype.NewInterface(value) + } else { + v.value = value + } + return v +} + +// Clone does a shallow copy of current Var and returns a pointer to this Var. +func (v *VarImp) Clone() Var { + return New(v.Val(), v.safe) +} + +// Set sets to , and returns the old value. +func (v *VarImp) Set(value interface{}) (old interface{}) { + if v.safe { + if t, ok := v.value.(*gtype.Interface); ok { + old = t.Set(value) + return + } + } + old = v.value + v.value = value + return +} + +// Val returns the current value of . +func (v *VarImp) Val() interface{} { + if v == nil { + return nil + } + if v.safe { + if t, ok := v.value.(*gtype.Interface); ok { + return t.Val() + } + } + return v.value +} + +// Interface is alias of Val. +func (v *VarImp) Interface() interface{} { + return v.Val() +} + +// IsNil checks whether is nil. +func (v *VarImp) IsNil() bool { + return v.Val() == nil +} + +// IsEmpty checks whether is empty. +func (v *VarImp) IsEmpty() bool { + return empty.IsEmpty(v.Val()) +} + +// Bytes converts and returns as []byte. +func (v *VarImp) Bytes() []byte { + return gconv.Bytes(v.Val()) +} + +// String converts and returns as string. +func (v *VarImp) String() string { + return gconv.String(v.Val()) +} + +// Bool converts and returns as bool. +func (v *VarImp) Bool() bool { + return gconv.Bool(v.Val()) +} + +// Int converts and returns as int. +func (v *VarImp) Int() int { + return gconv.Int(v.Val()) +} + +// Ints converts and returns as []int. +func (v *VarImp) Ints() []int { + return gconv.Ints(v.Val()) +} + +// Int8 converts and returns as int8. +func (v *VarImp) Int8() int8 { + return gconv.Int8(v.Val()) +} + +// Int16 converts and returns as int16. +func (v *VarImp) Int16() int16 { + return gconv.Int16(v.Val()) +} + +// Int32 converts and returns as int32. +func (v *VarImp) Int32() int32 { + return gconv.Int32(v.Val()) +} + +// Int64 converts and returns as int64. +func (v *VarImp) Int64() int64 { + return gconv.Int64(v.Val()) +} + +// Uint converts and returns as uint. +func (v *VarImp) Uint() uint { + return gconv.Uint(v.Val()) +} + +// Uints converts and returns as []uint. +func (v *VarImp) Uints() []uint { + return gconv.Uints(v.Val()) +} + +// Uint8 converts and returns as uint8. +func (v *VarImp) Uint8() uint8 { + return gconv.Uint8(v.Val()) +} + +// Uint16 converts and returns as uint16. +func (v *VarImp) Uint16() uint16 { + return gconv.Uint16(v.Val()) +} + +// Uint32 converts and returns as uint32. +func (v *VarImp) Uint32() uint32 { + return gconv.Uint32(v.Val()) +} + +// Uint64 converts and returns as uint64. +func (v *VarImp) Uint64() uint64 { + return gconv.Uint64(v.Val()) +} + +// Float32 converts and returns as float32. +func (v *VarImp) Float32() float32 { + return gconv.Float32(v.Val()) +} + +// Float64 converts and returns as float64. +func (v *VarImp) Float64() float64 { + return gconv.Float64(v.Val()) +} + +// Floats converts and returns as []float64. +func (v *VarImp) Floats() []float64 { + return gconv.Floats(v.Val()) +} + +// Strings converts and returns as []string. +func (v *VarImp) Strings() []string { + return gconv.Strings(v.Val()) +} + +// Interfaces converts and returns as []interfaces{}. +func (v *VarImp) Interfaces() []interface{} { + return gconv.Interfaces(v.Val()) +} + +// Slice is alias of Interfaces. +func (v *VarImp) Slice() []interface{} { + return v.Interfaces() +} + +// Array is alias of Interfaces. +func (v *VarImp) Array() []interface{} { + return v.Interfaces() +} + +// Vars converts and returns as []Var. +func (v *VarImp) Vars() []Var { + array := gconv.Interfaces(v.Val()) + if len(array) == 0 { + return nil + } + vars := make([]Var, len(array)) + for k, v := range array { + vars[k] = New(v) + } + return vars +} + +// Time converts and returns as time.Time. +// The parameter specifies the format of the time string using gtime, +// eg: Y-m-d H:i:s. +func (v *VarImp) Time(format ...string) time.Time { + return gconv.Time(v.Val(), format...) +} + +// Duration converts and returns as time.Duration. +// If value of is string, then it uses time.ParseDuration for conversion. +func (v *VarImp) Duration() time.Duration { + return gconv.Duration(v.Val()) +} + +// GTime converts and returns as *gtime.Time. +// The parameter specifies the format of the time string using gtime, +// eg: Y-m-d H:i:s. +func (v *VarImp) GTime(format ...string) *gtime.Time { + return gconv.GTime(v.Val(), format...) +} + +// MarshalJSON implements the interface MarshalJSON for json.Marshal. +func (v *VarImp) MarshalJSON() ([]byte, error) { + return json.Marshal(v.Val()) +} + +// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal. +func (v *VarImp) UnmarshalJSON(b []byte) error { + var i interface{} + err := json.Unmarshal(b, &i) + if err != nil { + return err + } + v.Set(i) + return nil +} + +// UnmarshalValue is an interface implement which sets any type of value for Var. +func (v *VarImp) UnmarshalValue(value interface{}) error { + v.Set(value) + return nil +} diff --git a/container/gvar/gvar_map.go b/container/gvar/gvar_imp_map.go similarity index 60% rename from container/gvar/gvar_map.go rename to container/gvar/gvar_imp_map.go index ba6156f3f..c9ed6cc67 100644 --- a/container/gvar/gvar_map.go +++ b/container/gvar/gvar_imp_map.go @@ -9,20 +9,20 @@ package gvar import "github.com/gogf/gf/util/gconv" // Map converts and returns as map[string]interface{}. -func (v *Var) Map(tags ...string) map[string]interface{} { +func (v *VarImp) Map(tags ...string) map[string]interface{} { return gconv.Map(v.Val(), tags...) } // MapStrStr converts and returns as map[string]string. -func (v *Var) MapStrStr(tags ...string) map[string]string { +func (v *VarImp) MapStrStr(tags ...string) map[string]string { return gconv.MapStrStr(v.Val(), tags...) } -// MapStrVar converts and returns as map[string]*Var. -func (v *Var) MapStrVar(tags ...string) map[string]*Var { +// MapStrVar converts and returns as map[string]Var. +func (v *VarImp) MapStrVar(tags ...string) map[string]Var { m := v.Map(tags...) if len(m) > 0 { - vMap := make(map[string]*Var, len(m)) + vMap := make(map[string]Var, len(m)) for k, v := range m { vMap[k] = New(v) } @@ -32,20 +32,20 @@ func (v *Var) MapStrVar(tags ...string) map[string]*Var { } // MapDeep converts and returns as map[string]interface{} recursively. -func (v *Var) MapDeep(tags ...string) map[string]interface{} { +func (v *VarImp) MapDeep(tags ...string) map[string]interface{} { return gconv.MapDeep(v.Val(), tags...) } // MapDeep converts and returns as map[string]string recursively. -func (v *Var) MapStrStrDeep(tags ...string) map[string]string { +func (v *VarImp) MapStrStrDeep(tags ...string) map[string]string { return gconv.MapStrStrDeep(v.Val(), tags...) } -// MapStrVarDeep converts and returns as map[string]*Var recursively. -func (v *Var) MapStrVarDeep(tags ...string) map[string]*Var { +// MapStrVarDeep converts and returns as map[string]*VarImp recursively. +func (v *VarImp) MapStrVarDeep(tags ...string) map[string]Var { m := v.MapDeep(tags...) if len(m) > 0 { - vMap := make(map[string]*Var, len(m)) + vMap := make(map[string]Var, len(m)) for k, v := range m { vMap[k] = New(v) } @@ -56,32 +56,32 @@ func (v *Var) MapStrVarDeep(tags ...string) map[string]*Var { // Maps converts and returns as map[string]string. // See gconv.Maps. -func (v *Var) Maps(tags ...string) []map[string]interface{} { +func (v *VarImp) Maps(tags ...string) []map[string]interface{} { return gconv.Maps(v.Val(), tags...) } // MapToMap converts any map type variable to another map type variable . // See gconv.MapToMap. -func (v *Var) MapToMap(pointer interface{}) (err error) { - return gconv.MapToMap(v.Val(), pointer) +func (v *VarImp) MapToMap(pointer interface{}, mapping ...map[string]string) (err error) { + return gconv.MapToMap(v.Val(), pointer, mapping...) } // MapToMapDeep converts any map type variable to another map type variable // recursively. // See gconv.MapToMapDeep. -func (v *Var) MapToMapDeep(pointer interface{}) (err error) { - return gconv.MapToMapDeep(v.Val(), pointer) +func (v *VarImp) MapToMapDeep(pointer interface{}, mapping ...map[string]string) (err error) { + return gconv.MapToMapDeep(v.Val(), pointer, mapping...) } // MapToMaps converts any map type variable to another map type variable . // See gconv.MapToMaps. -func (v *Var) MapToMaps(pointer interface{}, mapping ...map[string]string) (err error) { +func (v *VarImp) MapToMaps(pointer interface{}, mapping ...map[string]string) (err error) { return gconv.MapToMaps(v.Val(), pointer, mapping...) } // MapToMapsDeep converts any map type variable to another map type variable // recursively. // See gconv.MapToMapsDeep. -func (v *Var) MapToMapsDeep(pointer interface{}, mapping ...map[string]string) (err error) { +func (v *VarImp) MapToMapsDeep(pointer interface{}, mapping ...map[string]string) (err error) { return gconv.MapToMapsDeep(v.Val(), pointer, mapping...) } diff --git a/container/gvar/gvar_struct.go b/container/gvar/gvar_imp_struct.go similarity index 80% rename from container/gvar/gvar_struct.go rename to container/gvar/gvar_imp_struct.go index 6ae985279..8afc9e3f1 100644 --- a/container/gvar/gvar_struct.go +++ b/container/gvar/gvar_imp_struct.go @@ -13,24 +13,24 @@ import ( // Struct maps value of to . // The parameter should be a pointer to a struct instance. // The parameter is used to specify the key-to-attribute mapping rules. -func (v *Var) Struct(pointer interface{}, mapping ...map[string]string) error { +func (v *VarImp) Struct(pointer interface{}, mapping ...map[string]string) error { return gconv.Struct(v.Val(), pointer, mapping...) } // Struct maps value of to recursively. // The parameter should be a pointer to a struct instance. // The parameter is used to specify the key-to-attribute mapping rules. -func (v *Var) StructDeep(pointer interface{}, mapping ...map[string]string) error { +func (v *VarImp) StructDeep(pointer interface{}, mapping ...map[string]string) error { return gconv.StructDeep(v.Val(), pointer, mapping...) } // Structs converts and returns as given struct slice. -func (v *Var) Structs(pointer interface{}, mapping ...map[string]string) error { +func (v *VarImp) Structs(pointer interface{}, mapping ...map[string]string) error { return gconv.Structs(v.Val(), pointer, mapping...) } // StructsDeep converts and returns as given struct slice recursively. -func (v *Var) StructsDeep(pointer interface{}, mapping ...map[string]string) error { +func (v *VarImp) StructsDeep(pointer interface{}, mapping ...map[string]string) error { return gconv.StructsDeep(v.Val(), pointer, mapping...) } @@ -38,7 +38,7 @@ func (v *Var) StructsDeep(pointer interface{}, mapping ...map[string]string) err // to implement the converting. // It calls function Struct if is type of *struct/**struct to do the converting. // It calls function Structs if is type of *[]struct/*[]*struct to do the converting. -func (v *Var) Scan(pointer interface{}, mapping ...map[string]string) error { +func (v *VarImp) Scan(pointer interface{}, mapping ...map[string]string) error { return gconv.Scan(v.Val(), pointer, mapping...) } @@ -46,6 +46,6 @@ func (v *Var) Scan(pointer interface{}, mapping ...map[string]string) error { // parameter to implement the converting. // It calls function StructDeep if is type of *struct/**struct to do the converting. // It calls function StructsDeep if is type of *[]struct/*[]*struct to do the converting. -func (v *Var) ScanDeep(pointer interface{}, mapping ...map[string]string) error { +func (v *VarImp) ScanDeep(pointer interface{}, mapping ...map[string]string) error { return gconv.ScanDeep(v.Val(), pointer, mapping...) } diff --git a/container/gvar/gvar_z_unit_basic_test.go b/container/gvar/gvar_z_unit_basic_test.go index a3ae8cff4..ebcbd3a1d 100644 --- a/container/gvar/gvar_z_unit_basic_test.go +++ b/container/gvar/gvar_z_unit_basic_test.go @@ -19,12 +19,12 @@ import ( func Test_Set(t *testing.T) { gtest.C(t, func(t *gtest.T) { - var v gvar.Var + var v gvar.VarImp v.Set(123.456) t.Assert(v.Val(), 123.456) }) gtest.C(t, func(t *gtest.T) { - var v gvar.Var + var v gvar.VarImp v.Set(123.456) t.Assert(v.Val(), 123.456) }) @@ -304,7 +304,7 @@ func Test_Duration(t *testing.T) { func Test_UnmarshalValue(t *testing.T) { type V struct { Name string - Var *gvar.Var + Var gvar.Var } gtest.C(t, func(t *gtest.T) { var v *V diff --git a/container/gvar/gvar_z_unit_json_test.go b/container/gvar/gvar_z_unit_json_test.go index f18bc5546..f05251136 100644 --- a/container/gvar/gvar_z_unit_json_test.go +++ b/container/gvar/gvar_z_unit_json_test.go @@ -47,7 +47,7 @@ func Test_Json(t *testing.T) { }) gtest.C(t, func(t *gtest.T) { - var v gvar.Var + var v gvar.VarImp s := "i love gf" b, err := json.Marshal(s) t.Assert(err, nil) diff --git a/database/gdb/gdb.go b/database/gdb/gdb.go index af41f6d21..3f3e14e38 100644 --- a/database/gdb/gdb.go +++ b/database/gdb/gdb.go @@ -173,7 +173,7 @@ type Link interface { type ( // Value is the field value type. - Value = *gvar.Var + Value = gvar.Var // Record is the row record of the table. Record map[string]Value diff --git a/database/gdb/gdb_core.go b/database/gdb/gdb_core.go index dd80be6fc..ecdf9a3f7 100644 --- a/database/gdb/gdb_core.go +++ b/database/gdb/gdb_core.go @@ -244,12 +244,12 @@ func (c *Core) GetScan(pointer interface{}, sql string, args ...interface{}) err func (c *Core) GetValue(sql string, args ...interface{}) (Value, error) { one, err := c.DB.GetOne(sql, args...) if err != nil { - return nil, err + return gvar.New(nil), err } for _, v := range one { return v, nil } - return nil, nil + return gvar.New(nil), nil } // GetCount queries and returns the count from database. diff --git a/database/gdb/gdb_model_select.go b/database/gdb/gdb_model_select.go index 153ed3da3..c6c3c486d 100644 --- a/database/gdb/gdb_model_select.go +++ b/database/gdb/gdb_model_select.go @@ -8,6 +8,7 @@ package gdb import ( "fmt" + "github.com/gogf/gf/container/gvar" "github.com/gogf/gf/util/gconv" "reflect" ) @@ -118,12 +119,12 @@ func (m *Model) Value(fieldsAndWhere ...interface{}) (Value, error) { } one, err := m.One() if err != nil { - return nil, err + return gvar.New(nil), err } for _, v := range one { return v, nil } - return nil, nil + return gvar.New(nil), nil } // Array queries and returns data values as slice from database. diff --git a/database/gredis/gredis.go b/database/gredis/gredis.go index c2c53d2cd..181868838 100644 --- a/database/gredis/gredis.go +++ b/database/gredis/gredis.go @@ -210,8 +210,8 @@ func (r *Redis) Do(command string, args ...interface{}) (interface{}, error) { return conn.Do(command, args...) } -// DoVar returns value from Do as *gvar.Var. -func (r *Redis) DoVar(command string, args ...interface{}) (*gvar.Var, error) { +// DoVar returns value from Do as gvar.Var. +func (r *Redis) DoVar(command string, args ...interface{}) (gvar.Var, error) { v, err := r.Do(command, args...) if result, ok := v.([]byte); ok { return gvar.New(gconv.UnsafeBytesToStr(result)), err diff --git a/database/gredis/gredis_conn.go b/database/gredis/gredis_conn.go index 3eb525137..bb4b34944 100644 --- a/database/gredis/gredis_conn.go +++ b/database/gredis/gredis_conn.go @@ -44,13 +44,13 @@ func (c *Conn) Do(commandName string, args ...interface{}) (reply interface{}, e } // DoVar retrieves and returns the result from command as gvar.Var. -func (c *Conn) DoVar(command string, args ...interface{}) (*gvar.Var, error) { +func (c *Conn) DoVar(command string, args ...interface{}) (gvar.Var, error) { v, err := c.Do(command, args...) return gvar.New(v), err } // ReceiveVar receives a single reply as gvar.Var from the Redis server. -func (c *Conn) ReceiveVar() (*gvar.Var, error) { +func (c *Conn) ReceiveVar() (gvar.Var, error) { v, err := c.Receive() return gvar.New(v), err } diff --git a/database/gredis/gredis_z_example_test.go b/database/gredis/gredis_z_example_test.go index 499d31b34..2f0121ba9 100644 --- a/database/gredis/gredis_z_example_test.go +++ b/database/gredis/gredis_z_example_test.go @@ -15,7 +15,7 @@ import ( func Example_autoMarshalUnmarshalMap() { var ( err error - result *gvar.Var + result gvar.Var key = "user" data = g.Map{ "id": 10000, @@ -40,7 +40,7 @@ func Example_autoMarshalUnmarshalStruct() { } var ( err error - result *gvar.Var + result gvar.Var key = "user" user = &User{ Id: 10000, @@ -71,7 +71,7 @@ func Example_autoMarshalUnmarshalStructSlice() { } var ( err error - result *gvar.Var + result gvar.Var key = "user-slice" users1 = []User{ { @@ -104,7 +104,7 @@ func Example_autoMarshalUnmarshalStructSlice() { func Example_hashSet() { var ( err error - result *gvar.Var + result gvar.Var key = "user" ) _, err = g.Redis().Do("HSET", key, "id", 10000) diff --git a/database/gredis/gredis_z_unit_test.go b/database/gredis/gredis_z_unit_test.go index 23e5804f0..d62dea30c 100644 --- a/database/gredis/gredis_z_unit_test.go +++ b/database/gredis/gredis_z_unit_test.go @@ -356,7 +356,7 @@ func Test_Auto_MarshalSlice(t *testing.T) { gtest.C(t, func(t *gtest.T) { var ( - result *gvar.Var + result gvar.Var key = "user-slice" users1 = []User{ { diff --git a/encoding/gjson/gjson_api.go b/encoding/gjson/gjson_api.go index 149e19264..81e04f037 100644 --- a/encoding/gjson/gjson_api.go +++ b/encoding/gjson/gjson_api.go @@ -68,13 +68,13 @@ func (j *Json) Get(pattern string, def ...interface{}) interface{} { return nil } -// GetVar returns a *gvar.Var with value by given . -func (j *Json) GetVar(pattern string, def ...interface{}) *gvar.Var { +// GetVar returns a gvar.Var with value by given . +func (j *Json) GetVar(pattern string, def ...interface{}) gvar.Var { return gvar.New(j.Get(pattern, def...)) } -// GetVars returns []*gvar.Var with value by given . -func (j *Json) GetVars(pattern string, def ...interface{}) []*gvar.Var { +// GetVars returns []gvar.Var with value by given . +func (j *Json) GetVars(pattern string, def ...interface{}) []gvar.Var { return gvar.New(j.Get(pattern, def...)).Vars() } diff --git a/frame/g/g.go b/frame/g/g.go index 06a774c7b..72bdd723b 100644 --- a/frame/g/g.go +++ b/frame/g/g.go @@ -10,7 +10,7 @@ import ( "github.com/gogf/gf/container/gvar" ) -// Var is a universal variable type, like generics. +// Var is a universal variable interface, like generics. type Var = gvar.Var // Frequently-used map type alias. diff --git a/frame/g/g_func.go b/frame/g/g_func.go index 728f0dd25..8c008b767 100644 --- a/frame/g/g_func.go +++ b/frame/g/g_func.go @@ -13,16 +13,11 @@ import ( "github.com/gogf/gf/util/gutil" ) -// NewVar returns a *gvar.Var. -func NewVar(i interface{}, safe ...bool) *Var { +// NewVar returns a gvar.Var. +func NewVar(i interface{}, safe ...bool) Var { return gvar.New(i, safe...) } -// CreateVar returns a gvar.Var. -func CreateVar(i interface{}, safe ...bool) Var { - return gvar.Create(i, safe...) -} - // Wait blocks until all the web servers shutdown. func Wait() { ghttp.Wait() diff --git a/internal/cmdenv/cmdenv.go b/internal/cmdenv/cmdenv.go index 7ed521be3..410c3ccd7 100644 --- a/internal/cmdenv/cmdenv.go +++ b/internal/cmdenv/cmdenv.go @@ -42,7 +42,7 @@ func doInit() { // Fetching Rules: // 1. Command line arguments are in lowercase format, eg: gf..; // 2. Environment arguments are in uppercase format, eg: GF__; -func Get(key string, def ...interface{}) *gvar.Var { +func Get(key string, def ...interface{}) gvar.Var { value := interface{}(nil) if len(def) > 0 { value = def[0] diff --git a/internal/intstore/intstore.go b/internal/intstore/intstore.go new file mode 100644 index 000000000..e774bab4d --- /dev/null +++ b/internal/intstore/intstore.go @@ -0,0 +1,15 @@ +// Copyright 2020 gf Author(https://github.com/gogf/gf). 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 intstore provides local variable storing for internal usage. +package intstore + +import "reflect" + +var ( + // Reflect type for gvar.VarImp. + ReflectTypeVarImp = reflect.Type(nil) +) diff --git a/net/ghttp/ghttp_request_param.go b/net/ghttp/ghttp_request_param.go index f5463cfd2..201bcdc57 100644 --- a/net/ghttp/ghttp_request_param.go +++ b/net/ghttp/ghttp_request_param.go @@ -99,7 +99,7 @@ func (r *Request) Get(key string, def ...interface{}) interface{} { // GetVar is alis of GetRequestVar. // See GetRequestVar. -func (r *Request) GetVar(key string, def ...interface{}) *gvar.Var { +func (r *Request) GetVar(key string, def ...interface{}) gvar.Var { return r.GetRequestVar(key, def...) } diff --git a/net/ghttp/ghttp_request_param_ctx.go b/net/ghttp/ghttp_request_param_ctx.go index 91910c45d..054949f81 100644 --- a/net/ghttp/ghttp_request_param_ctx.go +++ b/net/ghttp/ghttp_request_param_ctx.go @@ -29,7 +29,7 @@ func (r *Request) GetCtx() context.Context { // GetCtxVar retrieves and returns a Var with given key name. // The optional parameter specifies the default value of the Var if given // does not exist in the context. -func (r *Request) GetCtxVar(key interface{}, def ...interface{}) *gvar.Var { +func (r *Request) GetCtxVar(key interface{}, def ...interface{}) gvar.Var { value := r.Context().Value(key) if value == nil && len(def) > 0 { value = def[0] diff --git a/net/ghttp/ghttp_request_param_form.go b/net/ghttp/ghttp_request_param_form.go index c100160ff..62583a0f0 100644 --- a/net/ghttp/ghttp_request_param_form.go +++ b/net/ghttp/ghttp_request_param_form.go @@ -37,7 +37,7 @@ func (r *Request) GetForm(key string, def ...interface{}) interface{} { // GetFormVar retrieves and returns parameter from form as Var. // It returns if does not exist in the form and is given, or else it returns nil. -func (r *Request) GetFormVar(key string, def ...interface{}) *gvar.Var { +func (r *Request) GetFormVar(key string, def ...interface{}) gvar.Var { return gvar.New(r.GetForm(key, def...)) } @@ -169,13 +169,13 @@ func (r *Request) GetFormMapStrStr(kvMap ...map[string]interface{}) map[string]s return nil } -// GetFormMapStrVar retrieves and returns all form parameters passed from client as map[string]*gvar.Var. +// GetFormMapStrVar retrieves and returns all form parameters passed from client as map[string]gvar.Var. // The parameter specifies the keys retrieving from client parameters, the associated values // are the default values if the client does not pass. -func (r *Request) GetFormMapStrVar(kvMap ...map[string]interface{}) map[string]*gvar.Var { +func (r *Request) GetFormMapStrVar(kvMap ...map[string]interface{}) map[string]gvar.Var { postMap := r.GetFormMap(kvMap...) if len(postMap) > 0 { - m := make(map[string]*gvar.Var, len(postMap)) + m := make(map[string]gvar.Var, len(postMap)) for k, v := range postMap { m[k] = gvar.New(v) } diff --git a/net/ghttp/ghttp_request_param_param.go b/net/ghttp/ghttp_request_param_param.go index cd788471f..92f6b1f86 100644 --- a/net/ghttp/ghttp_request_param_param.go +++ b/net/ghttp/ghttp_request_param_param.go @@ -29,9 +29,9 @@ func (r *Request) GetParam(key string, def ...interface{}) interface{} { return nil } -// GetParamVar returns custom parameter with given name as *gvar.Var. +// GetParamVar returns custom parameter with given name as gvar.Var. // It returns if does not exist. // It returns nil if is not passed. -func (r *Request) GetParamVar(key string, def ...interface{}) *gvar.Var { +func (r *Request) GetParamVar(key string, def ...interface{}) gvar.Var { return gvar.New(r.GetParam(key, def...)) } diff --git a/net/ghttp/ghttp_request_param_post.go b/net/ghttp/ghttp_request_param_post.go index 76d406ad4..46279e4cc 100644 --- a/net/ghttp/ghttp_request_param_post.go +++ b/net/ghttp/ghttp_request_param_post.go @@ -39,7 +39,7 @@ func (r *Request) GetPost(key string, def ...interface{}) interface{} { } // Deprecated. -func (r *Request) GetPostVar(key string, def ...interface{}) *gvar.Var { +func (r *Request) GetPostVar(key string, def ...interface{}) gvar.Var { return gvar.New(r.GetPost(key, def...)) } @@ -180,15 +180,15 @@ func (r *Request) GetPostMapStrStr(kvMap ...map[string]interface{}) map[string]s } // GetPostMapStrVar retrieves and returns all parameters in the form and body passed from client -// as map[string]*gvar.Var. The parameter specifies the keys +// as map[string]gvar.Var. The parameter specifies the keys // retrieving from client parameters, the associated values are the default values if the client // does not pass. // // Deprecated. -func (r *Request) GetPostMapStrVar(kvMap ...map[string]interface{}) map[string]*gvar.Var { +func (r *Request) GetPostMapStrVar(kvMap ...map[string]interface{}) map[string]gvar.Var { postMap := r.GetPostMap(kvMap...) if len(postMap) > 0 { - m := make(map[string]*gvar.Var, len(postMap)) + m := make(map[string]gvar.Var, len(postMap)) for k, v := range postMap { m[k] = gvar.New(v) } diff --git a/net/ghttp/ghttp_request_param_query.go b/net/ghttp/ghttp_request_param_query.go index b8250961d..ace74ff55 100644 --- a/net/ghttp/ghttp_request_param_query.go +++ b/net/ghttp/ghttp_request_param_query.go @@ -46,7 +46,7 @@ func (r *Request) GetQuery(key string, def ...interface{}) interface{} { return nil } -func (r *Request) GetQueryVar(key string, def ...interface{}) *gvar.Var { +func (r *Request) GetQueryVar(key string, def ...interface{}) gvar.Var { return gvar.New(r.GetQuery(key, def...)) } @@ -172,13 +172,13 @@ func (r *Request) GetQueryMapStrStr(kvMap ...map[string]interface{}) map[string] } // GetQueryMapStrVar retrieves and returns all parameters passed from client using HTTP GET method -// as map[string]*gvar.Var. The parameter specifies the keys +// as map[string]gvar.Var. The parameter specifies the keys // retrieving from client parameters, the associated values are the default values if the client // does not pass. -func (r *Request) GetQueryMapStrVar(kvMap ...map[string]interface{}) map[string]*gvar.Var { +func (r *Request) GetQueryMapStrVar(kvMap ...map[string]interface{}) map[string]gvar.Var { queryMap := r.GetQueryMap(kvMap...) if len(queryMap) > 0 { - m := make(map[string]*gvar.Var, len(queryMap)) + m := make(map[string]gvar.Var, len(queryMap)) for k, v := range queryMap { m[k] = gvar.New(v) } diff --git a/net/ghttp/ghttp_request_param_request.go b/net/ghttp/ghttp_request_param_request.go index ef6fcbfdc..cab6f8448 100644 --- a/net/ghttp/ghttp_request_param_request.go +++ b/net/ghttp/ghttp_request_param_request.go @@ -46,9 +46,9 @@ func (r *Request) GetRequest(key string, def ...interface{}) interface{} { } // GetRequestVar retrieves and returns the parameter named passed from client and -// custom params as *gvar.Var, no matter what HTTP method the client is using. The parameter +// custom params as gvar.Var, no matter what HTTP method the client is using. The parameter // specifies the default value if the does not exist. -func (r *Request) GetRequestVar(key string, def ...interface{}) *gvar.Var { +func (r *Request) GetRequestVar(key string, def ...interface{}) gvar.Var { return gvar.New(r.GetRequest(key, def...)) } @@ -247,13 +247,13 @@ func (r *Request) GetRequestMapStrStr(kvMap ...map[string]interface{}) map[strin } // GetRequestMapStrVar retrieves and returns all parameters passed from client and custom -// params as map[string]*gvar.Var, no matter what HTTP method the client is using. The parameter +// params as map[string]gvar.Var, no matter what HTTP method the client is using. The parameter // specifies the keys retrieving from client parameters, the associated values are the // default values if the client does not pass. -func (r *Request) GetRequestMapStrVar(kvMap ...map[string]interface{}) map[string]*gvar.Var { +func (r *Request) GetRequestMapStrVar(kvMap ...map[string]interface{}) map[string]gvar.Var { requestMap := r.GetRequestMap(kvMap...) if len(requestMap) > 0 { - m := make(map[string]*gvar.Var, len(requestMap)) + m := make(map[string]gvar.Var, len(requestMap)) for k, v := range requestMap { m[k] = gvar.New(v) } diff --git a/net/ghttp/ghttp_request_param_router.go b/net/ghttp/ghttp_request_param_router.go index 25b55f81f..e17af66a4 100644 --- a/net/ghttp/ghttp_request_param_router.go +++ b/net/ghttp/ghttp_request_param_router.go @@ -22,9 +22,9 @@ func (r *Request) GetRouterValue(key string, def ...interface{}) interface{} { return nil } -// GetRouterVar retrieves and returns the router value as *gvar.var with given key name . +// GetRouterVar retrieves and returns the router value as gvar.Var with given key name . // It returns if does not exist. -func (r *Request) GetRouterVar(key string, def ...interface{}) *gvar.Var { +func (r *Request) GetRouterVar(key string, def ...interface{}) gvar.Var { return gvar.New(r.GetRouterValue(key, def...)) } diff --git a/os/gbuild/gbuild.go b/os/gbuild/gbuild.go index 577e1b739..13b2809bc 100644 --- a/os/gbuild/gbuild.go +++ b/os/gbuild/gbuild.go @@ -59,8 +59,8 @@ func Get(name string, def ...interface{}) interface{} { return nil } -// Get retrieves and returns the build-in binary variable of given name as *gvar.Var. -func GetVar(name string, def ...interface{}) *gvar.Var { +// Get retrieves and returns the build-in binary variable of given name as gvar.Var. +func GetVar(name string, def ...interface{}) gvar.Var { return gvar.New(Get(name, def...)) } diff --git a/os/gcache/gcache.go b/os/gcache/gcache.go index 90b9c504d..056de54c8 100644 --- a/os/gcache/gcache.go +++ b/os/gcache/gcache.go @@ -40,8 +40,8 @@ func Get(key interface{}) interface{} { return cache.Get(key) } -// GetVar retrieves and returns the value of as *gvar.Var. -func GetVar(key interface{}) *gvar.Var { +// GetVar retrieves and returns the value of as gvar.Var. +func GetVar(key interface{}) gvar.Var { return cache.GetVar(key) } diff --git a/os/gcache/gcache_mem_cache.go b/os/gcache/gcache_mem_cache.go index 4afb5c321..a578b2875 100644 --- a/os/gcache/gcache_mem_cache.go +++ b/os/gcache/gcache_mem_cache.go @@ -223,8 +223,8 @@ func (c *memCache) Get(key interface{}) interface{} { return nil } -// GetVar retrieves and returns the value of as *gvar.Var. -func (c *memCache) GetVar(key interface{}) *gvar.Var { +// GetVar retrieves and returns the value of as gvar.Var. +func (c *memCache) GetVar(key interface{}) gvar.Var { return gvar.New(c.Get(key)) } diff --git a/os/gcfg/gcfg_api.go b/os/gcfg/gcfg_api.go index 9956f751f..b28bdce40 100644 --- a/os/gcfg/gcfg_api.go +++ b/os/gcfg/gcfg_api.go @@ -23,7 +23,7 @@ func (c *Config) Get(pattern string, def ...interface{}) interface{} { return nil } -func (c *Config) GetVar(pattern string, def ...interface{}) *gvar.Var { +func (c *Config) GetVar(pattern string, def ...interface{}) gvar.Var { if j := c.getJson(); j != nil { return gvar.New(j.Get(pattern, def...)) } diff --git a/os/gcmd/gcmd.go b/os/gcmd/gcmd.go index b40d8483b..eb7e2b934 100644 --- a/os/gcmd/gcmd.go +++ b/os/gcmd/gcmd.go @@ -51,8 +51,8 @@ func GetOpt(name string, def ...string) string { return "" } -// GetOptVar returns the option value named as *gvar.Var. -func GetOptVar(name string, def ...string) *gvar.Var { +// GetOptVar returns the option value named as gvar.Var. +func GetOptVar(name string, def ...string) gvar.Var { doInit() return gvar.New(GetOpt(name, def...)) } @@ -82,8 +82,8 @@ func GetArg(index int, def ...string) string { return "" } -// GetArgVar returns the argument at as *gvar.Var. -func GetArgVar(index int, def ...string) *gvar.Var { +// GetArgVar returns the argument at as gvar.Var. +func GetArgVar(index int, def ...string) gvar.Var { doInit() return gvar.New(GetArg(index, def...)) } diff --git a/os/gcmd/gcmd_parser.go b/os/gcmd/gcmd_parser.go index 73586ff24..d66a7fc6a 100644 --- a/os/gcmd/gcmd_parser.go +++ b/os/gcmd/gcmd_parser.go @@ -170,8 +170,8 @@ func (p *Parser) GetOpt(name string, def ...string) string { return "" } -// GetOptVar returns the option value named as *gvar.Var. -func (p *Parser) GetOptVar(name string, def ...interface{}) *gvar.Var { +// GetOptVar returns the option value named as gvar.Var. +func (p *Parser) GetOptVar(name string, def ...interface{}) gvar.Var { if p.ContainsOpt(name) { return gvar.New(p.GetOpt(name)) } @@ -203,8 +203,8 @@ func (p *Parser) GetArg(index int, def ...string) string { return "" } -// GetArgVar returns the argument at as *gvar.Var. -func (p *Parser) GetArgVar(index int, def ...string) *gvar.Var { +// GetArgVar returns the argument at as gvar.Var. +func (p *Parser) GetArgVar(index int, def ...string) gvar.Var { return gvar.New(p.GetArg(index, def...)) } diff --git a/os/genv/genv.go b/os/genv/genv.go index e8b2c183e..f7e16091e 100644 --- a/os/genv/genv.go +++ b/os/genv/genv.go @@ -43,7 +43,7 @@ func Get(key string, def ...string) string { // GetVar creates and returns a Var with the value of the environment variable // named by the . It uses the given if the variable does not exist // in the environment. -func GetVar(key string, def ...interface{}) *gvar.Var { +func GetVar(key string, def ...interface{}) gvar.Var { v, ok := os.LookupEnv(key) if !ok && len(def) > 0 { return gvar.New(def[0]) diff --git a/os/gsession/gsession_session.go b/os/gsession/gsession_session.go index 156033f36..23e163946 100644 --- a/os/gsession/gsession_session.go +++ b/os/gsession/gsession_session.go @@ -248,7 +248,7 @@ func (s *Session) Get(key string, def ...interface{}) interface{} { return nil } -func (s *Session) GetVar(key string, def ...interface{}) *gvar.Var { +func (s *Session) GetVar(key string, def ...interface{}) gvar.Var { return gvar.New(s.Get(key, def...), true) } diff --git a/util/gconv/gconv.go b/util/gconv/gconv.go index 791a4fd0e..a07992c4d 100644 --- a/util/gconv/gconv.go +++ b/util/gconv/gconv.go @@ -12,6 +12,7 @@ package gconv import ( "encoding/json" "fmt" + "github.com/gogf/gf/internal/intstore" "github.com/gogf/gf/os/gtime" "reflect" "strconv" @@ -251,6 +252,18 @@ func Convert(i interface{}, t string, params ...interface{}) interface{} { case "[]map[string]interface{}": return Maps(i) + case "gvar.Var": + rv := reflect.New(intstore.ReflectTypeVarImp) + ri := rv.Interface() + if v, ok := ri.(apiSet); ok { + v.Set(i) + } else if v, ok := ri.(apiUnmarshalValue); ok { + v.UnmarshalValue(i) + } else { + rv.Set(reflect.ValueOf(i)) + } + return ri + default: return i } diff --git a/util/gconv/gconv_interface.go b/util/gconv/gconv_interface.go index b10a600cf..77a22801c 100644 --- a/util/gconv/gconv_interface.go +++ b/util/gconv/gconv_interface.go @@ -51,3 +51,8 @@ type apiMapStrAny interface { type apiUnmarshalValue interface { UnmarshalValue(interface{}) error } + +// apiSet is the interface for custom value assignment. +type apiSet interface { + Set(value interface{}) (old interface{}) +} diff --git a/util/gconv/gconv_struct.go b/util/gconv/gconv_struct.go index 47375bd78..5d48e015a 100644 --- a/util/gconv/gconv_struct.go +++ b/util/gconv/gconv_struct.go @@ -241,34 +241,28 @@ func bindVarToStructAttr(elem reflect.Value, name string, value interface{}) (er return nil } -// bindVarToStructByIndex sets value to struct object attribute by index. -func bindVarToStructByIndex(elem reflect.Value, index int, value interface{}) (err error) { - structFieldValue := elem.FieldByIndex([]int{index}) - if !structFieldValue.IsValid() { - return nil - } - // CanSet checks whether attribute is public accessible. - if !structFieldValue.CanSet() { - return nil - } - // If any panic, it secondly uses reflect conversion and assignment. - defer func() { - if recover() != nil { - err = bindVarToReflectValue(structFieldValue, value) - } - }() - if empty.IsNil(value) { - structFieldValue.Set(reflect.Zero(structFieldValue.Type())) - } else { - // It firstly simply assigns the value to the attribute. - structFieldValue.Set(reflect.ValueOf(Convert(value, structFieldValue.Type().String()))) - } - return nil -} - // bindVarToReflectValue sets to reflect value object . func bindVarToReflectValue(structFieldValue reflect.Value, value interface{}) (err error) { - switch structFieldValue.Kind() { + kind := structFieldValue.Kind() + + // Converting using interface, for some kinds. + switch kind { + case reflect.Slice, reflect.Array, reflect.Ptr, reflect.Interface: + if !structFieldValue.IsNil() { + if v, ok := structFieldValue.Interface().(apiSet); ok { + v.Set(value) + return nil + } else if v, ok := structFieldValue.Interface().(apiUnmarshalValue); ok { + err = v.UnmarshalValue(value) + if err == nil { + return err + } + } + } + } + + // Converting by kind. + switch kind { case reflect.Struct: if err := Struct(value, structFieldValue); err != nil { // Note there's reflect conversion mechanism here.