add MarshalJSON function to implement the interface MarshalJSON for json.Marshal for gtype

This commit is contained in:
John
2019-09-29 15:59:09 +08:00
parent b830f9b96d
commit 47e74d27bf
21 changed files with 342 additions and 20 deletions

View File

@ -59,3 +59,12 @@ func (v *Bool) Cas(old, new bool) bool {
}
return atomic.CompareAndSwapInt32(&v.value, oldInt32, newInt32)
}
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
func (v *Bool) MarshalJSON() ([]byte, error) {
if v.Val() {
return []byte("true"), nil
} else {
return []byte("false"), nil
}
}

View File

@ -7,6 +7,8 @@
package gtype
import (
"github.com/gogf/gf/util/gconv"
"strconv"
"sync/atomic"
)
@ -49,3 +51,8 @@ func (v *Byte) Add(delta byte) (new byte) {
func (v *Byte) Cas(old, new byte) bool {
return atomic.CompareAndSwapInt32(&v.value, int32(old), int32(new))
}
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
func (v *Byte) MarshalJSON() ([]byte, error) {
return gconv.UnsafeStrToBytes(strconv.FormatUint(uint64(v.Val()), 10)), nil
}

View File

@ -6,7 +6,11 @@
package gtype
import "sync/atomic"
import (
"encoding/base64"
"github.com/gogf/gf/util/gconv"
"sync/atomic"
)
type Bytes struct {
value atomic.Value
@ -42,3 +46,11 @@ func (v *Bytes) Val() []byte {
}
return nil
}
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
func (v *Bytes) MarshalJSON() ([]byte, error) {
val := v.Val()
dst := make([]byte, base64.StdEncoding.EncodedLen(len(val)))
base64.StdEncoding.Encode(dst, val)
return gconv.UnsafeStrToBytes(`"` + gconv.UnsafeBytesToStr(dst) + `"`), nil
}

View File

@ -7,7 +7,9 @@
package gtype
import (
"github.com/gogf/gf/util/gconv"
"math"
"strconv"
"sync/atomic"
"unsafe"
)
@ -62,3 +64,8 @@ func (v *Float32) Add(delta float32) (new float32) {
func (v *Float32) Cas(old, new float32) bool {
return atomic.CompareAndSwapUint32(&v.value, uint32(old), uint32(new))
}
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
func (v *Float32) MarshalJSON() ([]byte, error) {
return gconv.UnsafeStrToBytes(strconv.FormatFloat(float64(v.Val()), 'f', -1, 32)), nil
}

View File

@ -7,7 +7,9 @@
package gtype
import (
"github.com/gogf/gf/util/gconv"
"math"
"strconv"
"sync/atomic"
"unsafe"
)
@ -62,3 +64,8 @@ func (v *Float64) Add(delta float64) (new float64) {
func (v *Float64) Cas(old, new float64) bool {
return atomic.CompareAndSwapUint64(&v.value, uint64(old), uint64(new))
}
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
func (v *Float64) MarshalJSON() ([]byte, error) {
return gconv.UnsafeStrToBytes(strconv.FormatFloat(v.Val(), 'f', -1, 64)), nil
}

View File

@ -7,8 +7,10 @@
// Package gtype provides kinds of high performance and concurrent-safe basic variable types.
package gtype
// Type is alias of Interface.
type Type = Interface
// New is alias of NewInterface.
// See NewInterface.
func New(value ...interface{}) *Type {
return NewInterface(value...)

View File

@ -7,6 +7,8 @@
package gtype
import (
"github.com/gogf/gf/util/gconv"
"strconv"
"sync/atomic"
)
@ -49,3 +51,8 @@ func (v *Int) Add(delta int) (new int) {
func (v *Int) Cas(old, new int) bool {
return atomic.CompareAndSwapInt64(&v.value, int64(old), int64(new))
}
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
func (v *Int) MarshalJSON() ([]byte, error) {
return gconv.UnsafeStrToBytes(strconv.Itoa(v.Val())), nil
}

View File

@ -7,6 +7,8 @@
package gtype
import (
"github.com/gogf/gf/util/gconv"
"strconv"
"sync/atomic"
)
@ -49,3 +51,8 @@ func (v *Int32) Add(delta int32) (new int32) {
func (v *Int32) Cas(old, new int32) bool {
return atomic.CompareAndSwapInt32(&v.value, old, new)
}
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
func (v *Int32) MarshalJSON() ([]byte, error) {
return gconv.UnsafeStrToBytes(strconv.Itoa(int(v.Val()))), nil
}

View File

@ -7,6 +7,8 @@
package gtype
import (
"github.com/gogf/gf/util/gconv"
"strconv"
"sync/atomic"
)
@ -49,3 +51,8 @@ func (v *Int64) Add(delta int64) (new int64) {
func (v *Int64) Cas(old, new int64) bool {
return atomic.CompareAndSwapInt64(&v.value, old, new)
}
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
func (v *Int64) MarshalJSON() ([]byte, error) {
return gconv.UnsafeStrToBytes(strconv.FormatInt(v.Val(), 10)), nil
}

View File

@ -7,6 +7,7 @@
package gtype
import (
"encoding/json"
"sync/atomic"
)
@ -41,3 +42,8 @@ func (v *Interface) Set(value interface{}) (old interface{}) {
func (v *Interface) Val() interface{} {
return v.value.Load()
}
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
func (v *Interface) MarshalJSON() ([]byte, error) {
return json.Marshal(v.Val())
}

View File

@ -7,6 +7,7 @@
package gtype
import (
"github.com/gogf/gf/util/gconv"
"sync/atomic"
)
@ -44,3 +45,8 @@ func (v *String) Val() string {
}
return ""
}
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
func (v *String) MarshalJSON() ([]byte, error) {
return gconv.UnsafeStrToBytes(`"` + v.Val() + `"`), nil
}

View File

@ -7,6 +7,8 @@
package gtype
import (
"github.com/gogf/gf/util/gconv"
"strconv"
"sync/atomic"
)
@ -49,3 +51,8 @@ func (v *Uint) Add(delta uint) (new uint) {
func (v *Uint) Cas(old, new uint) bool {
return atomic.CompareAndSwapUint64(&v.value, uint64(old), uint64(new))
}
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
func (v *Uint) MarshalJSON() ([]byte, error) {
return gconv.UnsafeStrToBytes(strconv.FormatUint(uint64(v.Val()), 10)), nil
}

View File

@ -7,6 +7,8 @@
package gtype
import (
"github.com/gogf/gf/util/gconv"
"strconv"
"sync/atomic"
)
@ -49,3 +51,8 @@ func (v *Uint32) Add(delta uint32) (new uint32) {
func (v *Uint32) Cas(old, new uint32) bool {
return atomic.CompareAndSwapUint32(&v.value, old, new)
}
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
func (v *Uint32) MarshalJSON() ([]byte, error) {
return gconv.UnsafeStrToBytes(strconv.FormatUint(uint64(v.Val()), 10)), nil
}

View File

@ -7,6 +7,8 @@
package gtype
import (
"github.com/gogf/gf/util/gconv"
"strconv"
"sync/atomic"
)
@ -49,3 +51,8 @@ func (v *Uint64) Add(delta uint64) (new uint64) {
func (v *Uint64) Cas(old, new uint64) bool {
return atomic.CompareAndSwapUint64(&v.value, old, new)
}
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
func (v *Uint64) MarshalJSON() ([]byte, error) {
return gconv.UnsafeStrToBytes(strconv.FormatUint(v.Val(), 10)), nil
}

View File

@ -16,18 +16,19 @@ import (
"github.com/gogf/gf/encoding/gbinary"
)
var it = NewInt()
var it32 = NewInt32()
var it64 = NewInt64()
var uit = NewUint()
var uit32 = NewUint32()
var uit64 = NewUint64()
var bl = NewBool()
var bytes = NewBytes()
var str = NewString()
var inf = NewInterface()
var at = atomic.Value{}
var (
it = NewInt()
it32 = NewInt32()
it64 = NewInt64()
uit = NewUint()
uit32 = NewUint32()
uit64 = NewUint64()
bl = NewBool()
bytes = NewBytes()
str = NewString()
inf = NewInterface()
at = atomic.Value{}
)
func BenchmarkInt_Set(b *testing.B) {
for i := 0; i < b.N; i++ {

View File

@ -0,0 +1,103 @@
// Copyright 2018 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.
// go test *.go -bench=".+\_Json" -benchmem
package gtype_test
import (
"encoding/json"
"github.com/gogf/gf/container/gtype"
"testing"
)
var (
vBool = gtype.NewBool()
vByte = gtype.NewByte()
vBytes = gtype.NewBytes()
vFloat32 = gtype.NewFloat32()
vFloat64 = gtype.NewFloat64()
vInt = gtype.NewInt()
vInt32 = gtype.NewInt32()
vInt64 = gtype.NewInt64()
vInterface = gtype.NewInterface()
vString = gtype.NewString()
vUint = gtype.NewUint()
vUint32 = gtype.NewUint32()
vUint64 = gtype.NewUint64()
)
func Benchmark_Bool_Json(b *testing.B) {
for i := 0; i < b.N; i++ {
json.Marshal(vBool)
}
}
func Benchmark_Byte_Json(b *testing.B) {
for i := 0; i < b.N; i++ {
json.Marshal(vByte)
}
}
func Benchmark_Bytes_Json(b *testing.B) {
for i := 0; i < b.N; i++ {
json.Marshal(vBytes)
}
}
func Benchmark_Float32_Json(b *testing.B) {
for i := 0; i < b.N; i++ {
json.Marshal(vFloat32)
}
}
func Benchmark_Float64_Json(b *testing.B) {
for i := 0; i < b.N; i++ {
json.Marshal(vFloat64)
}
}
func Benchmark_Int_Json(b *testing.B) {
for i := 0; i < b.N; i++ {
json.Marshal(vInt)
}
}
func Benchmark_Int32_Json(b *testing.B) {
for i := 0; i < b.N; i++ {
json.Marshal(vInt32)
}
}
func Benchmark_Int64_Json(b *testing.B) {
for i := 0; i < b.N; i++ {
json.Marshal(vInt64)
}
}
func Benchmark_Interface_Json(b *testing.B) {
for i := 0; i < b.N; i++ {
json.Marshal(vInterface)
}
}
func Benchmark_String_Json(b *testing.B) {
for i := 0; i < b.N; i++ {
json.Marshal(vString)
}
}
func Benchmark_Uint_Json(b *testing.B) {
for i := 0; i < b.N; i++ {
json.Marshal(vUint)
}
}
func Benchmark_Uint32_Json(b *testing.B) {
for i := 0; i < b.N; i++ {
json.Marshal(vUint64)
}
}

View File

@ -7,6 +7,7 @@
package gtype_test
import (
"encoding/json"
"sync"
"testing"
@ -35,6 +36,24 @@ func Test_Bool(t *testing.T) {
i2 := gtype.NewBool()
gtest.AssertEQ(i2.Val(), false)
})
gtest.Case(t, func() {
i := gtype.NewBool(true)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
})
gtest.Case(t, func() {
i := gtype.NewBool(false)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
})
}
func Test_Byte(t *testing.T) {
@ -59,6 +78,14 @@ func Test_Byte(t *testing.T) {
i1 := gtype.NewByte()
gtest.AssertEQ(i1.Val(), byte(0))
})
gtest.Case(t, func() {
i := gtype.NewByte(254)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
})
}
func Test_Bytes(t *testing.T) {
@ -72,6 +99,14 @@ func Test_Bytes(t *testing.T) {
i1 := gtype.NewBytes()
gtest.AssertEQ(i1.Val(), nil)
})
gtest.Case(t, func() {
i := gtype.NewBytes([]byte("i love gf"))
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
})
}
func Test_String(t *testing.T) {
@ -85,6 +120,14 @@ func Test_String(t *testing.T) {
i1 := gtype.NewString()
gtest.AssertEQ(i1.Val(), "")
})
gtest.Case(t, func() {
i := gtype.NewString("i love gf")
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
})
}
func Test_Interface(t *testing.T) {
@ -100,6 +143,14 @@ func Test_Interface(t *testing.T) {
i1 := gtype.New()
gtest.AssertEQ(i1.Val(), nil)
})
gtest.Case(t, func() {
i := gtype.New("i love gf")
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
})
}
func Test_Float32(t *testing.T) {
@ -125,6 +176,14 @@ func Test_Float32(t *testing.T) {
i1 := gtype.NewFloat32()
gtest.AssertEQ(i1.Val(), float32(0))
})
gtest.Case(t, func() {
i := gtype.NewFloat32(3.333)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
})
}
func Test_Float64(t *testing.T) {
@ -150,6 +209,14 @@ func Test_Float64(t *testing.T) {
i1 := gtype.NewFloat64()
gtest.AssertEQ(i1.Val(), float64(0))
})
gtest.Case(t, func() {
i := gtype.NewFloat64(3.333)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
})
}
func Test_Int(t *testing.T) {
@ -174,6 +241,14 @@ func Test_Int(t *testing.T) {
i1 := gtype.NewInt()
gtest.AssertEQ(i1.Val(), 0)
})
gtest.Case(t, func() {
i := gtype.NewInt(666)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
})
}
func Test_Int32(t *testing.T) {
@ -198,6 +273,14 @@ func Test_Int32(t *testing.T) {
i1 := gtype.NewInt32()
gtest.AssertEQ(i1.Val(), int32(0))
})
gtest.Case(t, func() {
i := gtype.NewInt32(666)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
})
}
func Test_Int64(t *testing.T) {
@ -222,6 +305,14 @@ func Test_Int64(t *testing.T) {
i1 := gtype.NewInt64()
gtest.AssertEQ(i1.Val(), int64(0))
})
gtest.Case(t, func() {
i := gtype.NewInt64(666)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
})
}
func Test_Uint(t *testing.T) {
@ -246,6 +337,14 @@ func Test_Uint(t *testing.T) {
i1 := gtype.NewUint()
gtest.AssertEQ(i1.Val(), uint(0))
})
gtest.Case(t, func() {
i := gtype.NewUint(666)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
})
}
func Test_Uint32(t *testing.T) {
@ -270,6 +369,14 @@ func Test_Uint32(t *testing.T) {
i1 := gtype.NewUint32()
gtest.AssertEQ(i1.Val(), uint32(0))
})
gtest.Case(t, func() {
i := gtype.NewUint32(666)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
})
}
func Test_Uint64(t *testing.T) {
@ -294,4 +401,12 @@ func Test_Uint64(t *testing.T) {
i1 := gtype.NewUint64()
gtest.AssertEQ(i1.Val(), uint64(0))
})
gtest.Case(t, func() {
i := gtype.NewUint64(666)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
})
}

