mirror of
https://gitee.com/johng/gf
synced 2026-06-09 02:57:43 +08:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 75725db6fb | |||
| 5cd8475143 | |||
| 5629f37939 | |||
| 08ec04d8b6 | |||
| c0b46f364a | |||
| 8c5f74e8bb | |||
| 94832262e3 | |||
| aefbfd52e9 | |||
| f3f0689bd4 |
@ -12,74 +12,74 @@ import (
|
||||
"github.com/gogf/gf/g/internal/rwmutex"
|
||||
)
|
||||
|
||||
type LinkMap struct {
|
||||
type ListMap struct {
|
||||
mu *rwmutex.RWMutex
|
||||
data map[interface{}]*glist.Element
|
||||
list *glist.List
|
||||
}
|
||||
|
||||
type gLinkMapNode struct {
|
||||
type gListMapNode struct {
|
||||
key interface{}
|
||||
value interface{}
|
||||
}
|
||||
|
||||
// NewLinkMap returns an empty link map.
|
||||
// LinkMap is backed by a hash table to store values and doubly-linked list to store ordering.
|
||||
// NewListMap returns an empty link map.
|
||||
// ListMap is backed by a hash table to store values and doubly-linked list to store ordering.
|
||||
// The param <unsafe> used to specify whether using map in un-concurrent-safety,
|
||||
// which is false in default, means concurrent-safe.
|
||||
func NewLinkMap(unsafe ...bool) *LinkMap {
|
||||
return &LinkMap{
|
||||
func NewListMap(unsafe ...bool) *ListMap {
|
||||
return &ListMap{
|
||||
mu : rwmutex.New(unsafe...),
|
||||
data : make(map[interface{}]*glist.Element),
|
||||
list : glist.New(true),
|
||||
}
|
||||
}
|
||||
|
||||
// NewLinkMapFrom returns a link map from given map <data>.
|
||||
// NewListMapFrom returns a link map from given map <data>.
|
||||
// Note that, the param <data> map will be set as the underlying data map(no deep copy),
|
||||
// there might be some concurrent-safe issues when changing the map outside.
|
||||
func NewLinkMapFrom(data map[interface{}]interface{}, unsafe...bool) *LinkMap {
|
||||
m := NewLinkMap(unsafe...)
|
||||
func NewListMapFrom(data map[interface{}]interface{}, unsafe...bool) *ListMap {
|
||||
m := NewListMap(unsafe...)
|
||||
m.Sets(data)
|
||||
return m
|
||||
}
|
||||
|
||||
// Iterator is alias of IteratorAsc.
|
||||
func (m *LinkMap) Iterator(f func (key, value interface{}) bool) {
|
||||
func (m *ListMap) Iterator(f func (key, value interface{}) bool) {
|
||||
m.IteratorAsc(f)
|
||||
}
|
||||
|
||||
// IteratorAsc iterates the map in ascending order with given callback function <f>.
|
||||
// If <f> returns true, then it continues iterating; or false to stop.
|
||||
func (m *LinkMap) IteratorAsc(f func (key interface{}, value interface{}) bool) {
|
||||
func (m *ListMap) IteratorAsc(f func (key interface{}, value interface{}) bool) {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
node := (*gLinkMapNode)(nil)
|
||||
node := (*gListMapNode)(nil)
|
||||
m.list.IteratorAsc(func(e *glist.Element) bool {
|
||||
node = e.Value.(*gLinkMapNode)
|
||||
node = e.Value.(*gListMapNode)
|
||||
return f(node.key, node.value)
|
||||
})
|
||||
}
|
||||
|
||||
// IteratorDesc iterates the map in descending order with given callback function <f>.
|
||||
// If <f> returns true, then it continues iterating; or false to stop.
|
||||
func (m *LinkMap) IteratorDesc(f func (key interface{}, value interface{}) bool) {
|
||||
func (m *ListMap) IteratorDesc(f func (key interface{}, value interface{}) bool) {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
node := (*gLinkMapNode)(nil)
|
||||
node := (*gListMapNode)(nil)
|
||||
m.list.IteratorDesc(func(e *glist.Element) bool {
|
||||
node = e.Value.(*gLinkMapNode)
|
||||
node = e.Value.(*gListMapNode)
|
||||
return f(node.key, node.value)
|
||||
})
|
||||
}
|
||||
|
||||
// Clone returns a new link map with copy of current map data.
|
||||
func (m *LinkMap) Clone(unsafe ...bool) *LinkMap {
|
||||
return NewLinkMapFrom(m.Map(), unsafe ...)
|
||||
func (m *ListMap) Clone(unsafe ...bool) *ListMap {
|
||||
return NewListMapFrom(m.Map(), unsafe ...)
|
||||
}
|
||||
|
||||
// Clear deletes all data of the map, it will remake a new underlying data map.
|
||||
func (m *LinkMap) Clear() {
|
||||
func (m *ListMap) Clear() {
|
||||
m.mu.Lock()
|
||||
m.data = make(map[interface{}]*glist.Element)
|
||||
m.list = glist.New(true)
|
||||
@ -87,12 +87,12 @@ func (m *LinkMap) Clear() {
|
||||
}
|
||||
|
||||
// Map returns a copy of the data of the map.
|
||||
func (m *LinkMap) Map() map[interface{}]interface{} {
|
||||
func (m *ListMap) Map() map[interface{}]interface{} {
|
||||
m.mu.RLock()
|
||||
node := (*gLinkMapNode)(nil)
|
||||
node := (*gListMapNode)(nil)
|
||||
data := make(map[interface{}]interface{}, len(m.data))
|
||||
m.list.IteratorAsc(func(e *glist.Element) bool {
|
||||
node = e.Value.(*gLinkMapNode)
|
||||
node = e.Value.(*gListMapNode)
|
||||
data[node.key] = node.value
|
||||
return true
|
||||
})
|
||||
@ -101,24 +101,24 @@ func (m *LinkMap) Map() map[interface{}]interface{} {
|
||||
}
|
||||
|
||||
// Set sets key-value to the map.
|
||||
func (m *LinkMap) Set(key interface{}, value interface{}) {
|
||||
func (m *ListMap) Set(key interface{}, value interface{}) {
|
||||
m.mu.Lock()
|
||||
if e, ok := m.data[key]; !ok {
|
||||
m.data[key] = m.list.PushBack(&gLinkMapNode{key, value})
|
||||
m.data[key] = m.list.PushBack(&gListMapNode{key, value})
|
||||
} else {
|
||||
e.Value = &gLinkMapNode{key, value}
|
||||
e.Value = &gListMapNode{key, value}
|
||||
}
|
||||
m.mu.Unlock()
|
||||
}
|
||||
|
||||
// Sets batch sets key-values to the map.
|
||||
func (m *LinkMap) Sets(data map[interface{}]interface{}) {
|
||||
func (m *ListMap) Sets(data map[interface{}]interface{}) {
|
||||
m.mu.Lock()
|
||||
for key, value := range data {
|
||||
if e, ok := m.data[key]; !ok {
|
||||
m.data[key] = m.list.PushBack(&gLinkMapNode{key, value})
|
||||
m.data[key] = m.list.PushBack(&gListMapNode{key, value})
|
||||
} else {
|
||||
e.Value = &gLinkMapNode{key, value}
|
||||
e.Value = &gListMapNode{key, value}
|
||||
}
|
||||
}
|
||||
m.mu.Unlock()
|
||||
@ -126,10 +126,10 @@ func (m *LinkMap) Sets(data map[interface{}]interface{}) {
|
||||
|
||||
// Search searches the map with given <key>.
|
||||
// Second return parameter <found> is true if key was found, otherwise false.
|
||||
func (m *LinkMap) Search(key interface{}) (value interface{}, found bool) {
|
||||
func (m *ListMap) Search(key interface{}) (value interface{}, found bool) {
|
||||
m.mu.RLock()
|
||||
if e, ok := m.data[key]; ok {
|
||||
value = e.Value.(*gLinkMapNode).value
|
||||
value = e.Value.(*gListMapNode).value
|
||||
found = ok
|
||||
}
|
||||
m.mu.RUnlock()
|
||||
@ -137,10 +137,10 @@ func (m *LinkMap) Search(key interface{}) (value interface{}, found bool) {
|
||||
}
|
||||
|
||||
// Get returns the value by given <key>.
|
||||
func (m *LinkMap) Get(key interface{}) (value interface{}) {
|
||||
func (m *ListMap) Get(key interface{}) (value interface{}) {
|
||||
m.mu.RLock()
|
||||
if e, ok := m.data[key]; ok {
|
||||
value = e.Value.(*gLinkMapNode).value
|
||||
value = e.Value.(*gListMapNode).value
|
||||
}
|
||||
m.mu.RUnlock()
|
||||
return
|
||||
@ -155,22 +155,22 @@ func (m *LinkMap) Get(key interface{}) (value interface{}) {
|
||||
// and its return value will be set to the map with <key>.
|
||||
//
|
||||
// It returns value with given <key>.
|
||||
func (m *LinkMap) doSetWithLockCheck(key interface{}, value interface{}) interface{} {
|
||||
func (m *ListMap) doSetWithLockCheck(key interface{}, value interface{}) interface{} {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if e, ok := m.data[key]; ok {
|
||||
return e.Value.(*gLinkMapNode).value
|
||||
return e.Value.(*gListMapNode).value
|
||||
}
|
||||
if f, ok := value.(func() interface {}); ok {
|
||||
value = f()
|
||||
}
|
||||
m.data[key] = m.list.PushBack(&gLinkMapNode{key, value})
|
||||
m.data[key] = m.list.PushBack(&gListMapNode{key, value})
|
||||
return value
|
||||
}
|
||||
|
||||
// GetOrSet returns the value by key,
|
||||
// or set value with given <value> if not exist and returns this value.
|
||||
func (m *LinkMap) GetOrSet(key interface{}, value interface{}) interface{} {
|
||||
func (m *ListMap) GetOrSet(key interface{}, value interface{}) interface{} {
|
||||
if v, ok := m.Search(key); !ok {
|
||||
return m.doSetWithLockCheck(key, value)
|
||||
} else {
|
||||
@ -181,7 +181,7 @@ func (m *LinkMap) GetOrSet(key interface{}, value interface{}) interface{} {
|
||||
// GetOrSetFunc returns the value by key,
|
||||
// or sets value with return value of callback function <f> if not exist
|
||||
// and returns this value.
|
||||
func (m *LinkMap) GetOrSetFunc(key interface{}, f func() interface{}) interface{} {
|
||||
func (m *ListMap) GetOrSetFunc(key interface{}, f func() interface{}) interface{} {
|
||||
if v, ok := m.Search(key); !ok {
|
||||
return m.doSetWithLockCheck(key, f())
|
||||
} else {
|
||||
@ -195,7 +195,7 @@ func (m *LinkMap) GetOrSetFunc(key interface{}, f func() interface{}) interface{
|
||||
//
|
||||
// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function <f>
|
||||
// with mutex.Lock of the map.
|
||||
func (m *LinkMap) GetOrSetFuncLock(key interface{}, f func() interface{}) interface{} {
|
||||
func (m *ListMap) GetOrSetFuncLock(key interface{}, f func() interface{}) interface{} {
|
||||
if v, ok := m.Search(key); !ok {
|
||||
return m.doSetWithLockCheck(key, f)
|
||||
} else {
|
||||
@ -205,31 +205,31 @@ func (m *LinkMap) GetOrSetFuncLock(key interface{}, f func() interface{}) interf
|
||||
|
||||
// GetVar returns a gvar.Var with the value by given <key>.
|
||||
// The returned gvar.Var is un-concurrent safe.
|
||||
func (m *LinkMap) GetVar(key interface{}) *gvar.Var {
|
||||
func (m *ListMap) GetVar(key interface{}) *gvar.Var {
|
||||
return gvar.New(m.Get(key), true)
|
||||
}
|
||||
|
||||
// GetVarOrSet returns a gvar.Var with result from GetVarOrSet.
|
||||
// The returned gvar.Var is un-concurrent safe.
|
||||
func (m *LinkMap) GetVarOrSet(key interface{}, value interface{}) *gvar.Var {
|
||||
func (m *ListMap) GetVarOrSet(key interface{}, value interface{}) *gvar.Var {
|
||||
return gvar.New(m.GetOrSet(key, value), true)
|
||||
}
|
||||
|
||||
// GetVarOrSetFunc returns a gvar.Var with result from GetOrSetFunc.
|
||||
// The returned gvar.Var is un-concurrent safe.
|
||||
func (m *LinkMap) 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), true)
|
||||
}
|
||||
|
||||
// GetVarOrSetFuncLock returns a gvar.Var with result from GetOrSetFuncLock.
|
||||
// The returned gvar.Var is un-concurrent safe.
|
||||
func (m *LinkMap) 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), true)
|
||||
}
|
||||
|
||||
// SetIfNotExist sets <value> to the map if the <key> does not exist, then return true.
|
||||
// It returns false if <key> exists, and <value> would be ignored.
|
||||
func (m *LinkMap) SetIfNotExist(key interface{}, value interface{}) bool {
|
||||
func (m *ListMap) SetIfNotExist(key interface{}, value interface{}) bool {
|
||||
if !m.Contains(key) {
|
||||
m.doSetWithLockCheck(key, value)
|
||||
return true
|
||||
@ -239,7 +239,7 @@ func (m *LinkMap) SetIfNotExist(key interface{}, value interface{}) bool {
|
||||
|
||||
// SetIfNotExistFunc sets value with return value of callback function <f>, then return true.
|
||||
// It returns false if <key> exists, and <value> would be ignored.
|
||||
func (m *LinkMap) SetIfNotExistFunc(key interface{}, f func() interface{}) bool {
|
||||
func (m *ListMap) SetIfNotExistFunc(key interface{}, f func() interface{}) bool {
|
||||
if !m.Contains(key) {
|
||||
m.doSetWithLockCheck(key, f())
|
||||
return true
|
||||
@ -252,7 +252,7 @@ func (m *LinkMap) SetIfNotExistFunc(key interface{}, f func() interface{}) bool
|
||||
//
|
||||
// SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that
|
||||
// it executes function <f> with mutex.Lock of the map.
|
||||
func (m *LinkMap) SetIfNotExistFuncLock(key interface{}, f func() interface{}) bool {
|
||||
func (m *ListMap) SetIfNotExistFuncLock(key interface{}, f func() interface{}) bool {
|
||||
if !m.Contains(key) {
|
||||
m.doSetWithLockCheck(key, f)
|
||||
return true
|
||||
@ -261,10 +261,10 @@ func (m *LinkMap) SetIfNotExistFuncLock(key interface{}, f func() interface{}) b
|
||||
}
|
||||
|
||||
// Remove deletes value from map by given <key>, and return this deleted value.
|
||||
func (m *LinkMap) Remove(key interface{}) (value interface{}) {
|
||||
func (m *ListMap) Remove(key interface{}) (value interface{}) {
|
||||
m.mu.Lock()
|
||||
if e, ok := m.data[key]; ok {
|
||||
value = e.Value.(*gLinkMapNode).value
|
||||
value = e.Value.(*gListMapNode).value
|
||||
delete(m.data, key)
|
||||
m.list.Remove(e)
|
||||
}
|
||||
@ -273,7 +273,7 @@ func (m *LinkMap) Remove(key interface{}) (value interface{}) {
|
||||
}
|
||||
|
||||
// Removes batch deletes values of the map by keys.
|
||||
func (m *LinkMap) Removes(keys []interface{}) {
|
||||
func (m *ListMap) Removes(keys []interface{}) {
|
||||
m.mu.Lock()
|
||||
for _, key := range keys {
|
||||
if e, ok := m.data[key]; ok {
|
||||
@ -285,12 +285,12 @@ func (m *LinkMap) Removes(keys []interface{}) {
|
||||
}
|
||||
|
||||
// Keys returns all keys of the map as a slice in ascending order.
|
||||
func (m *LinkMap) Keys() []interface{} {
|
||||
func (m *ListMap) Keys() []interface{} {
|
||||
m.mu.RLock()
|
||||
keys := make([]interface{}, m.list.Len())
|
||||
index := 0
|
||||
m.list.IteratorAsc(func(e *glist.Element) bool {
|
||||
keys[index] = e.Value.(*gLinkMapNode).key
|
||||
keys[index] = e.Value.(*gListMapNode).key
|
||||
index++
|
||||
return true
|
||||
})
|
||||
@ -299,12 +299,12 @@ func (m *LinkMap) Keys() []interface{} {
|
||||
}
|
||||
|
||||
// Values returns all values of the map as a slice.
|
||||
func (m *LinkMap) Values() []interface{} {
|
||||
func (m *ListMap) Values() []interface{} {
|
||||
m.mu.RLock()
|
||||
values := make([]interface{}, m.list.Len())
|
||||
index := 0
|
||||
m.list.IteratorAsc(func(e *glist.Element) bool {
|
||||
values[index] = e.Value.(*gLinkMapNode).value
|
||||
values[index] = e.Value.(*gListMapNode).value
|
||||
index++
|
||||
return true
|
||||
})
|
||||
@ -314,7 +314,7 @@ func (m *LinkMap) Values() []interface{} {
|
||||
|
||||
// Contains checks whether a key exists.
|
||||
// It returns true if the <key> exists, or else false.
|
||||
func (m *LinkMap) Contains(key interface{}) (ok bool) {
|
||||
func (m *ListMap) Contains(key interface{}) (ok bool) {
|
||||
m.mu.RLock()
|
||||
_, ok = m.data[key]
|
||||
m.mu.RUnlock()
|
||||
@ -322,7 +322,7 @@ func (m *LinkMap) Contains(key interface{}) (ok bool) {
|
||||
}
|
||||
|
||||
// Size returns the size of the map.
|
||||
func (m *LinkMap) Size() (size int) {
|
||||
func (m *ListMap) Size() (size int) {
|
||||
m.mu.RLock()
|
||||
size = len(m.data)
|
||||
m.mu.RUnlock()
|
||||
@ -331,12 +331,12 @@ func (m *LinkMap) Size() (size int) {
|
||||
|
||||
// IsEmpty checks whether the map is empty.
|
||||
// It returns true if map is empty, or else false.
|
||||
func (m *LinkMap) IsEmpty() bool {
|
||||
func (m *ListMap) IsEmpty() bool {
|
||||
return m.Size() == 0
|
||||
}
|
||||
|
||||
// Flip exchanges key-value of the map to value-key.
|
||||
func (m *LinkMap) Flip() {
|
||||
func (m *ListMap) Flip() {
|
||||
data := m.Map()
|
||||
m.Clear()
|
||||
for key, value := range data {
|
||||
@ -346,20 +346,20 @@ func (m *LinkMap) Flip() {
|
||||
|
||||
// Merge merges two link maps.
|
||||
// The <other> map will be merged into the map <m>.
|
||||
func (m *LinkMap) Merge(other *LinkMap) {
|
||||
func (m *ListMap) Merge(other *ListMap) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if other != m {
|
||||
other.mu.RLock()
|
||||
defer other.mu.RUnlock()
|
||||
}
|
||||
node := (*gLinkMapNode)(nil)
|
||||
node := (*gListMapNode)(nil)
|
||||
other.list.IteratorAsc(func(e *glist.Element) bool {
|
||||
node = e.Value.(*gLinkMapNode)
|
||||
node = e.Value.(*gListMapNode)
|
||||
if e, ok := m.data[node.key]; !ok {
|
||||
m.data[node.key] = m.list.PushBack(&gLinkMapNode{node.key, node.value})
|
||||
m.data[node.key] = m.list.PushBack(&gListMapNode{node.key, node.value})
|
||||
} else {
|
||||
e.Value = &gLinkMapNode{node.key, node.value}
|
||||
e.Value = &gListMapNode{node.key, node.value}
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
55
g/container/gmap/gmap_z_bench_maps_test.go
Normal file
55
g/container/gmap/gmap_z_bench_maps_test.go
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright 2017 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 gm file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
// go test *.go -bench=".*" -benchmem
|
||||
|
||||
package gmap_test
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/container/gmap"
|
||||
"github.com/gogf/gf/g/util/gutil"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var hashMap = gmap.New()
|
||||
var listMap = gmap.NewListMap()
|
||||
var treeMap = gmap.NewTreeMap(gutil.ComparatorInt)
|
||||
|
||||
func Benchmark_HashMap_Set(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
hashMap.Set(i, i)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_ListMap_Set(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
listMap.Set(i, i)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_TreeMap_Set(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
treeMap.Set(i, i)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_HashMap_Get(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
hashMap.Get(i)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_ListMap_Get(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
listMap.Get(i)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_TreeMap_Get(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
treeMap.Get(i)
|
||||
}
|
||||
}
|
||||
@ -6,21 +6,21 @@
|
||||
|
||||
// go test *.go -bench=".*" -benchmem
|
||||
|
||||
package gmap
|
||||
package gmap_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"github.com/gogf/gf/g/container/gmap"
|
||||
"testing"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
|
||||
var iim = NewIntIntMap()
|
||||
var iifm = NewIntAnyMap()
|
||||
var ism = NewIntStrMap()
|
||||
var ififm = New()
|
||||
var sim = NewStrIntMap()
|
||||
var sifm = NewStrAnyMap()
|
||||
var ssm = NewStrStrMap()
|
||||
var ififm = gmap.New()
|
||||
var iim = gmap.NewIntIntMap()
|
||||
var iifm = gmap.NewIntAnyMap()
|
||||
var ism = gmap.NewIntStrMap()
|
||||
var sim = gmap.NewStrIntMap()
|
||||
var sifm = gmap.NewStrAnyMap()
|
||||
var ssm = gmap.NewStrStrMap()
|
||||
|
||||
func Benchmark_IntIntMap_Set(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
|
||||
@ -6,21 +6,21 @@
|
||||
|
||||
// go test *.go -bench=".*" -benchmem
|
||||
|
||||
package gmap
|
||||
package gmap_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"github.com/gogf/gf/g/container/gmap"
|
||||
"testing"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
|
||||
var iimUnsafe = NewIntIntMap(true)
|
||||
var iifmUnsafe = NewIntAnyMap(true)
|
||||
var ismUnsafe = NewIntStrMap(true)
|
||||
var ififmUnsafe = New(true)
|
||||
var simUnsafe = NewStrIntMap(true)
|
||||
var sifmUnsafe = NewStrAnyMap(true)
|
||||
var ssmUnsafe = NewStrStrMap(true)
|
||||
var ififmUnsafe = gmap.New(true)
|
||||
var iimUnsafe = gmap.NewIntIntMap(true)
|
||||
var iifmUnsafe = gmap.NewIntAnyMap(true)
|
||||
var ismUnsafe = gmap.NewIntStrMap(true)
|
||||
var simUnsafe = gmap.NewStrIntMap(true)
|
||||
var sifmUnsafe = gmap.NewStrAnyMap(true)
|
||||
var ssmUnsafe = gmap.NewStrStrMap(true)
|
||||
|
||||
// 写入性能测试
|
||||
|
||||
|
||||
@ -13,9 +13,9 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_Link_Map_Basic(t *testing.T) {
|
||||
func Test_List_Map_Basic(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
m := gmap.NewLinkMap()
|
||||
m := gmap.NewListMap()
|
||||
m.Set("key1", "val1")
|
||||
gtest.Assert(m.Keys(), []interface{}{"key1"})
|
||||
|
||||
@ -43,12 +43,12 @@ func Test_Link_Map_Basic(t *testing.T) {
|
||||
gtest.Assert(m.Size(), 0)
|
||||
gtest.Assert(m.IsEmpty(), true)
|
||||
|
||||
m2 := gmap.NewLinkMapFrom(map[interface{}]interface{}{1: 1, "key1": "val1"})
|
||||
m2 := gmap.NewListMapFrom(map[interface{}]interface{}{1: 1, "key1": "val1"})
|
||||
gtest.Assert(m2.Map(), map[interface{}]interface{}{1: 1, "key1": "val1"})
|
||||
})
|
||||
}
|
||||
func Test_Link_Map_Set_Fun(t *testing.T) {
|
||||
m := gmap.NewLinkMap()
|
||||
func Test_List_Map_Set_Fun(t *testing.T) {
|
||||
m := gmap.NewListMap()
|
||||
m.GetOrSetFunc("fun", getValue)
|
||||
m.GetOrSetFuncLock("funlock", getValue)
|
||||
gtest.Assert(m.Get("funlock"), 3)
|
||||
@ -58,17 +58,17 @@ func Test_Link_Map_Set_Fun(t *testing.T) {
|
||||
gtest.Assert(m.SetIfNotExistFuncLock("funlock", getValue), false)
|
||||
}
|
||||
|
||||
func Test_Link_Map_Batch(t *testing.T) {
|
||||
m := gmap.NewLinkMap()
|
||||
func Test_List_Map_Batch(t *testing.T) {
|
||||
m := gmap.NewListMap()
|
||||
m.Sets(map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
|
||||
gtest.Assert(m.Map(), map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
|
||||
m.Removes([]interface{}{"key1", 1})
|
||||
gtest.Assert(m.Map(), map[interface{}]interface{}{"key2": "val2", "key3": "val3"})
|
||||
}
|
||||
func Test_Link_Map_Iterator(t *testing.T){
|
||||
func Test_List_Map_Iterator(t *testing.T){
|
||||
expect :=map[interface{}]interface{}{1: 1, "key1": "val1"}
|
||||
|
||||
m := gmap.NewLinkMapFrom(expect)
|
||||
m := gmap.NewListMapFrom(expect)
|
||||
m.Iterator(func(k interface{}, v interface{}) bool {
|
||||
gtest.Assert(expect[k], v)
|
||||
return true
|
||||
@ -88,9 +88,9 @@ func Test_Link_Map_Iterator(t *testing.T){
|
||||
gtest.Assert(j, 1)
|
||||
}
|
||||
|
||||
func Test_Link_Map_Clone(t *testing.T) {
|
||||
func Test_List_Map_Clone(t *testing.T) {
|
||||
//clone 方法是深克隆
|
||||
m := gmap.NewLinkMapFrom(map[interface{}]interface{}{1: 1, "key1": "val1"})
|
||||
m := gmap.NewListMapFrom(map[interface{}]interface{}{1: 1, "key1": "val1"})
|
||||
m_clone := m.Clone()
|
||||
m.Remove(1)
|
||||
//修改原 map,clone 后的 map 不影响
|
||||
@ -101,17 +101,17 @@ func Test_Link_Map_Clone(t *testing.T) {
|
||||
gtest.AssertIN("key1", m.Keys())
|
||||
}
|
||||
|
||||
func Test_Link_Map_Basic_Merge(t *testing.T) {
|
||||
m1 := gmap.NewLinkMap()
|
||||
m2 := gmap.NewLinkMap()
|
||||
func Test_List_Map_Basic_Merge(t *testing.T) {
|
||||
m1 := gmap.NewListMap()
|
||||
m2 := gmap.NewListMap()
|
||||
m1.Set("key1", "val1")
|
||||
m2.Set("key2", "val2")
|
||||
m1.Merge(m2)
|
||||
gtest.Assert(m1.Map(), map[interface{}]interface{}{"key1": "val1", "key2": "val2"})
|
||||
}
|
||||
|
||||
func Test_Link_Map_Order(t *testing.T) {
|
||||
m := gmap.NewLinkMap()
|
||||
func Test_List_Map_Order(t *testing.T) {
|
||||
m := gmap.NewListMap()
|
||||
m.Set("k1", "v1")
|
||||
m.Set("k2", "v2")
|
||||
m.Set("k3", "v3")
|
||||
|
||||
@ -388,10 +388,6 @@ func (tree *AVLTree) Print() {
|
||||
fmt.Println(tree.String())
|
||||
}
|
||||
|
||||
func (node *AVLTreeNode) String() string {
|
||||
return fmt.Sprintf("%v", node.Key)
|
||||
}
|
||||
|
||||
// Map returns all key-value items as map.
|
||||
func (tree *AVLTree) Map() map[interface{}]interface{} {
|
||||
m := make(map[interface{}]interface{}, tree.Size())
|
||||
@ -692,7 +688,7 @@ func output(node *AVLTreeNode, prefix string, isTail bool, str *string) {
|
||||
} else {
|
||||
*str += "┌── "
|
||||
}
|
||||
*str += node.String() + "\n"
|
||||
*str += fmt.Sprintf("%v\n", node.Key)
|
||||
if node.children[0] != nil {
|
||||
newPrefix := prefix
|
||||
if isTail {
|
||||
|
||||
@ -371,10 +371,6 @@ func (tree *BTree) Print() {
|
||||
fmt.Println(tree.String())
|
||||
}
|
||||
|
||||
func (entry *BTreeEntry) String() string {
|
||||
return fmt.Sprintf("%v", entry.Key)
|
||||
}
|
||||
|
||||
// Iterator is alias of IteratorAsc.
|
||||
func (tree *BTree) Iterator(f func (key, value interface{}) bool) {
|
||||
tree.IteratorAsc(f)
|
||||
|
||||
@ -546,10 +546,6 @@ func (tree *RedBlackTree) Print() {
|
||||
fmt.Println(tree.String())
|
||||
}
|
||||
|
||||
func (node *RedBlackTreeNode) String() string {
|
||||
return fmt.Sprintf("%v", node.Key)
|
||||
}
|
||||
|
||||
// Search searches the tree with given <key>.
|
||||
// Second return parameter <found> is true if key was found, otherwise false.
|
||||
func (tree *RedBlackTree) Search(key interface{}) (value interface{}, found bool) {
|
||||
@ -600,7 +596,7 @@ func (tree *RedBlackTree) output(node *RedBlackTreeNode, prefix string, isTail b
|
||||
} else {
|
||||
*str += "┌── "
|
||||
}
|
||||
*str += node.String() + "\n"
|
||||
*str += fmt.Sprintf("%v\n", node.Key)
|
||||
if node.left != nil {
|
||||
newPrefix := prefix
|
||||
if isTail {
|
||||
|
||||
@ -17,6 +17,7 @@ import (
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 格式化SQL查询条件
|
||||
@ -136,6 +137,10 @@ func convertParam(value interface{}) interface{} {
|
||||
}
|
||||
switch kind {
|
||||
case reflect.Struct:
|
||||
// 底层数据库引擎支持 time.Time 类型
|
||||
if _, ok := value.(time.Time); ok {
|
||||
return value
|
||||
}
|
||||
return gconv.String(value)
|
||||
}
|
||||
return value
|
||||
|
||||
@ -7,14 +7,17 @@
|
||||
// Package gredis provides convenient client for redis server.
|
||||
//
|
||||
// Redis Client.
|
||||
//
|
||||
// Redis Commands Official: https://redis.io/commands
|
||||
//
|
||||
// Redis Chinese Documentation: http://redisdoc.com/
|
||||
package gredis
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/gmap"
|
||||
"github.com/gogf/gf/third/github.com/gomodule/redigo/redis"
|
||||
"github.com/gogf/gf/g/container/gvar"
|
||||
"github.com/gogf/gf/third/github.com/gomodule/redigo/redis"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -31,7 +34,9 @@ type Redis struct {
|
||||
}
|
||||
|
||||
// Redis connection.
|
||||
type Conn redis.Conn
|
||||
type Conn struct {
|
||||
redis.Conn
|
||||
}
|
||||
|
||||
// Redis configuration.
|
||||
type Config struct {
|
||||
@ -134,16 +139,17 @@ func (r *Redis) Close() error {
|
||||
return r.pool.Close()
|
||||
}
|
||||
|
||||
// Alias of GetConn, see GetConn.
|
||||
func (r *Redis) Conn() Conn {
|
||||
return r.GetConn()
|
||||
}
|
||||
|
||||
// GetConn returns a raw underlying connection object,
|
||||
// Conn returns a raw underlying connection object,
|
||||
// which expose more methods to communicate with server.
|
||||
// **You should call Close function manually if you do not use this connection any further.**
|
||||
func (r *Redis) GetConn() Conn {
|
||||
return r.pool.Get().(Conn)
|
||||
func (r *Redis) Conn() *Conn {
|
||||
return &Conn{ r.pool.Get() }
|
||||
}
|
||||
|
||||
// Alias of Conn, see Conn.
|
||||
func (r *Redis) GetConn() *Conn {
|
||||
return r.Conn()
|
||||
}
|
||||
|
||||
// SetMaxIdle sets the MaxIdle attribute of the connection pool.
|
||||
@ -175,15 +181,21 @@ func (r *Redis) Stats() *PoolStats {
|
||||
// Do automatically get a connection from pool, and close it when reply received.
|
||||
// It does not really "close" the connection, but drop it back to the connection pool.
|
||||
func (r *Redis) Do(command string, args ...interface{}) (interface{}, error) {
|
||||
conn := r.pool.Get()
|
||||
conn := &Conn{ r.pool.Get() }
|
||||
defer conn.Close()
|
||||
return conn.Do(command, args...)
|
||||
}
|
||||
|
||||
// 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...)
|
||||
return gvar.New(v, true), err
|
||||
}
|
||||
|
||||
// Deprecated.
|
||||
// Send writes the command to the client's output buffer.
|
||||
func (r *Redis) Send(command string, args ...interface{}) error {
|
||||
conn := r.pool.Get()
|
||||
conn := &Conn{ r.pool.Get() }
|
||||
defer conn.Close()
|
||||
return conn.Send(command, args...)
|
||||
}
|
||||
|
||||
21
g/database/gredis/gredis_conn.go
Normal file
21
g/database/gredis/gredis_conn.go
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 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 gredis
|
||||
|
||||
import "github.com/gogf/gf/g/container/gvar"
|
||||
|
||||
// DoVar returns value from Do as gvar.Var.
|
||||
func (c *Conn) DoVar(command string, args ...interface{}) (*gvar.Var, error) {
|
||||
v, err := c.Do(command, args...)
|
||||
return gvar.New(v, true), err
|
||||
}
|
||||
|
||||
// ReceiveVar receives a single reply as gvar.Var from the Redis server.
|
||||
func (c *Conn) ReceiveVar() (*gvar.Var, error) {
|
||||
v, err := c.Receive()
|
||||
return gvar.New(v, true), err
|
||||
}
|
||||
@ -71,7 +71,7 @@ func Test_Stats(t *testing.T) {
|
||||
redis.SetIdleTimeout(500*time.Millisecond)
|
||||
redis.SetMaxConnLifetime(500*time.Millisecond)
|
||||
|
||||
array := make([]gredis.Conn, 0)
|
||||
array := make([]*gredis.Conn, 0)
|
||||
for i := 0; i < 10; i++ {
|
||||
array = append(array, redis.Conn())
|
||||
}
|
||||
|
||||
@ -9,20 +9,19 @@
|
||||
package glog
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/gtype"
|
||||
"github.com/gogf/gf/g/os/gfile"
|
||||
"github.com/gogf/gf/g/os/gfpool"
|
||||
"github.com/gogf/gf/g/os/gmlock"
|
||||
"github.com/gogf/gf/g/os/gtime"
|
||||
"github.com/gogf/gf/g/text/gregex"
|
||||
"io"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/gtype"
|
||||
"github.com/gogf/gf/g/os/gfile"
|
||||
"github.com/gogf/gf/g/os/gfpool"
|
||||
"github.com/gogf/gf/g/os/gtime"
|
||||
"github.com/gogf/gf/g/text/gregex"
|
||||
"io"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Logger struct {
|
||||
@ -216,11 +215,7 @@ func (l *Logger) print(std io.Writer, s string) {
|
||||
if _, ok := writer.(*Writer); ok {
|
||||
if f := l.getFilePointer(); f != nil {
|
||||
defer f.Close()
|
||||
key := l.path.Val()
|
||||
gmlock.Lock(key)
|
||||
_, err := io.WriteString(f, s)
|
||||
gmlock.Unlock(key)
|
||||
if err != nil {
|
||||
if _, err := io.WriteString(f, s); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,10 +7,10 @@
|
||||
package gconv_test
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
"testing"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
||||
@ -113,7 +113,6 @@ func Test_Map_StructWithJsonTag(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
// 私有属性不会进行转换
|
||||
func Test_Map_PrivateAttribute(t *testing.T) {
|
||||
type User struct {
|
||||
Id int
|
||||
@ -123,4 +122,24 @@ func Test_Map_PrivateAttribute(t *testing.T) {
|
||||
user := &User{1, "john"}
|
||||
gtest.Assert(gconv.Map(user), g.Map{"Id" : 1})
|
||||
})
|
||||
}
|
||||
}
|
||||
//
|
||||
//func Test_Map_StructInherit(t *testing.T) {
|
||||
// type Base struct {
|
||||
// Id int
|
||||
// }
|
||||
// type User struct {
|
||||
// Base
|
||||
// Name string
|
||||
// }
|
||||
// gtest.Case(t, func() {
|
||||
// user := &User{
|
||||
// Base : Base {
|
||||
// Id : 100,
|
||||
// },
|
||||
// Name : "john",
|
||||
// }
|
||||
// fmt.Println(gconv.Map(user))
|
||||
// //gtest.Assert(gconv.Map(user), g.Map{"Id" : 1})
|
||||
// })
|
||||
//}
|
||||
30
geg/container/gmap/gmap_order.go
Normal file
30
geg/container/gmap/gmap_order.go
Normal file
@ -0,0 +1,30 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/container/gmap"
|
||||
"github.com/gogf/gf/g/util/gutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
array := g.Slice{2, 3, 1, 5, 4, 6, 8, 7, 9}
|
||||
hashMap := gmap.New(true)
|
||||
linkMap := gmap.NewLinkMap(true)
|
||||
treeMap := gmap.NewTreeMap(gutil.ComparatorInt, true)
|
||||
for _, v := range array {
|
||||
hashMap.Set(v, v)
|
||||
}
|
||||
for _, v := range array {
|
||||
linkMap.Set(v, v)
|
||||
}
|
||||
for _, v := range array {
|
||||
treeMap.Set(v, v)
|
||||
}
|
||||
fmt.Println("HashMap Keys:", hashMap.Keys())
|
||||
fmt.Println("HashMap Values:", hashMap.Values())
|
||||
fmt.Println("LinkMap Keys:", linkMap.Keys())
|
||||
fmt.Println("LinkMap Values:", linkMap.Values())
|
||||
fmt.Println("TreeMap Keys:", treeMap.Keys())
|
||||
fmt.Println("TreeMap Values:", treeMap.Values())
|
||||
}
|
||||
@ -3,17 +3,24 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/gtree"
|
||||
"github.com/gogf/gf/g/util/gutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tree := gtree.NewAVLTree(func(v1, v2 interface{}) int {
|
||||
return v1.(int) - v2.(int)
|
||||
})
|
||||
tree := gtree.NewAVLTree(gutil.ComparatorInt)
|
||||
for i := 0; i < 10; i++ {
|
||||
tree.Set(i, i*10)
|
||||
}
|
||||
fmt.Println(tree.String())
|
||||
tree.Remove(1)
|
||||
// 打印树形
|
||||
tree.Print()
|
||||
// 前序遍历
|
||||
fmt.Println("ASC:")
|
||||
tree.IteratorAsc(func(key, value interface{}) bool {
|
||||
fmt.Println(key, value)
|
||||
return true
|
||||
})
|
||||
// 后续遍历
|
||||
fmt.Println("DESC:")
|
||||
tree.IteratorDesc(func(key, value interface{}) bool {
|
||||
fmt.Println(key, value)
|
||||
return true
|
||||
|
||||
62
geg/container/gtree/gtree_redblackmap.go
Normal file
62
geg/container/gtree/gtree_redblackmap.go
Normal file
@ -0,0 +1,62 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/gtree"
|
||||
"github.com/gogf/gf/g/util/gutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
m := gtree.NewRedBlackTree(gutil.ComparatorInt)
|
||||
|
||||
// 设置键值对
|
||||
for i := 0; i < 10; i++ {
|
||||
m.Set(i, i*10)
|
||||
}
|
||||
// 查询大小
|
||||
fmt.Println(m.Size())
|
||||
// 批量设置键值对(不同的数据类型对象参数不同)
|
||||
m.Sets(map[interface{}]interface{}{
|
||||
10: 10,
|
||||
11: 11,
|
||||
})
|
||||
fmt.Println(m.Size())
|
||||
|
||||
// 查询是否存在
|
||||
fmt.Println(m.Contains(1))
|
||||
|
||||
// 查询键值
|
||||
fmt.Println(m.Get(1))
|
||||
|
||||
// 删除数据项
|
||||
m.Remove(9)
|
||||
fmt.Println(m.Size())
|
||||
|
||||
// 批量删除
|
||||
m.Removes([]interface{}{10, 11})
|
||||
fmt.Println(m.Size())
|
||||
|
||||
// 当前键名列表(随机排序)
|
||||
fmt.Println(m.Keys())
|
||||
// 当前键值列表(随机排序)
|
||||
fmt.Println(m.Values())
|
||||
|
||||
// 查询键名,当键值不存在时,写入给定的默认值
|
||||
fmt.Println(m.GetOrSet(100, 100))
|
||||
|
||||
// 删除键值对,并返回对应的键值
|
||||
fmt.Println(m.Remove(100))
|
||||
|
||||
// 遍历map
|
||||
m.IteratorAsc(func(k interface{}, v interface{}) bool {
|
||||
fmt.Printf("%v:%v ", k, v)
|
||||
return true
|
||||
})
|
||||
fmt.Println()
|
||||
|
||||
// 清空map
|
||||
m.Clear()
|
||||
|
||||
// 判断map是否为空
|
||||
fmt.Println(m.IsEmpty())
|
||||
}
|
||||
@ -8,8 +8,8 @@ func main() {
|
||||
tree := gtree.NewRedBlackTree(func(v1, v2 interface{}) int {
|
||||
return v1.(int) - v2.(int)
|
||||
})
|
||||
for i := 0; i < 20; i++ {
|
||||
tree.Set(i, i*10)
|
||||
for i := 0; i < 10; i++ {
|
||||
tree.Set(i, i)
|
||||
}
|
||||
tree.Print()
|
||||
tree.Flip()
|
||||
|
||||
26
geg/database/orm/mysql/gdb_insert.go
Normal file
26
geg/database/orm/mysql/gdb_insert.go
Normal file
@ -0,0 +1,26 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
db := g.DB()
|
||||
// 开启调试模式,以便于记录所有执行的SQL
|
||||
db.SetDebug(true)
|
||||
|
||||
r, e := db.Table("user").Data(g.Map{
|
||||
"passport" : "1",
|
||||
"password" : "1",
|
||||
"nickname" : "1",
|
||||
"create_time" : time.Now(),
|
||||
}).Insert()
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
if r != nil {
|
||||
fmt.Println(r.LastInsertId())
|
||||
}
|
||||
}
|
||||
16
geg/database/redis/gredis_conn_do_var.go
Normal file
16
geg/database/redis/gredis_conn_do_var.go
Normal file
@ -0,0 +1,16 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
)
|
||||
|
||||
func main() {
|
||||
conn := g.Redis().Conn()
|
||||
defer conn.Close()
|
||||
if _, err := conn.Do("SET", "k", "v"); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
v, _ := conn.DoVar("GET", "k")
|
||||
fmt.Println(v.String())
|
||||
}
|
||||
19
geg/database/redis/gredis_conn_send_var.go
Normal file
19
geg/database/redis/gredis_conn_send_var.go
Normal file
@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
)
|
||||
|
||||
func main() {
|
||||
conn := g.Redis().Conn()
|
||||
defer conn.Close()
|
||||
conn.Send("SET", "foo", "bar")
|
||||
conn.Send("GET", "foo")
|
||||
conn.Flush()
|
||||
// reply from SET
|
||||
conn.Receive()
|
||||
// reply from GET
|
||||
v, _ := conn.ReceiveVar()
|
||||
fmt.Println(v.String())
|
||||
}
|
||||
22
geg/database/redis/gredis_conn_subscribe_var.go
Normal file
22
geg/database/redis/gredis_conn_subscribe_var.go
Normal file
@ -0,0 +1,22 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
)
|
||||
|
||||
func main() {
|
||||
conn := g.Redis().Conn()
|
||||
defer conn.Close()
|
||||
_, err := conn.Do("SUBSCRIBE", "channel")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for {
|
||||
reply, err := conn.ReceiveVar()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(reply.Strings())
|
||||
}
|
||||
}
|
||||
@ -1,40 +1,24 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
)
|
||||
|
||||
func main() {
|
||||
//b, e := gjson.MarshalOrdered(g.Map{
|
||||
// "a" : 1,
|
||||
// "b" : 2,
|
||||
// "c" : 3,
|
||||
//})
|
||||
//fmt.Println(e)
|
||||
//fmt.Println(string(b))
|
||||
|
||||
//m := map[string]interface{}{
|
||||
// "facet_is_special_price":[]string{"1"},
|
||||
// "score_outlet":"0",
|
||||
// "skus":[]string{"DI139BE71WDWDFMX", "DI139BE71WDWDFMX-519406"},
|
||||
// "facet_novelty_two_days":[]string{"0"},
|
||||
// "facet_brand":[]string{"139"},
|
||||
// "sku":[]string{"DI139BE71WDWDFMX"},
|
||||
//}
|
||||
|
||||
for {
|
||||
m := make(map[string]interface{})
|
||||
m["facet_is_special_price"] = []string{"1"}
|
||||
m["score_outlet"] = "0"
|
||||
m["skus"] = []string{"DI139BE71WDWDFMX", "DI139BE71WDWDFMX-519406"}
|
||||
m["facet_novelty_two_days"] = []string{"0"}
|
||||
m["facet_brand"] = []string{"139"}
|
||||
m["sku"] = []string{"DI139BE71WDWDFMX"}
|
||||
b, _ := json.Marshal(m)
|
||||
fmt.Println(string(b))
|
||||
time.Sleep(100*time.Millisecond)
|
||||
type Person struct{
|
||||
Name string
|
||||
}
|
||||
|
||||
type Staff struct{
|
||||
Person
|
||||
StaffId int
|
||||
}
|
||||
staff := &Staff{}
|
||||
params := g.Map{
|
||||
"Name" : "john",
|
||||
"StaffId" : "10000",
|
||||
}
|
||||
gconv.Struct(params, staff)
|
||||
fmt.Println(staff)
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package gf
|
||||
|
||||
const VERSION = "v1.6.10"
|
||||
const VERSION = "v1.6.13"
|
||||
const AUTHORS = "john<john@goframe.org>"
|
||||
|
||||
Reference in New Issue
Block a user