refacting gmap

This commit is contained in:
John 2019-05-07 22:28:34 +08:00
parent 48b1d616c5
commit 4c647aaa19
28 changed files with 408 additions and 352 deletions

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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()

View File

@ -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)

View File

@ -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
}
}

View File

@ -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

View 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
}
}

View File

@ -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...)
}

View File

@ -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

View File

@ -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为时间戳或者标准化的时间字符串。

View File

@ -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())
}
}