View File

@ -9,6 +9,7 @@ package gbase64
import (
"encoding/base64"
"github.com/gogf/gf/util/gconv"
)
// Encode encodes bytes with BASE64 algorithm.
@ -32,7 +33,7 @@ func EncodeString(src string) string {
// EncodeToString encodes bytes to string with BASE64 algorithm.
func EncodeToString(src []byte) string {
return string(Encode(src))
return gconv.UnsafeBytesToStr(Encode(src))
}
// DecodeString decodes string with BASE64 algorithm.
@ -43,5 +44,5 @@ func DecodeString(str string) ([]byte, error) {
// DecodeString decodes string with BASE64 algorithm.
func DecodeToString(str string) (string, error) {
b, err := DecodeString(str)
return string(b), err
return gconv.UnsafeBytesToStr(b), err
}

View File

@ -135,7 +135,7 @@ func LeEncodeInt8(i int8) []byte {
}
func LeEncodeUint8(i uint8) []byte {
return []byte{byte(i)}
return []byte{i}
}
func LeEncodeInt16(i int16) []byte {

View File

@ -114,7 +114,7 @@ func Byte(i interface{}) byte {
if v, ok := i.(byte); ok {
return v
}
return byte(Uint8(i))
return Uint8(i)
}
// Bytes converts <i> to []byte.
@ -155,7 +155,7 @@ func String(i interface{}) string {
}
switch value := i.(type) {
case int:
return strconv.FormatInt(int64(value), 10)
return strconv.Itoa(value)
case int8:
return strconv.Itoa(int(value))
case int16:
@ -163,7 +163,7 @@ func String(i interface{}) string {
case int32:
return strconv.Itoa(int(value))
case int64:
return strconv.FormatInt(int64(value), 10)
return strconv.FormatInt(value, 10)
case uint:
return strconv.FormatUint(uint64(value), 10)
case uint8:
@ -173,7 +173,7 @@ func String(i interface{}) string {
case uint32:
return strconv.FormatUint(uint64(value), 10)
case uint64:
return strconv.FormatUint(uint64(value), 10)
return strconv.FormatUint(value, 10)
case float32:
return strconv.FormatFloat(float64(value), 'f', -1, 32)
case float64:

View File

@ -9,11 +9,15 @@ package gconv
import "unsafe"
// UnsafeStrToBytes converts string to []byte without memory copy.
// Note that, if you completely sure you will never use <s> in the feature,
// you can use this unsafe function to implement type conversion in high performance.
func UnsafeStrToBytes(s string) []byte {
return *(*[]byte)(unsafe.Pointer(&s))
}
// UnsafeBytesToStr converts []byte to string without memory copy.
// Note that, if you completely sure you will never use <s> in the feature,
// you can use this unsafe function to implement type conversion in high performance.
func UnsafeBytesToStr(b []byte) string {
return *(*string)(unsafe.Pointer(&b))
}