mirror of
https://gitee.com/johng/gf.git
synced 2024-12-03 04:37:49 +08:00
refacting gmap
This commit is contained in:
parent
48b1d616c5
commit
4c647aaa19
@ -11,11 +11,13 @@ import (
|
||||
"github.com/gogf/gf/g/internal/rwmutex"
|
||||
)
|
||||
|
||||
// Deprecated, use Map instead.
|
||||
type IntBoolMap struct {
|
||||
m map[int]bool
|
||||
mu *rwmutex.RWMutex
|
||||
}
|
||||
|
||||
// Deprecated, use New instead.
|
||||
// NewIntBoolMap returns an empty IntBoolMap object.
|
||||
// The param <unsafe> used to specify whether using map with un-concurrent-safety,
|
||||
// which is false in default, means concurrent-safe.
|
||||
@ -26,6 +28,7 @@ func NewIntBoolMap(unsafe...bool) *IntBoolMap {
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated, use NewFrom instead.
|
||||
// NewIntBoolMapFrom returns an IntBoolMap object from given map <m>.
|
||||
// Notice that, the param map is a type of pointer,
|
||||
// there might be some concurrent-safe issues when changing the map outside.
|
||||
@ -36,6 +39,7 @@ func NewIntBoolMapFrom(m map[int]bool, unsafe...bool) *IntBoolMap {
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated, use NewFromArray instead.
|
||||
// NewIntBoolMapFromArray returns an IntBoolMap from given array.
|
||||
// The param <keys> given as the keys of the map,
|
||||
// and <values> as its corresponding values.
|
@ -11,11 +11,13 @@ import (
|
||||
"github.com/gogf/gf/g/internal/rwmutex"
|
||||
)
|
||||
|
||||
// Deprecated, use Map instead.
|
||||
type IntIntMap struct {
|
||||
mu *rwmutex.RWMutex
|
||||
m map[int]int
|
||||
}
|
||||
|
||||
// Deprecated, use New instead.
|
||||
// NewIntIntMap returns an empty IntIntMap object.
|
||||
// The param <unsafe> used to specify whether using map with un-concurrent-safety,
|
||||
// which is false in default, means concurrent-safe.
|
||||
@ -26,6 +28,7 @@ func NewIntIntMap(unsafe...bool) *IntIntMap {
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated, use NewFrom instead.
|
||||
// NewIntIntMapFrom returns an IntIntMap object from given map <m>.
|
||||
// Notice that, the param map is a type of pointer,
|
||||
// there might be some concurrent-safe issues when changing the map outside.
|
||||
@ -36,6 +39,7 @@ func NewIntIntMapFrom(m map[int]int, unsafe...bool) *IntIntMap {
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated, use NewFromArray instead.
|
||||
// NewIntIntMapFromArray returns an IntIntMap object from given array.
|
||||
// The param <keys> given as the keys of the map,
|
||||
// and <values> as its corresponding values.
|
@ -12,11 +12,13 @@ import (
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
)
|
||||
|
||||
// Deprecated, use Map instead.
|
||||
type IntInterfaceMap struct {
|
||||
mu *rwmutex.RWMutex
|
||||
m map[int]interface{}
|
||||
}
|
||||
|
||||
// Deprecated, use New instead.
|
||||
// NewIntInterfaceMap returns an empty IntInterfaceMap object.
|
||||
// The param <unsafe> used to specify whether using map with un-concurrent-safety,
|
||||
// which is false in default, means concurrent-safe.
|
||||
@ -27,6 +29,7 @@ func NewIntInterfaceMap(unsafe...bool) *IntInterfaceMap {
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated, use NewFrom instead.
|
||||
// NewIntInterfaceMapFrom returns an IntInterfaceMap object from given map <m>.
|
||||
// Notice that, the param map is a type of pointer,
|
||||
// there might be some concurrent-safe issues when changing the map outside.
|
||||
@ -37,6 +40,7 @@ func NewIntInterfaceMapFrom(m map[int]interface{}, unsafe...bool) *IntInterfaceM
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated, use NewFromArray instead.
|
||||
// NewFromArray returns a hash map from given array.
|
||||
// The param <keys> given as the keys of the map,
|
||||
// and <values> as its corresponding values.
|
@ -11,11 +11,13 @@ import (
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
)
|
||||
|
||||
// Deprecated, use Map instead.
|
||||
type IntStringMap struct {
|
||||
mu *rwmutex.RWMutex
|
||||
m map[int]string
|
||||
}
|
||||
|
||||
// Deprecated, use New instead.
|
||||
// NewIntStringMap returns an empty IntStringMap object.
|
||||
// The param <unsafe> used to specify whether using map with un-concurrent-safety,
|
||||
// which is false in default, means concurrent-safe.
|
||||
@ -26,6 +28,7 @@ func NewIntStringMap(unsafe ...bool) *IntStringMap {
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated, use NewFrom instead.
|
||||
// NewIntStringMapFrom returns an IntStringMap object from given map <m>.
|
||||
// Notice that, the param map is a type of pointer,
|
||||
// there might be some concurrent-safe issues when changing the map outside.
|
||||
@ -36,6 +39,7 @@ func NewIntStringMapFrom(m map[int]string, unsafe ...bool) *IntStringMap {
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated, use NewFromArray instead.
|
||||
// NewIntStringMapFromArray returns an IntStringMap object from given array.
|
||||
// The param <keys> given as the keys of the map,
|
||||
// and <values> as its corresponding values.
|
@ -11,11 +11,13 @@ import (
|
||||
"github.com/gogf/gf/g/internal/rwmutex"
|
||||
)
|
||||
|
||||
// Deprecated, use Map instead.
|
||||
type StringBoolMap struct {
|
||||
mu *rwmutex.RWMutex
|
||||
m map[string]bool
|
||||
}
|
||||
|
||||
// Deprecated, use New instead.
|
||||
// NewStringBoolMap returns an empty StringBoolMap object.
|
||||
// The param <unsafe> used to specify whether using map with un-concurrent-safety,
|
||||
// which is false in default, means concurrent-safe.
|
||||
@ -26,6 +28,7 @@ func NewStringBoolMap(unsafe...bool) *StringBoolMap {
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated, use NewFrom instead.
|
||||
// NewStringBoolMapFrom returns an StringBoolMap object from given map <m>.
|
||||
// Notice that, the param map is a type of pointer,
|
||||
// there might be some concurrent-safe issues when changing the map outside.
|
||||
@ -36,6 +39,7 @@ func NewStringBoolMapFrom(m map[string]bool, unsafe...bool) *StringBoolMap {
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated, use NewFromArray instead.
|
||||
// NewFromArray returns a hash map from given array.
|
||||
// The param <keys> given as the keys of the map,
|
||||
// and <values> as its corresponding values.
|
@ -12,11 +12,13 @@ import (
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
)
|
||||
|
||||
// Deprecated, use Map instead.
|
||||
type StringIntMap struct {
|
||||
mu *rwmutex.RWMutex
|
||||
m map[string]int
|
||||
}
|
||||
|
||||
// Deprecated, use New instead.
|
||||
// NewStringIntMap returns an empty StringIntMap object.
|
||||
// The param <unsafe> used to specify whether using map with un-concurrent-safety,
|
||||
// which is false in default, means concurrent-safe.
|
||||
@ -27,6 +29,7 @@ func NewStringIntMap(unsafe ...bool) *StringIntMap {
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated, use NewFrom instead.
|
||||
// NewStringIntMapFrom returns an StringIntMap object from given map <m>.
|
||||
// Notice that, the param map is a type of pointer,
|
||||
// there might be some concurrent-safe issues when changing the map outside.
|
||||
@ -37,6 +40,7 @@ func NewStringIntMapFrom(m map[string]int, unsafe ...bool) *StringIntMap {
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated, use NewFromArray instead.
|
||||
// NewStringIntMapFromArray returns an StringIntMap object from given array.
|
||||
// The param <keys> given as the keys of the map,
|
||||
// and <values> as its corresponding values.
|
@ -12,11 +12,13 @@ import (
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
)
|
||||
|
||||
// Deprecated, use Map instead.
|
||||
type StringInterfaceMap struct {
|
||||
mu *rwmutex.RWMutex
|
||||
m map[string]interface{}
|
||||
}
|
||||
|
||||
// Deprecated, use New instead.
|
||||
// NewStringInterfaceMap returns an empty StringInterfaceMap object.
|
||||
// The param <unsafe> used to specify whether using map with un-concurrent-safety,
|
||||
// which is false in default, means concurrent-safe.
|
||||
@ -27,6 +29,7 @@ func NewStringInterfaceMap(unsafe ...bool) *StringInterfaceMap {
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated, use NewFrom instead.
|
||||
// NewStringInterfaceMapFrom returns an StringInterfaceMap object from given map <m>.
|
||||
// Notice that, the param map is a type of pointer,
|
||||
// there might be some concurrent-safe issues when changing the map outside.
|
||||
@ -37,6 +40,7 @@ func NewStringInterfaceMapFrom(m map[string]interface{}, unsafe ...bool) *String
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated, use NewFromArray instead.
|
||||
// NewStringInterfaceMapFromArray returns an StringInterfaceMap object from given array.
|
||||
// The param <keys> given as the keys of the map,
|
||||
// and <values> as its corresponding values.
|
@ -11,11 +11,13 @@ import (
|
||||
"github.com/gogf/gf/g/internal/rwmutex"
|
||||
)
|
||||
|
||||
// Deprecated, use Map instead.
|
||||
type StringStringMap struct {
|
||||
mu *rwmutex.RWMutex
|
||||
m map[string]string
|
||||
}
|
||||
|
||||
// Deprecated, use New instead.
|
||||
// NewStringStringMap returns an empty StringStringMap object.
|
||||
// The param <unsafe> used to specify whether using map with un-concurrent-safety,
|
||||
// which is false in default, means concurrent-safe.
|
||||
@ -26,6 +28,7 @@ func NewStringStringMap(unsafe...bool) *StringStringMap {
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated, use NewFrom instead.
|
||||
// NewStringStringMapFrom returns an StringStringMap object from given map <m>.
|
||||
// Notice that, the param map is a type of pointer,
|
||||
// there might be some concurrent-safe issues when changing the map outside.
|
||||
@ -36,6 +39,7 @@ func NewStringStringMapFrom(m map[string]string, unsafe...bool) *StringStringMap
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated, use NewFromArray instead.
|
||||
// NewStringStringMapFromArray returns an StringStringMap object from given array.
|
||||
// The param <keys> given as the keys of the map,
|
||||
// and <values> as its corresponding values.
|
@ -18,7 +18,7 @@ var ibm = NewIntBoolMap()
|
||||
var iim = NewIntIntMap()
|
||||
var iifm = NewIntInterfaceMap()
|
||||
var ism = NewIntStringMap()
|
||||
var ififm = NewMap()
|
||||
var ififm = New()
|
||||
var sbm = NewStringBoolMap()
|
||||
var sim = NewStringIntMap()
|
||||
var sifm = NewStringInterfaceMap()
|
@ -18,7 +18,7 @@ var ibmUnsafe = NewIntBoolMap(true)
|
||||
var iimUnsafe = NewIntIntMap(true)
|
||||
var iifmUnsafe = NewIntInterfaceMap(true)
|
||||
var ismUnsafe = NewIntStringMap(true)
|
||||
var ififmUnsafe = NewMap(true)
|
||||
var ififmUnsafe = New(true)
|
||||
var sbmUnsafe = NewStringBoolMap(true)
|
||||
var simUnsafe = NewStringIntMap(true)
|
||||
var sifmUnsafe = NewStringInterfaceMap(true)
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
// Copyright 2017-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 gm file,
|
||||
@ -6,313 +6,3 @@
|
||||
|
||||
// Package gmap provides concurrent-safe/unsafe maps.
|
||||
package gmap
|
||||
|
||||
import "github.com/gogf/gf/g/internal/rwmutex"
|
||||
|
||||
type Map struct {
|
||||
mu *rwmutex.RWMutex
|
||||
m map[interface{}]interface{}
|
||||
}
|
||||
|
||||
// New returns an empty hash map.
|
||||
// The param <unsafe> used to specify whether using map with un-concurrent-safety,
|
||||
// which is false in default, means concurrent-safe.
|
||||
func New(unsafe ...bool) *Map {
|
||||
return NewMap(unsafe...)
|
||||
}
|
||||
|
||||
// Alias of New. See New.
|
||||
func NewMap(unsafe ...bool) *Map {
|
||||
return &Map{
|
||||
m : make(map[interface{}]interface{}),
|
||||
mu : rwmutex.New(unsafe...),
|
||||
}
|
||||
}
|
||||
|
||||
// NewFrom returns a hash map from given map <m>.
|
||||
// Notice that, the param map is a type of pointer,
|
||||
// there might be some concurrent-safe issues when changing the map outside.
|
||||
func NewFrom(m map[interface{}]interface{}, unsafe...bool) *Map {
|
||||
return &Map{
|
||||
m : m,
|
||||
mu : rwmutex.New(unsafe...),
|
||||
}
|
||||
}
|
||||
|
||||
// NewFromArray returns a hash map from given array.
|
||||
// The param <keys> given as the keys of the map,
|
||||
// and <values> as its corresponding values.
|
||||
//
|
||||
// If length of <keys> is greater than that of <values>,
|
||||
// the corresponding overflow map values will be the default value of its type.
|
||||
func NewFromArray(keys []interface{}, values []interface{}, unsafe...bool) *Map {
|
||||
m := make(map[interface{}]interface{})
|
||||
l := len(values)
|
||||
for i, k := range keys {
|
||||
if i < l {
|
||||
m[k] = values[i]
|
||||
} else {
|
||||
m[k] = interface{}(nil)
|
||||
}
|
||||
}
|
||||
return &Map{
|
||||
m : m,
|
||||
mu : rwmutex.New(unsafe...),
|
||||
}
|
||||
}
|
||||
|
||||
// Iterator iterates the hash map with custom callback function <f>.
|
||||
// If f returns true, then continue iterating; or false to stop.
|
||||
func (gm *Map) Iterator(f func (k interface{}, v interface{}) bool) {
|
||||
gm.mu.RLock()
|
||||
defer gm.mu.RUnlock()
|
||||
for k, v := range gm.m {
|
||||
if !f(k, v) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clone returns a new hash map with copy of current map data.
|
||||
func (gm *Map) Clone(unsafe ...bool) *Map {
|
||||
return NewFrom(gm.Map(), unsafe ...)
|
||||
}
|
||||
|
||||
// Map returns a copy of the data of the hash map.
|
||||
func (gm *Map) Map() map[interface{}]interface{} {
|
||||
m := make(map[interface{}]interface{})
|
||||
gm.mu.RLock()
|
||||
for k, v := range gm.m {
|
||||
m[k] = v
|
||||
}
|
||||
gm.mu.RUnlock()
|
||||
return m
|
||||
}
|
||||
|
||||
// Set sets key-value to the hash map.
|
||||
func (gm *Map) Set(key interface{}, val interface{}) {
|
||||
gm.mu.Lock()
|
||||
gm.m[key] = val
|
||||
gm.mu.Unlock()
|
||||
}
|
||||
|
||||
// BatchSet batch sets key-values to the hash map.
|
||||
func (gm *Map) BatchSet(m map[interface{}]interface{}) {
|
||||
gm.mu.Lock()
|
||||
for k, v := range m {
|
||||
gm.m[k] = v
|
||||
}
|
||||
gm.mu.Unlock()
|
||||
}
|
||||
|
||||
// Get returns the value by given <key>.
|
||||
func (gm *Map) Get(key interface{}) interface{} {
|
||||
gm.mu.RLock()
|
||||
val, _ := gm.m[key]
|
||||
gm.mu.RUnlock()
|
||||
return val
|
||||
}
|
||||
|
||||
// doSetWithLockCheck checks whether value of the key exists with mutex.Lock,
|
||||
// if not exists, set value to the map with given <key>,
|
||||
// or else just return the existing value.
|
||||
//
|
||||
// When setting value, if <value> is type of <func() interface {}>,
|
||||
// it will be executed with mutex.Lock of the hash map,
|
||||
// and its return value will be set to the map with <key>.
|
||||
//
|
||||
// It returns value with given <key>.
|
||||
func (gm *Map) doSetWithLockCheck(key interface{}, value interface{}) interface{} {
|
||||
gm.mu.Lock()
|
||||
defer gm.mu.Unlock()
|
||||
if v, ok := gm.m[key]; ok {
|
||||
return v
|
||||
}
|
||||
if f, ok := value.(func() interface {}); ok {
|
||||
value = f()
|
||||
}
|
||||
gm.m[key] = value
|
||||
return value
|
||||
}
|
||||
|
||||
// GetOrSet returns the value by key,
|
||||
// or set value with given <value> if not exist and returns this value.
|
||||
func (gm *Map) GetOrSet(key interface{}, value interface{}) interface{} {
|
||||
if v := gm.Get(key); v == nil {
|
||||
return gm.doSetWithLockCheck(key, value)
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
// GetOrSetFunc returns the value by key,
|
||||
// or sets value with return value of callback function <f> if not exist
|
||||
// and returns this value.
|
||||
func (gm *Map) GetOrSetFunc(key interface{}, f func() interface{}) interface{} {
|
||||
if v := gm.Get(key); v == nil {
|
||||
return gm.doSetWithLockCheck(key, f())
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
// GetOrSetFuncLock returns the value by key,
|
||||
// or sets value with return value of callback function <f> if not exist
|
||||
// and returns this value.
|
||||
//
|
||||
// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function <f>
|
||||
// with mutex.Lock of the hash map.
|
||||
func (gm *Map) GetOrSetFuncLock(key interface{}, f func() interface{}) interface{} {
|
||||
if v := gm.Get(key); v == nil {
|
||||
return gm.doSetWithLockCheck(key, f)
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
// 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 (gm *Map) SetIfNotExist(key interface{}, value interface{}) bool {
|
||||
if !gm.Contains(key) {
|
||||
gm.doSetWithLockCheck(key, value)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 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 (gm *Map) SetIfNotExistFunc(key interface{}, f func() interface{}) bool {
|
||||
if !gm.Contains(key) {
|
||||
gm.doSetWithLockCheck(key, f())
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// SetIfNotExistFuncLock sets value with return value of callback function <f>, then return true.
|
||||
// It returns false if <key> exists, and <value> would be ignored.
|
||||
//
|
||||
// SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that
|
||||
// it executes function <f> with mutex.Lock of the hash map.
|
||||
func (gm *Map) SetIfNotExistFuncLock(key interface{}, f func() interface{}) bool {
|
||||
if !gm.Contains(key) {
|
||||
gm.doSetWithLockCheck(key, f)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// BatchRemove batch deletes values of the map by keys.
|
||||
func (gm *Map) BatchRemove(keys []interface{}) {
|
||||
gm.mu.Lock()
|
||||
for _, key := range keys {
|
||||
delete(gm.m, key)
|
||||
}
|
||||
gm.mu.Unlock()
|
||||
}
|
||||
|
||||
// Remove deletes value from map by given <key>, and return this deleted value.
|
||||
func (gm *Map) Remove(key interface{}) interface{} {
|
||||
gm.mu.Lock()
|
||||
val, exists := gm.m[key]
|
||||
if exists {
|
||||
delete(gm.m, key)
|
||||
}
|
||||
gm.mu.Unlock()
|
||||
return val
|
||||
}
|
||||
|
||||
// Keys returns all keys of the map as a slice.
|
||||
func (gm *Map) Keys() []interface{} {
|
||||
gm.mu.RLock()
|
||||
keys := make([]interface{}, 0)
|
||||
for key, _ := range gm.m {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
gm.mu.RUnlock()
|
||||
return keys
|
||||
}
|
||||
|
||||
// Values returns all values of the map as a slice.
|
||||
func (gm *Map) Values() []interface{} {
|
||||
gm.mu.RLock()
|
||||
vals := make([]interface{}, 0)
|
||||
for _, val := range gm.m {
|
||||
vals = append(vals, val)
|
||||
}
|
||||
gm.mu.RUnlock()
|
||||
return vals
|
||||
}
|
||||
|
||||
// Contains checks whether a key exists.
|
||||
// It returns true if the <key> exists, or else false.
|
||||
func (gm *Map) Contains(key interface{}) bool {
|
||||
gm.mu.RLock()
|
||||
_, exists := gm.m[key]
|
||||
gm.mu.RUnlock()
|
||||
return exists
|
||||
}
|
||||
|
||||
// Size returns the size of the map.
|
||||
func (gm *Map) Size() int {
|
||||
gm.mu.RLock()
|
||||
length := len(gm.m)
|
||||
gm.mu.RUnlock()
|
||||
return length
|
||||
}
|
||||
|
||||
// IsEmpty checks whether the map is empty.
|
||||
// It returns true if map is empty, or else false.
|
||||
func (gm *Map) IsEmpty() bool {
|
||||
gm.mu.RLock()
|
||||
empty := len(gm.m) == 0
|
||||
gm.mu.RUnlock()
|
||||
return empty
|
||||
}
|
||||
|
||||
// Clear deletes all data of the map, it will remake a new underlying map data map.
|
||||
func (gm *Map) Clear() {
|
||||
gm.mu.Lock()
|
||||
gm.m = make(map[interface{}]interface{})
|
||||
gm.mu.Unlock()
|
||||
}
|
||||
|
||||
// LockFunc locks writing with given callback function <f> and mutex.Lock.
|
||||
func (gm *Map) LockFunc(f func(m map[interface{}]interface{})) {
|
||||
gm.mu.Lock()
|
||||
defer gm.mu.Unlock()
|
||||
f(gm.m)
|
||||
}
|
||||
|
||||
// RLockFunc locks reading with given callback function <f> and mutex.RLock.
|
||||
func (gm *Map) RLockFunc(f func(m map[interface{}]interface{})) {
|
||||
gm.mu.RLock()
|
||||
defer gm.mu.RUnlock()
|
||||
f(gm.m)
|
||||
}
|
||||
|
||||
// Flip exchanges key-value of the map, it will change key-value to value-key.
|
||||
func (gm *Map) Flip() {
|
||||
gm.mu.Lock()
|
||||
defer gm.mu.Unlock()
|
||||
n := make(map[interface{}]interface{}, len(gm.m))
|
||||
for i, v := range gm.m {
|
||||
n[v] = i
|
||||
}
|
||||
gm.m = n
|
||||
}
|
||||
|
||||
// Merge merges two hash maps.
|
||||
// The <other> map will be merged into the map <gm>.
|
||||
func (gm *Map) Merge(other *Map) {
|
||||
gm.mu.Lock()
|
||||
defer gm.mu.Unlock()
|
||||
if other != gm {
|
||||
other.mu.RLock()
|
||||
defer other.mu.RUnlock()
|
||||
}
|
||||
for k, v := range other.m {
|
||||
gm.m[k] = v
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
// 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 gm file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package gmap
|
||||
|
312
g/container/gmap/gmap_hashmap.go
Normal file
312
g/container/gmap/gmap_hashmap.go
Normal file
@ -0,0 +1,312 @@
|
||||
// Copyright 2017-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 m file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package gmap
|
||||
|
||||
import "github.com/gogf/gf/g/internal/rwmutex"
|
||||
|
||||
type HashMap struct {
|
||||
mu *rwmutex.RWMutex
|
||||
data map[interface{}]interface{}
|
||||
}
|
||||
|
||||
// New returns an empty hash map.
|
||||
// The param <unsafe> used to specify whether using map with un-concurrent-safety,
|
||||
// which is false in default, means concurrent-safe.
|
||||
func New(unsafe ...bool) *HashMap {
|
||||
return &HashMap{
|
||||
mu : rwmutex.New(unsafe...),
|
||||
data : make(map[interface{}]interface{}),
|
||||
}
|
||||
}
|
||||
|
||||
// NewFrom returns a hash map from given map <m>.
|
||||
// Notice that, the param map is a type of pointer,
|
||||
// there might be some concurrent-safe issues when changing the map outside.
|
||||
func NewFrom(data map[interface{}]interface{}, unsafe...bool) *HashMap {
|
||||
return &HashMap {
|
||||
mu : rwmutex.New(unsafe...),
|
||||
data : data,
|
||||
}
|
||||
}
|
||||
|
||||
// NewFromArray returns a hash map from given array.
|
||||
// The param <keys> given as the keys of the map,
|
||||
// and <values> as its corresponding values.
|
||||
//
|
||||
// If length of <keys> is greater than that of <values>,
|
||||
// the corresponding overflow map values will be the default value of its type.
|
||||
func NewFromArray(keys []interface{}, values []interface{}, unsafe...bool) *HashMap {
|
||||
m := make(map[interface{}]interface{})
|
||||
l := len(values)
|
||||
for i, k := range keys {
|
||||
if i < l {
|
||||
m[k] = values[i]
|
||||
} else {
|
||||
m[k] = interface{}(nil)
|
||||
}
|
||||
}
|
||||
return &HashMap{
|
||||
mu : rwmutex.New(unsafe...),
|
||||
data : m,
|
||||
}
|
||||
}
|
||||
|
||||
// Iterator iterates the hash map with custom callback function <f>.
|
||||
// If f returns true, then continue iterating; or false to stop.
|
||||
func (m *HashMap) Iterator(f func (k interface{}, v interface{}) bool) {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
for k, v := range m.data {
|
||||
if !f(k, v) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clone returns a new hash map with copy of current map data.
|
||||
func (m *HashMap) Clone(unsafe ...bool) *HashMap {
|
||||
return NewFrom(m.Map(), unsafe ...)
|
||||
}
|
||||
|
||||
// Map returns a copy of the data of the hash map.
|
||||
func (m *HashMap) Map() map[interface{}]interface{} {
|
||||
data := make(map[interface{}]interface{})
|
||||
m.mu.RLock()
|
||||
for k, v := range m.data {
|
||||
data[k] = v
|
||||
}
|
||||
m.mu.RUnlock()
|
||||
return data
|
||||
}
|
||||
|
||||
// Set sets key-value to the hash map.
|
||||
func (m *HashMap) Set(key interface{}, val interface{}) {
|
||||
m.mu.Lock()
|
||||
m.data[key] = val
|
||||
m.mu.Unlock()
|
||||
}
|
||||
|
||||
// BatchSet batch sets key-values to the hash map.
|
||||
func (m *HashMap) BatchSet(data map[interface{}]interface{}) {
|
||||
m.mu.Lock()
|
||||
for k, v := range data {
|
||||
m.data[k] = v
|
||||
}
|
||||
m.mu.Unlock()
|
||||
}
|
||||
|
||||
// Get returns the value by given <key>.
|
||||
func (m *HashMap) Get(key interface{}) interface{} {
|
||||
m.mu.RLock()
|
||||
val, _ := m.data[key]
|
||||
m.mu.RUnlock()
|
||||
return val
|
||||
}
|
||||
|
||||
// doSetWithLockCheck checks whether value of the key exists within mutex.Lock,
|
||||
// if the value not exists, it sets value to the map with given <key>,
|
||||
// or else just returns the existing value.
|
||||
//
|
||||
// When setting value, if <value> is type of <func() interface {}>,
|
||||
// it will be executed within mutex.Lock of the hash map,
|
||||
// and its return value will be set to the map with <key>.
|
||||
//
|
||||
// It returns value of given <key>.
|
||||
func (m *HashMap) doSetWithLockCheck(key interface{}, value interface{}) interface{} {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if v, ok := m.data[key]; ok {
|
||||
return v
|
||||
}
|
||||
if f, ok := value.(func() interface {}); ok {
|
||||
value = f()
|
||||
}
|
||||
m.data[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 *HashMap) GetOrSet(key interface{}, value interface{}) interface{} {
|
||||
if v := m.Get(key); v == nil {
|
||||
return m.doSetWithLockCheck(key, value)
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
// 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 *HashMap) GetOrSetFunc(key interface{}, f func() interface{}) interface{} {
|
||||
if v := m.Get(key); v == nil {
|
||||
return m.doSetWithLockCheck(key, f())
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
// GetOrSetFuncLock returns the value by key,
|
||||
// or sets value with return value of callback function <f> if not exist
|
||||
// and returns this value.
|
||||
//
|
||||
// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function <f>
|
||||
// with mutex.Lock of the hash map.
|
||||
func (m *HashMap) GetOrSetFuncLock(key interface{}, f func() interface{}) interface{} {
|
||||
if v := m.Get(key); v == nil {
|
||||
return m.doSetWithLockCheck(key, f)
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
// 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 *HashMap) SetIfNotExist(key interface{}, value interface{}) bool {
|
||||
if !m.Contains(key) {
|
||||
m.doSetWithLockCheck(key, value)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 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 *HashMap) SetIfNotExistFunc(key interface{}, f func() interface{}) bool {
|
||||
if !m.Contains(key) {
|
||||
m.doSetWithLockCheck(key, f())
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// SetIfNotExistFuncLock sets value with return value of callback function <f>, then return true.
|
||||
// It returns false if <key> exists, and <value> would be ignored.
|
||||
//
|
||||
// SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that
|
||||
// it executes function <f> with mutex.Lock of the hash map.
|
||||
func (m *HashMap) SetIfNotExistFuncLock(key interface{}, f func() interface{}) bool {
|
||||
if !m.Contains(key) {
|
||||
m.doSetWithLockCheck(key, f)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// BatchRemove batch deletes values of the map by keys.
|
||||
func (m *HashMap) BatchRemove(keys []interface{}) {
|
||||
m.mu.Lock()
|
||||
for _, key := range keys {
|
||||
delete(m.data, key)
|
||||
}
|
||||
m.mu.Unlock()
|
||||
}
|
||||
|
||||
// Remove deletes value from map by given <key>, and return this deleted value.
|
||||
func (m *HashMap) Remove(key interface{}) interface{} {
|
||||
m.mu.Lock()
|
||||
val, exists := m.data[key]
|
||||
if exists {
|
||||
delete(m.data, key)
|
||||
}
|
||||
m.mu.Unlock()
|
||||
return val
|
||||
}
|
||||
|
||||
// Keys returns all keys of the map as a slice.
|
||||
func (m *HashMap) Keys() []interface{} {
|
||||
m.mu.RLock()
|
||||
keys := make([]interface{}, 0)
|
||||
for key, _ := range m.data {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
m.mu.RUnlock()
|
||||
return keys
|
||||
}
|
||||
|
||||
// Values returns all values of the map as a slice.
|
||||
func (m *HashMap) Values() []interface{} {
|
||||
m.mu.RLock()
|
||||
vals := make([]interface{}, 0)
|
||||
for _, val := range m.data {
|
||||
vals = append(vals, val)
|
||||
}
|
||||
m.mu.RUnlock()
|
||||
return vals
|
||||
}
|
||||
|
||||
// Contains checks whether a key exists.
|
||||
// It returns true if the <key> exists, or else false.
|
||||
func (m *HashMap) Contains(key interface{}) bool {
|
||||
m.mu.RLock()
|
||||
_, exists := m.data[key]
|
||||
m.mu.RUnlock()
|
||||
return exists
|
||||
}
|
||||
|
||||
// Size returns the size of the map.
|
||||
func (m *HashMap) Size() int {
|
||||
m.mu.RLock()
|
||||
length := len(m.data)
|
||||
m.mu.RUnlock()
|
||||
return length
|
||||
}
|
||||
|
||||
// IsEmpty checks whether the map is empty.
|
||||
// It returns true if map is empty, or else false.
|
||||
func (m *HashMap) IsEmpty() bool {
|
||||
m.mu.RLock()
|
||||
empty := len(m.data) == 0
|
||||
m.mu.RUnlock()
|
||||
return empty
|
||||
}
|
||||
|
||||
// Clear deletes all data of the map, it will remake a new underlying map data map.
|
||||
func (m *HashMap) Clear() {
|
||||
m.mu.Lock()
|
||||
m.data = make(map[interface{}]interface{})
|
||||
m.mu.Unlock()
|
||||
}
|
||||
|
||||
// LockFunc locks writing with given callback function <f> and mutex.Lock.
|
||||
func (m *HashMap) LockFunc(f func(m map[interface{}]interface{})) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
f(m.data)
|
||||
}
|
||||
|
||||
// RLockFunc locks reading with given callback function <f> and mutex.RLock.
|
||||
func (m *HashMap) RLockFunc(f func(m map[interface{}]interface{})) {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
f(m.data)
|
||||
}
|
||||
|
||||
// Flip exchanges key-value of the map, it will change key-value to value-key.
|
||||
func (m *HashMap) Flip() {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
n := make(map[interface{}]interface{}, len(m.data))
|
||||
for i, v := range m.data {
|
||||
n[v] = i
|
||||
}
|
||||
m.data = n
|
||||
}
|
||||
|
||||
// Merge merges two hash maps.
|
||||
// The <other> map will be merged into the map <gm>.
|
||||
func (m *HashMap) Merge(other *HashMap) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if other != m {
|
||||
other.mu.RLock()
|
||||
defer other.mu.RUnlock()
|
||||
}
|
||||
for k, v := range other.data {
|
||||
m.data[k] = v
|
||||
}
|
||||
}
|
@ -15,11 +15,13 @@ import (
|
||||
)
|
||||
|
||||
type Var struct {
|
||||
value interface{} // 变量值
|
||||
safe bool // 当为true时, value为 *gtype.Interface 类型
|
||||
value interface{} // Underlying value.
|
||||
safe bool // Concurrent safe or not.
|
||||
}
|
||||
|
||||
// 创建一个动态变量,value参数可以为nil
|
||||
// New returns a new Var with given <value>.
|
||||
// The param <unsafe> used to specify whether using Var with un-concurrent-safety,
|
||||
// which is false in default, means concurrent-safe.
|
||||
func New(value interface{}, unsafe...bool) *Var {
|
||||
v := &Var{}
|
||||
if len(unsafe) == 0 || !unsafe[0] {
|
||||
@ -31,16 +33,19 @@ func New(value interface{}, unsafe...bool) *Var {
|
||||
return v
|
||||
}
|
||||
|
||||
// 创建一个只读动态变量,value参数可以为nil
|
||||
// NewRead returns a read-only interface object with given <value>.
|
||||
// The param <unsafe> used to specify whether using Var with un-concurrent-safety,
|
||||
// which is false in default, means concurrent-safe.
|
||||
func NewRead(value interface{}, unsafe...bool) VarRead {
|
||||
return VarRead(New(value, unsafe...))
|
||||
}
|
||||
|
||||
// 返回动态变量的只读接口
|
||||
// ReadOnly returns a read-only interface object of <v>.
|
||||
func (v *Var) ReadOnly() VarRead {
|
||||
return VarRead(v)
|
||||
}
|
||||
|
||||
// Set sets <value> to <v>, and returns the old value.
|
||||
func (v *Var) Set(value interface{}) (old interface{}) {
|
||||
if v.safe {
|
||||
old = v.value.(*gtype.Interface).Set(value)
|
||||
@ -51,6 +56,7 @@ func (v *Var) Set(value interface{}) (old interface{}) {
|
||||
return
|
||||
}
|
||||
|
||||
// Val returns the current value of <v>.
|
||||
func (v *Var) Val() interface{} {
|
||||
if v.safe {
|
||||
return v.value.(*gtype.Interface).Val()
|
||||
@ -59,11 +65,38 @@ func (v *Var) Val() interface{} {
|
||||
}
|
||||
}
|
||||
|
||||
// Val() 别名
|
||||
// See Val().
|
||||
func (v *Var) Interface() interface{} {
|
||||
return v.Val()
|
||||
}
|
||||
|
||||
// Time converts and returns <v> as time.Time.
|
||||
// The param <format> 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...)
|
||||
}
|
||||
|
||||
// TimeDuration converts and returns <v> as time.Duration.
|
||||
// If value of <v> is string, then it uses time.ParseDuration for conversion.
|
||||
func (v *Var) TimeDuration() time.Duration {
|
||||
return gconv.TimeDuration(v.Val())
|
||||
}
|
||||
|
||||
// GTime converts and returns <v> as *gtime.Time.
|
||||
// The param <format> 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...)
|
||||
}
|
||||
|
||||
// Struct maps value of <v> to <objPointer>.
|
||||
// The param <objPointer> should be a pointer to a struct instance.
|
||||
// The param <attrMapping> is used to specify the key-to-attribute mapping rules.
|
||||
func (v *Var) Struct(objPointer interface{}, attrMapping...map[string]string) error {
|
||||
return gconv.Struct(v.Val(), objPointer, attrMapping...)
|
||||
}
|
||||
|
||||
func (v *Var) IsNil() bool { return v.Val() == nil }
|
||||
func (v *Var) Bytes() []byte { return gconv.Bytes(v.Val()) }
|
||||
func (v *Var) String() string { return gconv.String(v.Val()) }
|
||||
@ -88,19 +121,3 @@ func (v *Var) Ints() []int { return gconv.Ints(v.Val()) }
|
||||
func (v *Var) Floats() []float64 { return gconv.Floats(v.Val()) }
|
||||
func (v *Var) Strings() []string { return gconv.Strings(v.Val()) }
|
||||
func (v *Var) Interfaces() []interface{} { return gconv.Interfaces(v.Val()) }
|
||||
|
||||
func (v *Var) Time(format...string) time.Time {
|
||||
return gconv.Time(v.Val(), format...)
|
||||
}
|
||||
func (v *Var) TimeDuration() time.Duration {
|
||||
return gconv.TimeDuration(v.Val())
|
||||
}
|
||||
|
||||
func (v *Var) GTime(format...string) *gtime.Time {
|
||||
return gconv.GTime(v.Val(), format...)
|
||||
}
|
||||
|
||||
// 将变量转换为对象,注意 objPointer 参数必须为struct指针
|
||||
func (v *Var) Struct(objPointer interface{}, attrMapping...map[string]string) error {
|
||||
return gconv.Struct(v.Val(), objPointer, attrMapping...)
|
||||
}
|
@ -11,7 +11,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// 只读变量接口
|
||||
// Read-only interface.
|
||||
type VarRead interface {
|
||||
Val() interface{}
|
||||
IsNil() bool
|
||||
@ -31,10 +31,12 @@ type VarRead interface {
|
||||
Float32() float32
|
||||
Float64() float64
|
||||
Interface() interface{}
|
||||
|
||||
Ints() []int
|
||||
Floats() []float64
|
||||
Strings() []string
|
||||
Interfaces() []interface{}
|
||||
|
||||
Time(format ...string) time.Time
|
||||
TimeDuration() time.Duration
|
||||
GTime(format...string) *gtime.Time
|
||||
|
@ -7,19 +7,24 @@
|
||||
package gconv
|
||||
|
||||
import (
|
||||
"time"
|
||||
"github.com/gogf/gf/g/os/gtime"
|
||||
"github.com/gogf/gf/g/text/gstr"
|
||||
"github.com/gogf/gf/g/os/gtime"
|
||||
"github.com/gogf/gf/g/text/gstr"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 将变量i转换为time.Time类型
|
||||
// 将变量i转换为time.Time类型。
|
||||
func Time(i interface{}, format...string) time.Time {
|
||||
return GTime(i, format...).Time
|
||||
}
|
||||
|
||||
// 将变量i转换为time.Time类型
|
||||
// 将变量i转换为time.Duration类型,支持字符串格式。
|
||||
func TimeDuration(i interface{}) time.Duration {
|
||||
return time.Duration(Int64(i))
|
||||
s := String(i)
|
||||
if gstr.IsNumeric(s) {
|
||||
d, _ := time.ParseDuration(s)
|
||||
return d
|
||||
}
|
||||
return time.Duration(Int64(i))
|
||||
}
|
||||
|
||||
// 将变量i转换为time.Time类型, 自动识别i为时间戳或者标准化的时间字符串。
|
||||
|
@ -1,9 +1,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g/os/gfile"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println("10" > "4")
|
||||
if r, e := ghttp.Get("https://goframe.org/cover.png"); e != nil {
|
||||
panic(e)
|
||||
} else {
|
||||
defer r.Close()
|
||||
gfile.PutBinContents("/Users/john/Temp/cover.png", r.ReadAll())
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user