diff --git a/TODO.MD b/TODO.MD index f11ec2211..1efa597b9 100644 --- a/TODO.MD +++ b/TODO.MD @@ -40,7 +40,9 @@ 1. 改进gproc进程间通信处理逻辑,提高稳定性,以应对进程间大批量的数据发送/接收; 1. ghttp的热重启的本地进程端口监听,在不使用该特性时默认关闭掉; 1. gtcp增加对TLS加密通信的支持; - +1. 添加Save/Replace/BatchSave/BatchReplace方法对sqlite数据库的支持; +1. 添加sqlite数据库的单元测试用例; +1. gredis增加cluster支持; # DONE diff --git a/g/container/garray/garray.go b/g/container/garray/garray.go index effd62079..35f367894 100644 --- a/g/container/garray/garray.go +++ b/g/container/garray/garray.go @@ -4,8 +4,6 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -// Package garray provides kinds of concurrent-safe(alternative) arrays. -// -// 并发安全数组. +// Package garray provides concurrent-safe/unsafe arrays. package garray diff --git a/g/container/gchan/gchan.go b/g/container/gchan/gchan.go index 1ef693fdf..6b6be6da3 100644 --- a/g/container/gchan/gchan.go +++ b/g/container/gchan/gchan.go @@ -4,9 +4,9 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -// Package gchan provides graceful operations for channel. +// Package gchan provides graceful channel for safe operations. // -// 优雅的Channel操作. +// It's safe to call Chan.Push/Close functions repeatedly. package gchan import ( @@ -15,39 +15,48 @@ import ( ) type Chan struct { - list chan interface{} - closed *gtype.Bool + channel chan interface{} + closed *gtype.Bool } +// New creates a graceful channel with given limit. func New(limit int) *Chan { return &Chan { - list : make(chan interface{}, limit), - closed : gtype.NewBool(), + channel : make(chan interface{}, limit), + closed : gtype.NewBool(), } } -// 将数据压入队列 -func (q *Chan) Push(v interface{}) error { - if q.closed.Val() { +// Push pushes to channel. +// It is safe to be called repeatedly. +func (c *Chan) Push(value interface{}) error { + if c.closed.Val() { return errors.New("closed") } - q.list <- v + c.channel <- value return nil } -// 先进先出地从队列取出一项数据,当没有数据可获取时,阻塞等待 -func (q *Chan) Pop() interface{} { - return <- q.list +// Pop pops value from channel. +// If there's no value in channel, it would block to wait. +func (c *Chan) Pop() interface{} { + return <- c.channel } -// 关闭队列(通知所有通过Pop阻塞的协程退出) -func (q *Chan) Close() { - if !q.closed.Set(true) { - close(q.list) +// Close closes the channel. +// It is safe to be called repeatedly. +func (c *Chan) Close() { + if !c.closed.Set(true) { + close(c.channel) } } -// 获取当前队列大小 -func (q *Chan) Size() int { - return len(q.list) +// See Len. +func (c *Chan) Size() int { + return c.Len() +} + +// Len returns the length of the channel. +func (c *Chan) Len() int { + return len(c.channel) } \ No newline at end of file diff --git a/g/container/glist/glist.go b/g/container/glist/glist.go index 4fe925900..e9c3a6080 100644 --- a/g/container/glist/glist.go +++ b/g/container/glist/glist.go @@ -5,9 +5,7 @@ // You can obtain one at https://github.com/gogf/gf. // -// Package glist provides a concurrent-safe(alternative) doubly linked list. -// -// 并发安全双向链表. +// Package glist provides a concurrent-safe/unsafe doubly linked list. package glist import ( @@ -15,14 +13,14 @@ import ( "github.com/gogf/gf/g/internal/rwmutex" ) -// 变长双向链表 -type List struct { - mu *rwmutex.RWMutex - list *list.List -} - -type Element = list.Element +type ( + List struct { + mu *rwmutex.RWMutex + list *list.List + } + Element = list.Element +) // 获得一个变长链表指针 func New(unsafe...bool) *List { diff --git a/g/container/gmap/gmap.go b/g/container/gmap/gmap.go index c2a982aab..4d2685698 100644 --- a/g/container/gmap/gmap.go +++ b/g/container/gmap/gmap.go @@ -4,46 +4,34 @@ // If a copy of the MIT was not distributed with gm file, // You can obtain one at https://github.com/gogf/gf. -// Package gmap provides kinds of concurrent-safe(alternative) maps. -// -// 并发安全MAP. +// Package gmap provides concurrent-safe/unsafe maps. package gmap import "github.com/gogf/gf/g/internal/rwmutex" -// 注意: -// 1、这个Map是所有并发安全Map中效率最低的,如果对效率要求比较高的场合,请合理选择对应数据类型的Map; -// 2、这个Map的优点是使用简便,由于键值都是interface{}类型,因此对键值的数据类型要求不高; -// 3、底层实现比较类似于sync.Map; type Map struct { mu *rwmutex.RWMutex m map[interface{}]interface{} } -// Create an empty hash map. +// New returns an empty hash map. // The param used to specify whether using map with un-concurrent-safety, -// which is false in default, means concurrent-safe in default. -// -// 创建一个空的哈希表,参数unsafe用于指定是否用于非并发安全场景,默认为false,表示并发安全。 -func New(unsafe...bool) *Map { +// which is false in default, means concurrent-safe. +func New(unsafe ...bool) *Map { return NewMap(unsafe...) } -// See New. -// -// 同New方法。 -func NewMap(unsafe...bool) *Map { +// Alias of New. See New. +func NewMap(unsafe ...bool) *Map { return &Map{ m : make(map[interface{}]interface{}), mu : rwmutex.New(unsafe...), } } -// Create a hash map from given map. -// Be aware that, the param map is a type of pointer, +// NewFrom returns a hash map from given map . +// Notice that, the param map is a type of pointer, // there might be some concurrent-safe issues when changing the map outside. -// -// 基于给定的map变量创建哈希表对象,注意由于map是指针类型,外部对map有操作时会有并发安全问题。 func NewFrom(m map[interface{}]interface{}, unsafe...bool) *Map { return &Map{ m : m, @@ -51,12 +39,12 @@ func NewFrom(m map[interface{}]interface{}, unsafe...bool) *Map { } } -// Create a hash map from given arrays. +// NewFromArray returns a hash map from given array. // The param given as the keys of the map, -// and as the corresponding values. +// and as its corresponding values. // -// 基于给定的数组变量创建哈希表对象,keys作为键名, values作为键值。 -// 当keys数组大小比values数组大时,多余的键名将会使用对应类型默认的键值。 +// If length of is greater than that of , +// 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) @@ -73,10 +61,8 @@ func NewFromArray(keys []interface{}, values []interface{}, unsafe...bool) *Map } } -// Iterate the hash map with custom callback function . +// Iterator iterates the hash map with custom callback function . // If f returns true, then continue iterating; or false to stop. -// -// 给定回调函数对原始内容进行遍历,回调函数返回true表示继续遍历,否则停止遍历 func (gm *Map) Iterator(f func (k interface{}, v interface{}) bool) { gm.mu.RLock() defer gm.mu.RUnlock() @@ -87,17 +73,12 @@ func (gm *Map) Iterator(f func (k interface{}, v interface{}) bool) { } } -// Clone current hash map with copy of underlying data, -// return a new hash map. -// -// 哈希表克隆. -func (gm *Map) Clone() *Map { - return NewFrom(gm.Map(), !gm.mu.IsSafe()) +// Clone returns a new hash map with copy of current map data. +func (gm *Map) Clone(unsafe ...bool) *Map { + return NewFrom(gm.Map(), unsafe ...) } -// Returns copy of the data of the hash map. -// -// 返回当前哈希表的数据Map. +// 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() @@ -108,18 +89,14 @@ func (gm *Map) Map() map[interface{}]interface{} { return m } -// Set key-value to the hash map. -// -// 设置键值对 +// 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() } -// Batch set key-values to the hash map. -// -// 批量设置键值对 +// 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 { @@ -128,9 +105,7 @@ func (gm *Map) BatchSet(m map[interface{}]interface{}) { gm.mu.Unlock() } -// Get value by key. -// -// 获取键值 +// Get returns the value by given . func (gm *Map) Get(key interface{}) interface{} { gm.mu.RLock() val, _ := gm.m[key] @@ -138,8 +113,15 @@ func (gm *Map) Get(key interface{}) interface{} { return val } -// 设置kv缓存键值对,内部会对键名的存在性使用写锁进行二次检索确认,如果存在则不再写入;返回键名对应的键值。 -// 在高并发下有用,防止数据写入的并发逻辑错误。 +// doSetWithLockCheck checks whether value of the key exists with mutex.Lock, +// if not exists, set value to the map with given , +// or else just return the existing value. +// +// When setting value, if is type of , +// it will be executed with mutex.Lock of the hash map, +// and its return value will be set to the map with . +// +// It returns value with given . func (gm *Map) doSetWithLockCheck(key interface{}, value interface{}) interface{} { gm.mu.Lock() defer gm.mu.Unlock() @@ -153,9 +135,8 @@ func (gm *Map) doSetWithLockCheck(key interface{}, value interface{}) interface{ return value } -// Get the value by key, or set it with given key-value if not exist. -// -// 当键名存在时返回其键值,否则写入指定的键值 +// GetOrSet returns the value by key, +// or set value with given 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) @@ -164,9 +145,9 @@ func (gm *Map) GetOrSet(key interface{}, value interface{}) interface{} { } } -// Get the value by key, or set the it with return of callback function if not exist. -// -// 当键名存在时返回其键值,否则写入指定的键值,键值由指定的函数生成 +// GetOrSetFunc returns the value by key, +// or sets value with return value of callback function 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()) @@ -175,10 +156,12 @@ func (gm *Map) GetOrSetFunc(key interface{}, f func() interface{}) interface{} { } } -// Get the value by key, or set the it with return of callback function if not exist. -// The difference with GetOrSetFunc is, it locks in executing callback function . +// GetOrSetFuncLock returns the value by key, +// or sets value with return value of callback function if not exist +// and returns this value. // -// 与GetOrSetFunc不同的是,f是在写锁机制内执行 +// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function +// 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) @@ -187,9 +170,8 @@ func (gm *Map) GetOrSetFuncLock(key interface{}, f func() interface{}) interface } } -// Set key-value if the key does not exist, then return true; or else return false. -// -// 当键名不存在时写入,并返回true;否则返回false。 +// SetIfNotExist sets to the map if the does not exist, then return true. +// It returns false if exists, and would be ignored. func (gm *Map) SetIfNotExist(key interface{}, value interface{}) bool { if !gm.Contains(key) { gm.doSetWithLockCheck(key, value) @@ -198,9 +180,30 @@ func (gm *Map) SetIfNotExist(key interface{}, value interface{}) bool { return false } -// Batch remove by keys. +// SetIfNotExistFunc sets value with return value of callback function , then return true. +// It returns false if exists, and 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 , then return true. +// It returns false if exists, and would be ignored. // -// 批量删除键值对 +// SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that +// it executes function 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 { @@ -209,9 +212,7 @@ func (gm *Map) BatchRemove(keys []interface{}) { gm.mu.Unlock() } -// Remove by given key. -// -// 返回对应的键值,并删除该键值 +// Remove deletes value from map by given , and return this deleted value. func (gm *Map) Remove(key interface{}) interface{} { gm.mu.Lock() val, exists := gm.m[key] @@ -222,9 +223,7 @@ func (gm *Map) Remove(key interface{}) interface{} { return val } -// Return all the keys of hash map as a slice. -// -// 返回键列表. +// Keys returns all keys of the map as a slice. func (gm *Map) Keys() []interface{} { gm.mu.RLock() keys := make([]interface{}, 0) @@ -235,9 +234,7 @@ func (gm *Map) Keys() []interface{} { return keys } -// Return all the values of hash map as a slice. -// -// 返回值列表(注意是随机排序) +// Values returns all values of the map as a slice. func (gm *Map) Values() []interface{} { gm.mu.RLock() vals := make([]interface{}, 0) @@ -248,9 +245,8 @@ func (gm *Map) Values() []interface{} { return vals } -// Check whether a key exist. -// -// 是否存在某个键 +// Contains checks whether a key exists. +// It returns true if the exists, or else false. func (gm *Map) Contains(key interface{}) bool { gm.mu.RLock() _, exists := gm.m[key] @@ -258,9 +254,7 @@ func (gm *Map) Contains(key interface{}) bool { return exists } -// Get the size of hash map. -// -// 哈希表大小 +// Size returns the size of the map. func (gm *Map) Size() int { gm.mu.RLock() length := len(gm.m) @@ -268,9 +262,8 @@ func (gm *Map) Size() int { return length } -// Check whether the hash map is empty. -// -// 哈希表是否为空 +// 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 @@ -278,36 +271,28 @@ func (gm *Map) IsEmpty() bool { return empty } -// Clear the hash map, it will remake a new underlying map data map. -// -// 清空哈希表 +// 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() } -// Lock writing with given callback . -// -// 并发安全锁操作,使用自定义方法执行加锁修改操作 +// LockFunc locks writing with given callback function and mutex.Lock. func (gm *Map) LockFunc(f func(m map[interface{}]interface{})) { gm.mu.Lock() defer gm.mu.Unlock() f(gm.m) } -// Lock reading with given callback . -// -// 并发安全锁操作,使用自定义方法执行加锁读取操作 +// RLockFunc locks reading with given callback function and mutex.RLock. func (gm *Map) RLockFunc(f func(m map[interface{}]interface{})) { gm.mu.RLock() defer gm.mu.RUnlock() f(gm.m) } -// Exchange key-value in the hash map, it will change key-value to value-key. -// -// 交换Map中的键和值. +// 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() @@ -318,17 +303,16 @@ func (gm *Map) Flip() { gm.m = n } -// Merge two hash maps. -// -// 合并两个Map. -func (gm *Map) Merge(m *Map) { +// Merge merges two hash maps. +// The map will be merged into the map . +func (gm *Map) Merge(other *Map) { gm.mu.Lock() defer gm.mu.Unlock() - if m != gm { - m.mu.RLock() - defer m.mu.RUnlock() + if other != gm { + other.mu.RLock() + defer other.mu.RUnlock() } - for k, v := range m.m { + for k, v := range other.m { gm.m[k] = v } } \ No newline at end of file diff --git a/g/container/gmap/gmap_int_bool_map.go b/g/container/gmap/gmap_int_bool_map.go index 035bc3e4d..519a7f05e 100644 --- a/g/container/gmap/gmap_int_bool_map.go +++ b/g/container/gmap/gmap_int_bool_map.go @@ -16,6 +16,9 @@ type IntBoolMap struct { mu *rwmutex.RWMutex } +// NewIntBoolMap returns an empty IntBoolMap object. +// The param used to specify whether using map with un-concurrent-safety, +// which is false in default, means concurrent-safe. func NewIntBoolMap(unsafe...bool) *IntBoolMap { return &IntBoolMap{ m : make(map[int]bool), @@ -23,6 +26,9 @@ func NewIntBoolMap(unsafe...bool) *IntBoolMap { } } +// NewIntBoolMapFrom returns an IntBoolMap object from given map . +// Notice that, the param map is a type of pointer, +// there might be some concurrent-safe issues when changing the map outside. func NewIntBoolMapFrom(m map[int]bool, unsafe...bool) *IntBoolMap { return &IntBoolMap{ m : m, @@ -30,6 +36,12 @@ func NewIntBoolMapFrom(m map[int]bool, unsafe...bool) *IntBoolMap { } } +// NewIntBoolMapFromArray returns an IntBoolMap from given array. +// The param given as the keys of the map, +// and as its corresponding values. +// +// If length of is greater than that of , +// the corresponding overflow map values will be the default value of its type. func NewIntBoolMapFromArray(keys []int, values []bool, unsafe...bool) *IntBoolMap { m := make(map[int]bool) l := len(values) @@ -46,12 +58,12 @@ func NewIntBoolMapFromArray(keys []int, values []bool, unsafe...bool) *IntBoolMa } } -// 哈希表克隆. +// Clone returns a new hash map with copy of current map data. func (gm *IntBoolMap) Clone() *IntBoolMap { return NewIntBoolMapFrom(gm.Map(), !gm.mu.IsSafe()) } -// 返回当前哈希表的数据Map. +// Map returns a copy of the data of the hash map. func (gm *IntBoolMap) Map() map[int]bool { m := make(map[int]bool) gm.mu.RLock() @@ -62,7 +74,8 @@ func (gm *IntBoolMap) Map() map[int]bool { return m } -// 给定回调函数对原始内容进行遍历,回调函数返回true表示继续遍历,否则停止遍历 +// Iterator iterates the hash map with custom callback function . +// If f returns true, then continue iterating; or false to stop. func (gm *IntBoolMap) Iterator(f func (k int, v bool) bool) { gm.mu.RLock() defer gm.mu.RUnlock() @@ -73,14 +86,14 @@ func (gm *IntBoolMap) Iterator(f func (k int, v bool) bool) { } } -// 设置键值对 +// Set sets key-value to the hash map. func (gm *IntBoolMap) Set(key int, val bool) { gm.mu.Lock() gm.m[key] = val gm.mu.Unlock() } -// 批量设置键值对 +// BatchSet batch sets key-values to the hash map. func (gm *IntBoolMap) BatchSet(m map[int]bool) { gm.mu.Lock() for k, v := range m { @@ -89,7 +102,7 @@ func (gm *IntBoolMap) BatchSet(m map[int]bool) { gm.mu.Unlock() } -// 获取键值 +// Get returns the value by given . func (gm *IntBoolMap) Get(key int) bool { gm.mu.RLock() val, _ := gm.m[key] @@ -97,8 +110,11 @@ func (gm *IntBoolMap) Get(key int) bool { return val } -// 设置kv缓存键值对,内部会对键名的存在性使用写锁进行二次检索确认,如果存在则不再写入;返回键名对应的键值。 -// 在高并发下有用,防止数据写入的并发逻辑错误。 +// doSetWithLockCheck checks whether value of the key exists with mutex.Lock, +// if not exists, set value to the map with given , +// or else just return the existing value. +// +// It returns value with given . func (gm *IntBoolMap) doSetWithLockCheck(key int, value bool) bool { gm.mu.Lock() if v, ok := gm.m[key]; ok { @@ -110,7 +126,8 @@ func (gm *IntBoolMap) doSetWithLockCheck(key int, value bool) bool { return value } -// 当键名存在时返回其键值,否则写入指定的键值 +// GetOrSet returns the value by key, +// or set value with given if not exist and returns this value. func (gm *IntBoolMap) GetOrSet(key int, value bool) bool { gm.mu.RLock() v, ok := gm.m[key] @@ -122,7 +139,8 @@ func (gm *IntBoolMap) GetOrSet(key int, value bool) bool { } } -// 当键名存在时返回其键值,否则写入指定的键值,键值由指定的函数生成 +// GetOrSetFunc returns the value by key, +// or sets value with return value of callback function if not exist and returns this value. func (gm *IntBoolMap) GetOrSetFunc(key int, f func() bool) bool { gm.mu.RLock() v, ok := gm.m[key] @@ -134,7 +152,11 @@ func (gm *IntBoolMap) GetOrSetFunc(key int, f func() bool) bool { } } -// 与GetOrSetFunc不同的是,f是在写锁机制内执行 +// GetOrSetFuncLock returns the value by key, +// or sets value with return value of callback function if not exist and returns this value. +// +// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function +// with mutex.Lock of the hash map. func (gm *IntBoolMap) GetOrSetFuncLock(key int, f func() bool) bool { gm.mu.RLock() val, ok := gm.m[key] @@ -143,10 +165,9 @@ func (gm *IntBoolMap) GetOrSetFuncLock(key int, f func() bool) bool { gm.mu.Lock() defer gm.mu.Unlock() if v, ok := gm.m[key]; ok { - gm.mu.Unlock() return v } - val = f() + val = f() gm.m[key] = val return val } else { @@ -154,7 +175,8 @@ func (gm *IntBoolMap) GetOrSetFuncLock(key int, f func() bool) bool { } } -// 当键名不存在时写入,并返回true;否则返回false。 +// SetIfNotExist sets to the map if the does not exist, then return true. +// It returns false if exists, and would be ignored. func (gm *IntBoolMap) SetIfNotExist(key int, value bool) bool { if !gm.Contains(key) { gm.doSetWithLockCheck(key, value) @@ -163,7 +185,34 @@ func (gm *IntBoolMap) SetIfNotExist(key int, value bool) bool { return false } -// 批量删除键值对 +// SetIfNotExistFunc sets value with return value of callback function , then return true. +// It returns false if exists, and would be ignored. +func (gm *IntBoolMap) SetIfNotExistFunc(key int, f func() bool) bool { + if !gm.Contains(key) { + gm.doSetWithLockCheck(key, f()) + return true + } + return false +} + +// SetIfNotExistFuncLock sets value with return value of callback function , then return true. +// It returns false if exists, and would be ignored. +// +// SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that +// it executes function with mutex.Lock of the hash map. +func (gm *IntBoolMap) SetIfNotExistFuncLock(key int, f func() bool) bool { + if !gm.Contains(key) { + gm.mu.Lock() + defer gm.mu.Unlock() + if _, ok := gm.m[key]; !ok { + gm.m[key] = f() + } + return true + } + return false +} + +// BatchRemove batch deletes values of the map by keys. func (gm *IntBoolMap) BatchRemove(keys []int) { gm.mu.Lock() for _, key := range keys { @@ -172,7 +221,7 @@ func (gm *IntBoolMap) BatchRemove(keys []int) { gm.mu.Unlock() } -// 返回对应的键值,并删除该键值 +// Remove deletes value from map by given , and return this deleted value. func (gm *IntBoolMap) Remove(key int) bool { gm.mu.Lock() val, exists := gm.m[key] @@ -183,7 +232,7 @@ func (gm *IntBoolMap) Remove(key int) bool { return val } -// 返回键列表 +// Keys returns all keys of the map as a slice. func (gm *IntBoolMap) Keys() []int { gm.mu.RLock() keys := make([]int, 0) @@ -194,18 +243,8 @@ func (gm *IntBoolMap) Keys() []int { return keys } -// 返回值列表(注意是随机排序) -//func (gm *IntBoolMap) Values() []bool { -// gm.mu.RLock() -// vals := make([]bool, 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 exists, or else false. func (gm *IntBoolMap) Contains(key int) bool { gm.mu.RLock() _, exists := gm.m[key] @@ -213,7 +252,7 @@ func (gm *IntBoolMap) Contains(key int) bool { return exists } -// 哈希表大小 +// Size returns the size of the map. func (gm *IntBoolMap) Size() int { gm.mu.RLock() length := len(gm.m) @@ -221,7 +260,8 @@ func (gm *IntBoolMap) Size() int { return length } -// 哈希表是否为空 +// IsEmpty checks whether the map is empty. +// It returns true if map is empty, or else false. func (gm *IntBoolMap) IsEmpty() bool { gm.mu.RLock() empty := len(gm.m) == 0 @@ -229,36 +269,37 @@ func (gm *IntBoolMap) IsEmpty() bool { return empty } -// 清空哈希表 +// Clear deletes all data of the map, it will remake a new underlying map data map. func (gm *IntBoolMap) Clear() { gm.mu.Lock() gm.m = make(map[int]bool) gm.mu.Unlock() } -// 并发安全锁操作,使用自定义方法执行加锁修改操作 +// LockFunc locks writing with given callback function and mutex.Lock. func (gm *IntBoolMap) LockFunc(f func(m map[int]bool)) { gm.mu.Lock() defer gm.mu.Unlock() f(gm.m) } -// 并发安全锁操作,使用自定义方法执行加锁读取操作 +// RLockFunc locks reading with given callback function and mutex.RLock. func (gm *IntBoolMap) RLockFunc(f func(m map[int]bool)) { gm.mu.RLock() defer gm.mu.RUnlock() f(gm.m) } -// 合并两个Map. -func (gm *IntBoolMap) Merge(m *IntBoolMap) { +// Merge merges two hash maps. +// The map will be merged into the map . +func (gm *IntBoolMap) Merge(other *IntBoolMap) { gm.mu.Lock() defer gm.mu.Unlock() - if m != gm { - m.mu.RLock() - defer m.mu.RUnlock() + if other != gm { + other.mu.RLock() + defer other.mu.RUnlock() } - for k, v := range m.m { + for k, v := range other.m { gm.m[k] = v } } \ No newline at end of file diff --git a/g/container/gmap/gmap_int_int_map.go b/g/container/gmap/gmap_int_int_map.go index 723365dc4..8d756479c 100644 --- a/g/container/gmap/gmap_int_int_map.go +++ b/g/container/gmap/gmap_int_int_map.go @@ -16,6 +16,9 @@ type IntIntMap struct { m map[int]int } +// NewIntIntMap returns an empty IntIntMap object. +// The param used to specify whether using map with un-concurrent-safety, +// which is false in default, means concurrent-safe. func NewIntIntMap(unsafe...bool) *IntIntMap { return &IntIntMap{ m : make(map[int]int), @@ -23,6 +26,9 @@ func NewIntIntMap(unsafe...bool) *IntIntMap { } } +// NewIntIntMapFrom returns an IntIntMap object from given map . +// Notice that, the param map is a type of pointer, +// there might be some concurrent-safe issues when changing the map outside. func NewIntIntMapFrom(m map[int]int, unsafe...bool) *IntIntMap { return &IntIntMap{ m : m, @@ -30,6 +36,12 @@ func NewIntIntMapFrom(m map[int]int, unsafe...bool) *IntIntMap { } } +// NewIntIntMapFromArray returns an IntIntMap object from given array. +// The param given as the keys of the map, +// and as its corresponding values. +// +// If length of is greater than that of , +// the corresponding overflow map values will be the default value of its type. func NewIntIntMapFromArray(keys []int, values []int, unsafe...bool) *IntIntMap { m := make(map[int]int) l := len(values) @@ -46,7 +58,8 @@ func NewIntIntMapFromArray(keys []int, values []int, unsafe...bool) *IntIntMap { } } -// 给定回调函数对原始内容进行遍历,回调函数返回true表示继续遍历,否则停止遍历 +// Iterator iterates the hash map with custom callback function . +// If f returns true, then continue iterating; or false to stop. func (gm *IntIntMap) Iterator(f func (k int, v int) bool) { gm.mu.RLock() defer gm.mu.RUnlock() @@ -57,12 +70,12 @@ func (gm *IntIntMap) Iterator(f func (k int, v int) bool) { } } -// 哈希表克隆. +// Clone returns a new hash map with copy of current map data. func (gm *IntIntMap) Clone() *IntIntMap { return NewIntIntMapFrom(gm.Map(), !gm.mu.IsSafe()) } -// 返回当前哈希表的数据Map. +// Map returns a copy of the data of the hash map. func (gm *IntIntMap) Map() map[int]int { m := make(map[int]int) gm.mu.RLock() @@ -73,14 +86,14 @@ func (gm *IntIntMap) Map() map[int]int { return m } -// 设置键值对 +// Set sets key-value to the hash map. func (gm *IntIntMap) Set(key int, val int) { gm.mu.Lock() gm.m[key] = val gm.mu.Unlock() } -// 批量设置键值对 +// BatchSet batch sets key-values to the hash map. func (gm *IntIntMap) BatchSet(m map[int]int) { gm.mu.Lock() for k, v := range m { @@ -89,7 +102,7 @@ func (gm *IntIntMap) BatchSet(m map[int]int) { gm.mu.Unlock() } -// 获取键值 +// Get returns the value by given . func (gm *IntIntMap) Get(key int) (int) { gm.mu.RLock() val, _ := gm.m[key] @@ -97,8 +110,11 @@ func (gm *IntIntMap) Get(key int) (int) { return val } -// 设置kv缓存键值对,内部会对键名的存在性使用写锁进行二次检索确认,如果存在则不再写入;返回键名对应的键值。 -// 在高并发下有用,防止数据写入的并发逻辑错误。 +// doSetWithLockCheck checks whether value of the key exists with mutex.Lock, +// if not exists, set value to the map with given , +// or else just return the existing value. +// +// It returns value with given . func (gm *IntIntMap) doSetWithLockCheck(key int, value int) int { gm.mu.Lock() if v, ok := gm.m[key]; ok { @@ -110,7 +126,8 @@ func (gm *IntIntMap) doSetWithLockCheck(key int, value int) int { return value } -// 当键名存在时返回其键值,否则写入指定的键值 +// GetOrSet returns the value by key, +// or set value with given if not exist and returns this value. func (gm *IntIntMap) GetOrSet(key int, value int) int { gm.mu.RLock() v, ok := gm.m[key] @@ -122,7 +139,8 @@ func (gm *IntIntMap) GetOrSet(key int, value int) int { } } -// 当键名存在时返回其键值,否则写入指定的键值,键值由指定的函数生成 +// GetOrSetFunc returns the value by key, +// or sets value with return value of callback function if not exist and returns this value. func (gm *IntIntMap) GetOrSetFunc(key int, f func() int) int { gm.mu.RLock() v, ok := gm.m[key] @@ -134,7 +152,11 @@ func (gm *IntIntMap) GetOrSetFunc(key int, f func() int) int { } } -// 与GetOrSetFunc不同的是,f是在写锁机制内执行 +// GetOrSetFuncLock returns the value by key, +// or sets value with return value of callback function if not exist and returns this value. +// +// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function +// with mutex.Lock of the hash map. func (gm *IntIntMap) GetOrSetFuncLock(key int, f func() int) int { gm.mu.RLock() val, ok := gm.m[key] @@ -143,7 +165,6 @@ func (gm *IntIntMap) GetOrSetFuncLock(key int, f func() int) int { gm.mu.Lock() defer gm.mu.Unlock() if v, ok := gm.m[key]; ok { - gm.mu.Unlock() return v } val = f() @@ -154,7 +175,8 @@ func (gm *IntIntMap) GetOrSetFuncLock(key int, f func() int) int { } } -// 当键名不存在时写入,并返回true;否则返回false。 +// SetIfNotExist sets to the map if the does not exist, then return true. +// It returns false if exists, and would be ignored. func (gm *IntIntMap) SetIfNotExist(key int, value int) bool { if !gm.Contains(key) { gm.doSetWithLockCheck(key, value) @@ -163,7 +185,34 @@ func (gm *IntIntMap) SetIfNotExist(key int, value int) bool { return false } -// 批量删除键值对 +// SetIfNotExistFunc sets value with return value of callback function , then return true. +// It returns false if exists, and would be ignored. +func (gm *IntIntMap) SetIfNotExistFunc(key int, f func() int) bool { + if !gm.Contains(key) { + gm.doSetWithLockCheck(key, f()) + return true + } + return false +} + +// SetIfNotExistFuncLock sets value with return value of callback function , then return true. +// It returns false if exists, and would be ignored. +// +// SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that +// it executes function with mutex.Lock of the hash map. +func (gm *IntIntMap) SetIfNotExistFuncLock(key int, f func() int) bool { + if !gm.Contains(key) { + gm.mu.Lock() + defer gm.mu.Unlock() + if _, ok := gm.m[key]; !ok { + gm.m[key] = f() + } + return true + } + return false +} + +// BatchRemove batch deletes values of the map by keys. func (gm *IntIntMap) BatchRemove(keys []int) { gm.mu.Lock() for _, key := range keys { @@ -172,7 +221,7 @@ func (gm *IntIntMap) BatchRemove(keys []int) { gm.mu.Unlock() } -// 返回对应的键值,并删除该键值 +// Remove deletes value from map by given , and return this deleted value. func (gm *IntIntMap) Remove(key int) int { gm.mu.Lock() val, exists := gm.m[key] @@ -183,7 +232,7 @@ func (gm *IntIntMap) Remove(key int) int { return val } -// 返回键列表 +// Keys returns all keys of the map as a slice. func (gm *IntIntMap) Keys() []int { gm.mu.RLock() keys := make([]int, 0) @@ -194,7 +243,7 @@ func (gm *IntIntMap) Keys() []int { return keys } -// 返回值列表(注意是随机排序) +// Values returns all values of the map as a slice. func (gm *IntIntMap) Values() []int { gm.mu.RLock() vals := make([]int, 0) @@ -205,7 +254,8 @@ func (gm *IntIntMap) Values() []int { return vals } -// 是否存在某个键 +// Contains checks whether a key exists. +// It returns true if the exists, or else false. func (gm *IntIntMap) Contains(key int) bool { gm.mu.RLock() _, exists := gm.m[key] @@ -213,7 +263,7 @@ func (gm *IntIntMap) Contains(key int) bool { return exists } -// 哈希表大小 +// Size returns the size of the map. func (gm *IntIntMap) Size() int { gm.mu.RLock() length := len(gm.m) @@ -221,7 +271,8 @@ func (gm *IntIntMap) Size() int { return length } -// 哈希表是否为空 +// IsEmpty checks whether the map is empty. +// It returns true if map is empty, or else false. func (gm *IntIntMap) IsEmpty() bool { gm.mu.RLock() empty := len(gm.m) == 0 @@ -229,28 +280,28 @@ func (gm *IntIntMap) IsEmpty() bool { return empty } -// 清空哈希表 +// Clear deletes all data of the map, it will remake a new underlying map data map. func (gm *IntIntMap) Clear() { gm.mu.Lock() gm.m = make(map[int]int) gm.mu.Unlock() } -// 并发安全锁操作,使用自定义方法执行加锁修改操作 +// LockFunc locks writing with given callback function and mutex.Lock. func (gm *IntIntMap) LockFunc(f func(m map[int]int)) { gm.mu.Lock() defer gm.mu.Unlock() f(gm.m) } -// 并发安全锁操作,使用自定义方法执行加锁读取操作 +// RLockFunc locks reading with given callback function and mutex.RLock. func (gm *IntIntMap) RLockFunc(f func(m map[int]int)) { gm.mu.RLock() defer gm.mu.RUnlock() f(gm.m) } -// 交换Map中的键和值. +// Flip exchanges key-value of the map, it will change key-value to value-key. func (gm *IntIntMap) Flip() { gm.mu.Lock() defer gm.mu.Unlock() @@ -261,15 +312,16 @@ func (gm *IntIntMap) Flip() { gm.m = n } -// 合并两个Map. -func (gm *IntIntMap) Merge(m *IntIntMap) { +// Merge merges two hash maps. +// The map will be merged into the map . +func (gm *IntIntMap) Merge(other *IntIntMap) { gm.mu.Lock() defer gm.mu.Unlock() - if m != gm { - m.mu.RLock() - defer m.mu.RUnlock() + if other != gm { + other.mu.RLock() + defer other.mu.RUnlock() } - for k, v := range m.m { + for k, v := range other.m { gm.m[k] = v } } diff --git a/g/container/gmap/gmap_int_interface_map.go b/g/container/gmap/gmap_int_interface_map.go index 454bec10a..54aa96ff1 100644 --- a/g/container/gmap/gmap_int_interface_map.go +++ b/g/container/gmap/gmap_int_interface_map.go @@ -17,6 +17,9 @@ type IntInterfaceMap struct { m map[int]interface{} } +// NewIntInterfaceMap returns an empty IntInterfaceMap object. +// The param used to specify whether using map with un-concurrent-safety, +// which is false in default, means concurrent-safe. func NewIntInterfaceMap(unsafe...bool) *IntInterfaceMap { return &IntInterfaceMap{ m : make(map[int]interface{}), @@ -24,6 +27,9 @@ func NewIntInterfaceMap(unsafe...bool) *IntInterfaceMap { } } +// NewIntInterfaceMapFrom returns an IntInterfaceMap object from given map . +// Notice that, the param map is a type of pointer, +// there might be some concurrent-safe issues when changing the map outside. func NewIntInterfaceMapFrom(m map[int]interface{}, unsafe...bool) *IntInterfaceMap { return &IntInterfaceMap{ m : m, @@ -31,6 +37,12 @@ func NewIntInterfaceMapFrom(m map[int]interface{}, unsafe...bool) *IntInterfaceM } } +// NewFromArray returns a hash map from given array. +// The param given as the keys of the map, +// and as its corresponding values. +// +// If length of is greater than that of , +// the corresponding overflow map values will be the default value of its type. func NewIntInterfaceMapFromArray(keys []int, values []interface{}, unsafe...bool) *IntInterfaceMap { m := make(map[int]interface{}) l := len(values) @@ -47,7 +59,8 @@ func NewIntInterfaceMapFromArray(keys []int, values []interface{}, unsafe...bool } } -// 给定回调函数对原始内容进行遍历,回调函数返回true表示继续遍历,否则停止遍历 +// Iterator iterates the hash map with custom callback function . +// If f returns true, then continue iterating; or false to stop. func (gm *IntInterfaceMap) Iterator(f func (k int, v interface{}) bool) { gm.mu.RLock() defer gm.mu.RUnlock() @@ -58,12 +71,12 @@ func (gm *IntInterfaceMap) Iterator(f func (k int, v interface{}) bool) { } } -// 哈希表克隆. +// Clone returns a new hash map with copy of current map data. func (gm *IntInterfaceMap) Clone() *IntInterfaceMap { return NewIntInterfaceMapFrom(gm.Map(), !gm.mu.IsSafe()) } -// 返回当前哈希表的数据Map. +// Map returns a copy of the data of the hash map. func (gm *IntInterfaceMap) Map() map[int]interface{} { m := make(map[int]interface{}) gm.mu.RLock() @@ -74,14 +87,14 @@ func (gm *IntInterfaceMap) Map() map[int]interface{} { return m } -// 设置键值对 +// Set sets key-value to the hash map. func (gm *IntInterfaceMap) Set(key int, val interface{}) { gm.mu.Lock() gm.m[key] = val gm.mu.Unlock() } -// 批量设置键值对 +// BatchSet batch sets key-values to the hash map. func (gm *IntInterfaceMap) BatchSet(m map[int]interface{}) { gm.mu.Lock() for k, v := range m { @@ -90,7 +103,7 @@ func (gm *IntInterfaceMap) BatchSet(m map[int]interface{}) { gm.mu.Unlock() } -// 获取键值 +// Get returns the value by given . func (gm *IntInterfaceMap) Get(key int) (interface{}) { gm.mu.RLock() val, _ := gm.m[key] @@ -98,8 +111,16 @@ func (gm *IntInterfaceMap) Get(key int) (interface{}) { return val } -// 设置kv缓存键值对,内部会对键名的存在性使用写锁进行二次检索确认,如果存在则不再写入;返回键名对应的键值。 -// 在高并发下有用,防止数据写入的并发逻辑错误。 + +// doSetWithLockCheck checks whether value of the key exists with mutex.Lock, +// if not exists, set value to the map with given , +// or else just return the existing value. +// +// When setting value, if is type of , +// it will be executed with mutex.Lock of the hash map, +// and its return value will be set to the map with . +// +// It returns value with given . func (gm *IntInterfaceMap) doSetWithLockCheck(key int, value interface{}) interface{} { gm.mu.Lock() defer gm.mu.Unlock() @@ -115,7 +136,8 @@ func (gm *IntInterfaceMap) doSetWithLockCheck(key int, value interface{}) interf return value } -// 当键名存在时返回其键值,否则写入指定的键值 +// GetOrSet returns the value by key, +// or set value with given if not exist and returns this value. func (gm *IntInterfaceMap) GetOrSet(key int, value interface{}) interface{} { if v := gm.Get(key); v == nil { return gm.doSetWithLockCheck(key, value) @@ -124,7 +146,8 @@ func (gm *IntInterfaceMap) GetOrSet(key int, value interface{}) interface{} { } } -// 当键名存在时返回其键值,否则写入指定的键值,键值由指定的函数生成 +// GetOrSetFunc returns the value by key, +// or sets value with return value of callback function if not exist and returns this value. func (gm *IntInterfaceMap) GetOrSetFunc(key int, f func() interface{}) interface{} { if v := gm.Get(key); v == nil { return gm.doSetWithLockCheck(key, f()) @@ -133,7 +156,11 @@ func (gm *IntInterfaceMap) GetOrSetFunc(key int, f func() interface{}) interface } } -// 与GetOrSetFunc不同的是,f是在写锁机制内执行 +// GetOrSetFuncLock returns the value by key, +// or sets value with return value of callback function if not exist and returns this value. +// +// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function +// with mutex.Lock of the hash map. func (gm *IntInterfaceMap) GetOrSetFuncLock(key int, f func() interface{}) interface{} { if v := gm.Get(key); v == nil { return gm.doSetWithLockCheck(key, f) @@ -142,7 +169,8 @@ func (gm *IntInterfaceMap) GetOrSetFuncLock(key int, f func() interface{}) inter } } -// 当键名不存在时写入,并返回true;否则返回false。 +// SetIfNotExist sets to the map if the does not exist, then return true. +// It returns false if exists, and would be ignored. func (gm *IntInterfaceMap) SetIfNotExist(key int, value interface{}) bool { if !gm.Contains(key) { gm.doSetWithLockCheck(key, value) @@ -151,7 +179,31 @@ func (gm *IntInterfaceMap) SetIfNotExist(key int, value interface{}) bool { return false } -// 批量删除键值对 +// SetIfNotExistFunc sets value with return value of callback function , then return true. +// It returns false if exists, and would be ignored. +func (gm *IntInterfaceMap) SetIfNotExistFunc(key int, 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 , then return true. +// It returns false if exists, and would be ignored. +// +// SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that +// it executes function with mutex.Lock of the hash map. +func (gm *IntInterfaceMap) SetIfNotExistFuncLock(key int, 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 *IntInterfaceMap) BatchRemove(keys []int) { gm.mu.Lock() for _, key := range keys { @@ -160,7 +212,7 @@ func (gm *IntInterfaceMap) BatchRemove(keys []int) { gm.mu.Unlock() } -// 返回对应的键值,并删除该键值 +// Remove deletes value from map by given , and return this deleted value. func (gm *IntInterfaceMap) Remove(key int) interface{} { gm.mu.Lock() val, exists := gm.m[key] @@ -171,7 +223,7 @@ func (gm *IntInterfaceMap) Remove(key int) interface{} { return val } -// 返回键列表 +// Keys returns all keys of the map as a slice. func (gm *IntInterfaceMap) Keys() []int { gm.mu.RLock() keys := make([]int, 0) @@ -182,7 +234,7 @@ func (gm *IntInterfaceMap) Keys() []int { return keys } -// 返回值列表(注意是随机排序) +// Values returns all values of the map as a slice. func (gm *IntInterfaceMap) Values() []interface{} { gm.mu.RLock() vals := make([]interface{}, 0) @@ -193,7 +245,8 @@ func (gm *IntInterfaceMap) Values() []interface{} { return vals } -// 是否存在某个键 +// Contains checks whether a key exists. +// It returns true if the exists, or else false. func (gm *IntInterfaceMap) Contains(key int) bool { gm.mu.RLock() _, exists := gm.m[key] @@ -201,7 +254,7 @@ func (gm *IntInterfaceMap) Contains(key int) bool { return exists } -// 哈希表大小 +// Size returns the size of the map. func (gm *IntInterfaceMap) Size() int { gm.mu.RLock() length := len(gm.m) @@ -209,7 +262,8 @@ func (gm *IntInterfaceMap) Size() int { return length } -// 哈希表是否为空 +// IsEmpty checks whether the map is empty. +// It returns true if map is empty, or else false. func (gm *IntInterfaceMap) IsEmpty() bool { gm.mu.RLock() empty := len(gm.m) == 0 @@ -217,28 +271,28 @@ func (gm *IntInterfaceMap) IsEmpty() bool { return empty } -// 清空哈希表 +// Clear deletes all data of the map, it will remake a new underlying map data map. func (gm *IntInterfaceMap) Clear() { gm.mu.Lock() gm.m = make(map[int]interface{}) gm.mu.Unlock() } -// 并发安全锁操作,使用自定义方法执行加锁修改操作 +// LockFunc locks writing with given callback function and mutex.Lock. func (gm *IntInterfaceMap) LockFunc(f func(m map[int]interface{})) { gm.mu.Lock() defer gm.mu.Unlock() f(gm.m) } -// 并发安全锁操作,使用自定义方法执行加锁读取操作 +// RLockFunc locks reading with given callback function and mutex.RLock. func (gm *IntInterfaceMap) RLockFunc(f func(m map[int]interface{})) { gm.mu.RLock() defer gm.mu.RUnlock() f(gm.m) } -// 交换Map中的键和值. +// Flip exchanges key-value of the map, it will change key-value to value-key. func (gm *IntInterfaceMap) Flip() { gm.mu.Lock() defer gm.mu.Unlock() @@ -249,15 +303,16 @@ func (gm *IntInterfaceMap) Flip() { gm.m = n } -// 合并两个Map. -func (gm *IntInterfaceMap) Merge(m *IntInterfaceMap) { +// Merge merges two hash maps. +// The map will be merged into the map . +func (gm *IntInterfaceMap) Merge(other *IntInterfaceMap) { gm.mu.Lock() defer gm.mu.Unlock() - if m != gm { - m.mu.RLock() - defer m.mu.RUnlock() + if other != gm { + other.mu.RLock() + defer other.mu.RUnlock() } - for k, v := range m.m { + for k, v := range other.m { gm.m[k] = v } } \ No newline at end of file diff --git a/g/container/gmap/gmap_int_string_map.go b/g/container/gmap/gmap_int_string_map.go index 54c075a0f..b2bb701c7 100644 --- a/g/container/gmap/gmap_int_string_map.go +++ b/g/container/gmap/gmap_int_string_map.go @@ -17,6 +17,9 @@ type IntStringMap struct { m map[int]string } +// NewIntStringMap returns an empty IntStringMap object. +// The param used to specify whether using map with un-concurrent-safety, +// which is false in default, means concurrent-safe. func NewIntStringMap(unsafe...bool) *IntStringMap { return &IntStringMap{ m : make(map[int]string), @@ -24,6 +27,9 @@ func NewIntStringMap(unsafe...bool) *IntStringMap { } } +// NewIntStringMapFrom returns an IntStringMap object from given map . +// Notice that, the param map is a type of pointer, +// there might be some concurrent-safe issues when changing the map outside. func NewIntStringMapFrom(m map[int]string, unsafe...bool) *IntStringMap { return &IntStringMap{ m : m, @@ -31,6 +37,12 @@ func NewIntStringMapFrom(m map[int]string, unsafe...bool) *IntStringMap { } } +// NewIntStringMapFromArray returns an IntStringMap object from given array. +// The param given as the keys of the map, +// and as its corresponding values. +// +// If length of is greater than that of , +// the corresponding overflow map values will be the default value of its type. func NewIntStringMapFromArray(keys []int, values []string, unsafe...bool) *IntStringMap { m := make(map[int]string) l := len(values) @@ -47,7 +59,8 @@ func NewIntStringMapFromArray(keys []int, values []string, unsafe...bool) *IntSt } } -// 给定回调函数对原始内容进行遍历,回调函数返回true表示继续遍历,否则停止遍历 +// Iterator iterates the hash map with custom callback function . +// If f returns true, then continue iterating; or false to stop. func (gm *IntStringMap) Iterator(f func (k int, v string) bool) { gm.mu.RLock() defer gm.mu.RUnlock() @@ -58,12 +71,12 @@ func (gm *IntStringMap) Iterator(f func (k int, v string) bool) { } } -// 哈希表克隆. +// Clone returns a new hash map with copy of current map data. func (gm *IntStringMap) Clone() *IntStringMap { return NewIntStringMapFrom(gm.Map(), !gm.mu.IsSafe()) } -// 返回当前哈希表的数据Map. +// Map returns a copy of the data of the hash map. func (gm *IntStringMap) Map() map[int]string { m := make(map[int]string) gm.mu.RLock() @@ -74,14 +87,14 @@ func (gm *IntStringMap) Map() map[int]string { return m } -// 设置键值对 +// Set sets key-value to the hash map. func (gm *IntStringMap) Set(key int, val string) { gm.mu.Lock() gm.m[key] = val gm.mu.Unlock() } -// 批量设置键值对 +// BatchSet batch sets key-values to the hash map. func (gm *IntStringMap) BatchSet(m map[int]string) { gm.mu.Lock() for k, v := range m { @@ -90,7 +103,7 @@ func (gm *IntStringMap) BatchSet(m map[int]string) { gm.mu.Unlock() } -// 获取键值 +// Get returns the value by given . func (gm *IntStringMap) Get(key int) string { gm.mu.RLock() val, _ := gm.m[key] @@ -98,8 +111,11 @@ func (gm *IntStringMap) Get(key int) string { return val } -// 设置kv缓存键值对,内部会对键名的存在性使用写锁进行二次检索确认,如果存在则不再写入;返回键名对应的键值。 -// 在高并发下有用,防止数据写入的并发逻辑错误。 +// doSetWithLockCheck checks whether value of the key exists with mutex.Lock, +// if not exists, set value to the map with given , +// or else just return the existing value. +// +// It returns value with given . func (gm *IntStringMap) doSetWithLockCheck(key int, value string) string { gm.mu.Lock() if v, ok := gm.m[key]; ok { @@ -111,7 +127,8 @@ func (gm *IntStringMap) doSetWithLockCheck(key int, value string) string { return value } -// 当键名存在时返回其键值,否则写入指定的键值 +// GetOrSet returns the value by key, +// or set value with given if not exist and returns this value. func (gm *IntStringMap) GetOrSet(key int, value string) string { gm.mu.RLock() v, ok := gm.m[key] @@ -123,7 +140,8 @@ func (gm *IntStringMap) GetOrSet(key int, value string) string { } } -// 当键名存在时返回其键值,否则写入指定的键值,键值由指定的函数生成 +// GetOrSetFunc returns the value by key, +// or sets value with return value of callback function if not exist and returns this value. func (gm *IntStringMap) GetOrSetFunc(key int, f func() string) string { gm.mu.RLock() v, ok := gm.m[key] @@ -135,7 +153,11 @@ func (gm *IntStringMap) GetOrSetFunc(key int, f func() string) string { } } -// 与GetOrSetFunc不同的是,f是在写锁机制内执行 +// GetOrSetFuncLock returns the value by key, +// or sets value with return value of callback function if not exist and returns this value. +// +// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function +// with mutex.Lock of the hash map. func (gm *IntStringMap) GetOrSetFuncLock(key int, f func() string) string { gm.mu.RLock() val, ok := gm.m[key] @@ -144,10 +166,9 @@ func (gm *IntStringMap) GetOrSetFuncLock(key int, f func() string) string { gm.mu.Lock() defer gm.mu.Unlock() if v, ok := gm.m[key]; ok { - gm.mu.Unlock() return v } - val = f() + val = f() gm.m[key] = val return val } else { @@ -155,7 +176,8 @@ func (gm *IntStringMap) GetOrSetFuncLock(key int, f func() string) string { } } -// 当键名不存在时写入,并返回true;否则返回false。 +// SetIfNotExist sets to the map if the does not exist, then return true. +// It returns false if exists, and would be ignored. func (gm *IntStringMap) SetIfNotExist(key int, value string) bool { if !gm.Contains(key) { gm.doSetWithLockCheck(key, value) @@ -164,7 +186,35 @@ func (gm *IntStringMap) SetIfNotExist(key int, value string) bool { return false } -// 批量删除键值对 +// SetIfNotExistFunc sets value with return value of callback function , then return true. +// It returns false if exists, and would be ignored. +func (gm *IntStringMap) SetIfNotExistFunc(key int, f func() string) bool { + if !gm.Contains(key) { + gm.doSetWithLockCheck(key, f()) + return true + } + return false +} + +// SetIfNotExistFuncLock sets value with return value of callback function , then return true. +// It returns false if exists, and would be ignored. +// +// SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that +// it executes function with mutex.Lock of the hash map. +func (gm *IntStringMap) SetIfNotExistFuncLock(key int, f func() string) bool { + if !gm.Contains(key) { + gm.mu.Lock() + defer gm.mu.Unlock() + if _, ok := gm.m[key]; !ok { + gm.m[key] = f() + } + return true + } + return false +} + + +// BatchRemove batch deletes values of the map by keys. func (gm *IntStringMap) BatchRemove(keys []int) { gm.mu.Lock() for _, key := range keys { @@ -173,7 +223,7 @@ func (gm *IntStringMap) BatchRemove(keys []int) { gm.mu.Unlock() } -// 返回对应的键值,并删除该键值 +// Remove deletes value from map by given , and return this deleted value. func (gm *IntStringMap) Remove(key int) string { gm.mu.Lock() val, exists := gm.m[key] @@ -184,7 +234,7 @@ func (gm *IntStringMap) Remove(key int) string { return val } -// 返回键列表 +// Keys returns all keys of the map as a slice. func (gm *IntStringMap) Keys() []int { gm.mu.RLock() keys := make([]int, 0) @@ -195,7 +245,7 @@ func (gm *IntStringMap) Keys() []int { return keys } -// 返回值列表(注意是随机排序) +// Values returns all values of the map as a slice. func (gm *IntStringMap) Values() []string { gm.mu.RLock() vals := make([]string, 0) @@ -206,7 +256,8 @@ func (gm *IntStringMap) Values() []string { return vals } -// 是否存在某个键 +// Contains checks whether a key exists. +// It returns true if the exists, or else false. func (gm *IntStringMap) Contains(key int) bool { gm.mu.RLock() _, exists := gm.m[key] @@ -214,7 +265,7 @@ func (gm *IntStringMap) Contains(key int) bool { return exists } -// 哈希表大小 +// Size returns the size of the map. func (gm *IntStringMap) Size() int { gm.mu.RLock() length := len(gm.m) @@ -222,7 +273,8 @@ func (gm *IntStringMap) Size() int { return length } -// 哈希表是否为空 +// IsEmpty checks whether the map is empty. +// It returns true if map is empty, or else false. func (gm *IntStringMap) IsEmpty() bool { gm.mu.RLock() empty := len(gm.m) == 0 @@ -230,28 +282,28 @@ func (gm *IntStringMap) IsEmpty() bool { return empty } -// 清空哈希表 +// Clear deletes all data of the map, it will remake a new underlying map data map. func (gm *IntStringMap) Clear() { gm.mu.Lock() gm.m = make(map[int]string) gm.mu.Unlock() } -// 并发安全锁操作,使用自定义方法执行加锁修改操作 +// LockFunc locks writing with given callback function and mutex.Lock. func (gm *IntStringMap) LockFunc(f func(m map[int]string)) { gm.mu.Lock() defer gm.mu.Unlock() f(gm.m) } -// 并发安全锁操作,使用自定义方法执行加锁读取操作 +// RLockFunc locks reading with given callback function and mutex.RLock. func (gm *IntStringMap) RLockFunc(f func(m map[int]string)) { gm.mu.RLock() defer gm.mu.RUnlock() f(gm.m) } -// 交换Map中的键和值. +// Flip exchanges key-value of the map, it will change key-value to value-key. func (gm *IntStringMap) Flip() { gm.mu.Lock() defer gm.mu.Unlock() @@ -262,15 +314,16 @@ func (gm *IntStringMap) Flip() { gm.m = n } -// 合并两个Map. -func (gm *IntStringMap) Merge(m *IntStringMap) { +// Merge merges two hash maps. +// The map will be merged into the map . +func (gm *IntStringMap) Merge(other *IntStringMap) { gm.mu.Lock() defer gm.mu.Unlock() - if m != gm { - m.mu.RLock() - defer m.mu.RUnlock() + if other != gm { + other.mu.RLock() + defer other.mu.RUnlock() } - for k, v := range m.m { + for k, v := range other.m { gm.m[k] = v } } \ No newline at end of file diff --git a/g/container/gmap/gmap_string_bool_map.go b/g/container/gmap/gmap_string_bool_map.go index e1edfacd2..6c3e14d4f 100644 --- a/g/container/gmap/gmap_string_bool_map.go +++ b/g/container/gmap/gmap_string_bool_map.go @@ -16,6 +16,9 @@ type StringBoolMap struct { m map[string]bool } +// NewStringBoolMap returns an empty StringBoolMap object. +// The param used to specify whether using map with un-concurrent-safety, +// which is false in default, means concurrent-safe. func NewStringBoolMap(unsafe...bool) *StringBoolMap { return &StringBoolMap{ m : make(map[string]bool), @@ -23,6 +26,9 @@ func NewStringBoolMap(unsafe...bool) *StringBoolMap { } } +// NewStringBoolMapFrom returns an StringBoolMap object from given map . +// Notice that, the param map is a type of pointer, +// there might be some concurrent-safe issues when changing the map outside. func NewStringBoolMapFrom(m map[string]bool, unsafe...bool) *StringBoolMap { return &StringBoolMap{ m : m, @@ -30,6 +36,12 @@ func NewStringBoolMapFrom(m map[string]bool, unsafe...bool) *StringBoolMap { } } +// NewFromArray returns a hash map from given array. +// The param given as the keys of the map, +// and as its corresponding values. +// +// If length of is greater than that of , +// the corresponding overflow map values will be the default value of its type. func NewStringBoolMapFromArray(keys []string, values []bool, unsafe...bool) *StringBoolMap { m := make(map[string]bool) l := len(values) @@ -46,7 +58,8 @@ func NewStringBoolMapFromArray(keys []string, values []bool, unsafe...bool) *Str } } -// 给定回调函数对原始内容进行遍历,回调函数返回true表示继续遍历,否则停止遍历 +// Iterator iterates the hash map with custom callback function . +// If f returns true, then continue iterating; or false to stop. func (gm *StringBoolMap) Iterator(f func (k string, v bool) bool) { gm.mu.RLock() defer gm.mu.RUnlock() @@ -57,12 +70,12 @@ func (gm *StringBoolMap) Iterator(f func (k string, v bool) bool) { } } -// 哈希表克隆. +// Clone returns a new hash map with copy of current map data. func (gm *StringBoolMap) Clone() *StringBoolMap { return NewStringBoolMapFrom(gm.Map(), !gm.mu.IsSafe()) } -// 返回当前哈希表的数据Map. +// Map returns a copy of the data of the hash map. func (gm *StringBoolMap) Map() map[string]bool { m := make(map[string]bool) gm.mu.RLock() @@ -73,14 +86,14 @@ func (gm *StringBoolMap) Map() map[string]bool { return m } -// 设置键值对 +// Set sets key-value to the hash map. func (gm *StringBoolMap) Set(key string, val bool) { gm.mu.Lock() gm.m[key] = val gm.mu.Unlock() } -// 批量设置键值对 +// BatchSet batch sets key-values to the hash map. func (gm *StringBoolMap) BatchSet(m map[string]bool) { gm.mu.Lock() for k, v := range m { @@ -89,7 +102,7 @@ func (gm *StringBoolMap) BatchSet(m map[string]bool) { gm.mu.Unlock() } -// 获取键值 +// Get returns the value by given . func (gm *StringBoolMap) Get(key string) bool { gm.mu.RLock() val, _ := gm.m[key] @@ -97,8 +110,11 @@ func (gm *StringBoolMap) Get(key string) bool { return val } -// 设置kv缓存键值对,内部会对键名的存在性使用写锁进行二次检索确认,如果存在则不再写入;返回键名对应的键值。 -// 在高并发下有用,防止数据写入的并发逻辑错误。 +// doSetWithLockCheck checks whether value of the key exists with mutex.Lock, +// if not exists, set value to the map with given , +// or else just return the existing value. +// +// It returns value with given . func (gm *StringBoolMap) doSetWithLockCheck(key string, value bool) bool { gm.mu.Lock() if v, ok := gm.m[key]; ok { @@ -110,7 +126,8 @@ func (gm *StringBoolMap) doSetWithLockCheck(key string, value bool) bool { return value } -// 当键名存在时返回其键值,否则写入指定的键值 +// GetOrSet returns the value by key, +// or set value with given if not exist and returns this value. func (gm *StringBoolMap) GetOrSet(key string, value bool) bool { gm.mu.RLock() v, ok := gm.m[key] @@ -122,7 +139,9 @@ func (gm *StringBoolMap) GetOrSet(key string, value bool) bool { } } -// 当键名存在时返回其键值,否则写入指定的键值,键值由指定的函数生成 +// GetOrSetFunc returns the value by key, +// or sets value with return value of callback function if not exist +// and returns this value. func (gm *StringBoolMap) GetOrSetFunc(key string, f func() bool) bool { gm.mu.RLock() v, ok := gm.m[key] @@ -134,7 +153,12 @@ func (gm *StringBoolMap) GetOrSetFunc(key string, f func() bool) bool { } } -// 与GetOrSetFunc不同的是,f是在写锁机制内执行 +// GetOrSetFuncLock returns the value by key, +// or sets value with return value of callback function if not exist +// and returns this value. +// +// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function +// with mutex.Lock of the hash map. func (gm *StringBoolMap) GetOrSetFuncLock(key string, f func() bool) bool { gm.mu.RLock() val, ok := gm.m[key] @@ -143,7 +167,6 @@ func (gm *StringBoolMap) GetOrSetFuncLock(key string, f func() bool) bool { gm.mu.Lock() defer gm.mu.Unlock() if v, ok := gm.m[key]; ok { - gm.mu.Unlock() return v } val = f() @@ -154,7 +177,9 @@ func (gm *StringBoolMap) GetOrSetFuncLock(key string, f func() bool) bool { } } -// 当键名不存在时写入,并返回true;否则返回false。 + +// SetIfNotExist sets to the map if the does not exist, then return true. +// It returns false if exists, and would be ignored. func (gm *StringBoolMap) SetIfNotExist(key string, value bool) bool { if !gm.Contains(key) { gm.doSetWithLockCheck(key, value) @@ -163,7 +188,34 @@ func (gm *StringBoolMap) SetIfNotExist(key string, value bool) bool { return false } -// 批量删除键值对 +// SetIfNotExistFunc sets value with return value of callback function , then return true. +// It returns false if exists, and would be ignored. +func (gm *StringBoolMap) SetIfNotExistFunc(key string, f func() bool) bool { + if !gm.Contains(key) { + gm.doSetWithLockCheck(key, f()) + return true + } + return false +} + +// SetIfNotExistFuncLock sets value with return value of callback function , then return true. +// It returns false if exists, and would be ignored. +// +// SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that +// it executes function with mutex.Lock of the hash map. +func (gm *StringBoolMap) SetIfNotExistFuncLock(key string, f func() bool) bool { + if !gm.Contains(key) { + gm.mu.Lock() + defer gm.mu.Unlock() + if _, ok := gm.m[key]; !ok { + gm.m[key] = f() + } + return true + } + return false +} + +// BatchRemove batch deletes values of the map by keys. func (gm *StringBoolMap) BatchRemove(keys []string) { gm.mu.Lock() for _, key := range keys { @@ -172,7 +224,7 @@ func (gm *StringBoolMap) BatchRemove(keys []string) { gm.mu.Unlock() } -// 返回对应的键值,并删除该键值 +// Remove deletes value from map by given , and return this deleted value. func (gm *StringBoolMap) Remove(key string) bool { gm.mu.Lock() val, exists := gm.m[key] @@ -183,7 +235,7 @@ func (gm *StringBoolMap) Remove(key string) bool { return val } -// 返回键列表 +// Keys returns all keys of the map as a slice. func (gm *StringBoolMap) Keys() []string { gm.mu.RLock() keys := make([]string, 0) @@ -194,18 +246,8 @@ func (gm *StringBoolMap) Keys() []string { return keys } -// 返回值列表(注意是随机排序) -//func (gm *StringBoolMap) Values() []bool { -// gm.mu.RLock() -// vals := make([]bool, 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 exists, or else false. func (gm *StringBoolMap) Contains(key string) bool { gm.mu.RLock() _, exists := gm.m[key] @@ -213,7 +255,7 @@ func (gm *StringBoolMap) Contains(key string) bool { return exists } -// 哈希表大小 +// Size returns the size of the map. func (gm *StringBoolMap) Size() int { gm.mu.RLock() length := len(gm.m) @@ -221,7 +263,8 @@ func (gm *StringBoolMap) Size() int { return length } -// 哈希表是否为空 +// IsEmpty checks whether the map is empty. +// It returns true if map is empty, or else false. func (gm *StringBoolMap) IsEmpty() bool { gm.mu.RLock() empty := len(gm.m) == 0 @@ -229,36 +272,37 @@ func (gm *StringBoolMap) IsEmpty() bool { return empty } -// 清空哈希表 +// Clear deletes all data of the map, it will remake a new underlying map data map. func (gm *StringBoolMap) Clear() { gm.mu.Lock() gm.m = make(map[string]bool) gm.mu.Unlock() } -// 并发安全锁操作,使用自定义方法执行加锁修改操作 +// LockFunc locks writing with given callback function and mutex.Lock. func (gm *StringBoolMap) LockFunc(f func(m map[string]bool)) { gm.mu.Lock() defer gm.mu.Unlock() f(gm.m) } -// 并发安全锁操作,使用自定义方法执行加锁读取操作 +// RLockFunc locks reading with given callback function and mutex.RLock. func (gm *StringBoolMap) RLockFunc(f func(m map[string]bool)) { gm.mu.RLock() defer gm.mu.RUnlock() f(gm.m) } -// 合并两个Map. -func (gm *StringBoolMap) Merge(m *StringBoolMap) { +// Merge merges two hash maps. +// The map will be merged into the map . +func (gm *StringBoolMap) Merge(other *StringBoolMap) { gm.mu.Lock() defer gm.mu.Unlock() - if m != gm { - m.mu.RLock() - defer m.mu.RUnlock() + if other != gm { + other.mu.RLock() + defer other.mu.RUnlock() } - for k, v := range m.m { + for k, v := range other.m { gm.m[k] = v } } \ No newline at end of file diff --git a/g/container/gmap/gmap_string_int_map.go b/g/container/gmap/gmap_string_int_map.go index 63a16806d..052d956e3 100644 --- a/g/container/gmap/gmap_string_int_map.go +++ b/g/container/gmap/gmap_string_int_map.go @@ -17,6 +17,9 @@ type StringIntMap struct { m map[string]int } +// NewStringIntMap returns an empty StringIntMap object. +// The param used to specify whether using map with un-concurrent-safety, +// which is false in default, means concurrent-safe. func NewStringIntMap(unsafe...bool) *StringIntMap { return &StringIntMap{ m : make(map[string]int), @@ -24,6 +27,9 @@ func NewStringIntMap(unsafe...bool) *StringIntMap { } } +// NewStringIntMapFrom returns an StringIntMap object from given map . +// Notice that, the param map is a type of pointer, +// there might be some concurrent-safe issues when changing the map outside. func NewStringIntMapFrom(m map[string]int, unsafe...bool) *StringIntMap { return &StringIntMap{ m : m, @@ -31,6 +37,12 @@ func NewStringIntMapFrom(m map[string]int, unsafe...bool) *StringIntMap { } } +// NewStringIntMapFromArray returns an StringIntMap object from given array. +// The param given as the keys of the map, +// and as its corresponding values. +// +// If length of is greater than that of , +// the corresponding overflow map values will be the default value of its type. func NewStringIntMapFromArray(keys []string, values []int, unsafe...bool) *StringIntMap { m := make(map[string]int) l := len(values) @@ -47,7 +59,8 @@ func NewStringIntMapFromArray(keys []string, values []int, unsafe...bool) *Strin } } -// 给定回调函数对原始内容进行遍历,回调函数返回true表示继续遍历,否则停止遍历 +// Iterator iterates the hash map with custom callback function . +// If f returns true, then continue iterating; or false to stop. func (gm *StringIntMap) Iterator(f func (k string, v int) bool) { gm.mu.RLock() defer gm.mu.RUnlock() @@ -58,12 +71,12 @@ func (gm *StringIntMap) Iterator(f func (k string, v int) bool) { } } -// 哈希表克隆. +// Clone returns a new hash map with copy of current map data. func (gm *StringIntMap) Clone() *StringIntMap { return NewStringIntMapFrom(gm.Map(), !gm.mu.IsSafe()) } -// 返回当前哈希表的数据Map. +// Map returns a copy of the data of the hash map. func (gm *StringIntMap) Map() map[string]int { m := make(map[string]int) gm.mu.RLock() @@ -74,14 +87,14 @@ func (gm *StringIntMap) Map() map[string]int { return m } -// 设置键值对 +// Set sets key-value to the hash map. func (gm *StringIntMap) Set(key string, val int) { gm.mu.Lock() gm.m[key] = val gm.mu.Unlock() } -// 批量设置键值对 +// BatchSet batch sets key-values to the hash map. func (gm *StringIntMap) BatchSet(m map[string]int) { gm.mu.Lock() for k, v := range m { @@ -90,7 +103,7 @@ func (gm *StringIntMap) BatchSet(m map[string]int) { gm.mu.Unlock() } -// 获取键值 +// Get returns the value by given . func (gm *StringIntMap) Get(key string) int { gm.mu.RLock() val, _ := gm.m[key] @@ -98,8 +111,11 @@ func (gm *StringIntMap) Get(key string) int { return val } -// 设置kv缓存键值对,内部会对键名的存在性使用写锁进行二次检索确认,如果存在则不再写入;返回键名对应的键值。 -// 在高并发下有用,防止数据写入的并发逻辑错误。 +// doSetWithLockCheck checks whether value of the key exists with mutex.Lock, +// if not exists, set value to the map with given , +// or else just return the existing value. +// +// It returns value with given . func (gm *StringIntMap) doSetWithLockCheck(key string, value int) int { gm.mu.Lock() if v, ok := gm.m[key]; ok { @@ -111,7 +127,8 @@ func (gm *StringIntMap) doSetWithLockCheck(key string, value int) int { return value } -// 当键名存在时返回其键值,否则写入指定的键值 +// GetOrSet returns the value by key, +// or set value with given if not exist and returns this value. func (gm *StringIntMap) GetOrSet(key string, value int) int { gm.mu.RLock() v, ok := gm.m[key] @@ -123,7 +140,9 @@ func (gm *StringIntMap) GetOrSet(key string, value int) int { } } -// 当键名存在时返回其键值,否则写入指定的键值,键值由指定的函数生成 +// GetOrSetFunc returns the value by key, +// or sets value with return value of callback function if not exist +// and returns this value. func (gm *StringIntMap) GetOrSetFunc(key string, f func() int) int { gm.mu.RLock() v, ok := gm.m[key] @@ -135,7 +154,12 @@ func (gm *StringIntMap) GetOrSetFunc(key string, f func() int) int { } } -// 与GetOrSetFunc不同的是,f是在写锁机制内执行 +// GetOrSetFuncLock returns the value by key, +// or sets value with return value of callback function if not exist +// and returns this value. +// +// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function +// with mutex.Lock of the hash map. func (gm *StringIntMap) GetOrSetFuncLock(key string, f func() int) int { gm.mu.RLock() val, ok := gm.m[key] @@ -144,10 +168,9 @@ func (gm *StringIntMap) GetOrSetFuncLock(key string, f func() int) int { gm.mu.Lock() defer gm.mu.Unlock() if v, ok := gm.m[key]; ok { - gm.mu.Unlock() return v } - val = f() + val = f() gm.m[key] = val return val } else { @@ -155,7 +178,8 @@ func (gm *StringIntMap) GetOrSetFuncLock(key string, f func() int) int { } } -// 当键名不存在时写入,并返回true;否则返回false。 +// SetIfNotExist sets to the map if the does not exist, then return true. +// It returns false if exists, and would be ignored. func (gm *StringIntMap) SetIfNotExist(key string, value int) bool { if !gm.Contains(key) { gm.doSetWithLockCheck(key, value) @@ -164,7 +188,34 @@ func (gm *StringIntMap) SetIfNotExist(key string, value int) bool { return false } -// 批量删除键值对 +// SetIfNotExistFunc sets value with return value of callback function , then return true. +// It returns false if exists, and would be ignored. +func (gm *StringIntMap) SetIfNotExistFunc(key string, f func() int) bool { + if !gm.Contains(key) { + gm.doSetWithLockCheck(key, f()) + return true + } + return false +} + +// SetIfNotExistFuncLock sets value with return value of callback function , then return true. +// It returns false if exists, and would be ignored. +// +// SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that +// it executes function with mutex.Lock of the hash map. +func (gm *StringIntMap) SetIfNotExistFuncLock(key string, f func() int) bool { + if !gm.Contains(key) { + gm.mu.Lock() + defer gm.mu.Unlock() + if _, ok := gm.m[key]; !ok { + gm.m[key] = f() + } + return true + } + return false +} + +// BatchRemove batch deletes values of the map by keys. func (gm *StringIntMap) BatchRemove(keys []string) { gm.mu.Lock() for _, key := range keys { @@ -173,7 +224,7 @@ func (gm *StringIntMap) BatchRemove(keys []string) { gm.mu.Unlock() } -// 返回对应的键值,并删除该键值 +// Remove deletes value from map by given , and return this deleted value. func (gm *StringIntMap) Remove(key string) int { gm.mu.Lock() val, exists := gm.m[key] @@ -184,7 +235,7 @@ func (gm *StringIntMap) Remove(key string) int { return val } -// 返回键列表 +// Keys returns all keys of the map as a slice. func (gm *StringIntMap) Keys() []string { gm.mu.RLock() keys := make([]string, 0) @@ -195,7 +246,7 @@ func (gm *StringIntMap) Keys() []string { return keys } -// 返回值列表(注意是随机排序) +// Values returns all values of the map as a slice. func (gm *StringIntMap) Values() []int { gm.mu.RLock() vals := make([]int, 0) @@ -206,7 +257,8 @@ func (gm *StringIntMap) Values() []int { return vals } -// 是否存在某个键 +// Contains checks whether a key exists. +// It returns true if the exists, or else false. func (gm *StringIntMap) Contains(key string) bool { gm.mu.RLock() _, exists := gm.m[key] @@ -214,7 +266,7 @@ func (gm *StringIntMap) Contains(key string) bool { return exists } -// 哈希表大小 +// Size returns the size of the map. func (gm *StringIntMap) Size() int { gm.mu.RLock() length := len(gm.m) @@ -222,7 +274,8 @@ func (gm *StringIntMap) Size() int { return length } -// 哈希表是否为空 +// IsEmpty checks whether the map is empty. +// It returns true if map is empty, or else false. func (gm *StringIntMap) IsEmpty() bool { gm.mu.RLock() empty := len(gm.m) == 0 @@ -230,28 +283,28 @@ func (gm *StringIntMap) IsEmpty() bool { return empty } -// 清空哈希表 +// Clear deletes all data of the map, it will remake a new underlying map data map. func (gm *StringIntMap) Clear() { gm.mu.Lock() gm.m = make(map[string]int) gm.mu.Unlock() } -// 并发安全写锁操作,使用自定义方法执行加锁修改操作 +// LockFunc locks writing with given callback function and mutex.Lock. func (gm *StringIntMap) LockFunc(f func(m map[string]int)) { gm.mu.Lock() defer gm.mu.Unlock() f(gm.m) } -// 并发安全读锁操作,使用自定义方法执行加锁读取操作 +// RLockFunc locks reading with given callback function and mutex.RLock. func (gm *StringIntMap) RLockFunc(f func(m map[string]int)) { gm.mu.RLock() defer gm.mu.RUnlock() f(gm.m) } -// 交换Map中的键和值. +// Flip exchanges key-value of the map, it will change key-value to value-key. func (gm *StringIntMap) Flip() { gm.mu.Lock() defer gm.mu.Unlock() @@ -262,15 +315,16 @@ func (gm *StringIntMap) Flip() { gm.m = n } -// 合并两个Map. -func (gm *StringIntMap) Merge(m *StringIntMap) { +// Merge merges two hash maps. +// The map will be merged into the map . +func (gm *StringIntMap) Merge(other *StringIntMap) { gm.mu.Lock() defer gm.mu.Unlock() - if m != gm { - m.mu.RLock() - defer m.mu.RUnlock() + if other != gm { + other.mu.RLock() + defer other.mu.RUnlock() } - for k, v := range m.m { + for k, v := range other.m { gm.m[k] = v } } \ No newline at end of file diff --git a/g/container/gmap/gmap_string_interface_map.go b/g/container/gmap/gmap_string_interface_map.go index b2809fec2..3fab490e9 100644 --- a/g/container/gmap/gmap_string_interface_map.go +++ b/g/container/gmap/gmap_string_interface_map.go @@ -17,6 +17,9 @@ type StringInterfaceMap struct { m map[string]interface{} } +// NewStringInterfaceMap returns an empty StringInterfaceMap object. +// The param used to specify whether using map with un-concurrent-safety, +// which is false in default, means concurrent-safe. func NewStringInterfaceMap(unsafe...bool) *StringInterfaceMap { return &StringInterfaceMap{ m : make(map[string]interface{}), @@ -24,6 +27,9 @@ func NewStringInterfaceMap(unsafe...bool) *StringInterfaceMap { } } +// NewStringInterfaceMapFrom returns an StringInterfaceMap object from given map . +// Notice that, the param map is a type of pointer, +// there might be some concurrent-safe issues when changing the map outside. func NewStringInterfaceMapFrom(m map[string]interface{}, unsafe...bool) *StringInterfaceMap { return &StringInterfaceMap{ m : m, @@ -31,6 +37,12 @@ func NewStringInterfaceMapFrom(m map[string]interface{}, unsafe...bool) *StringI } } +// NewStringInterfaceMapFromArray returns an StringInterfaceMap object from given array. +// The param given as the keys of the map, +// and as its corresponding values. +// +// If length of is greater than that of , +// the corresponding overflow map values will be the default value of its type. func NewStringInterfaceMapFromArray(keys []string, values []interface{}, unsafe...bool) *StringInterfaceMap { m := make(map[string]interface{}) l := len(values) @@ -47,7 +59,8 @@ func NewStringInterfaceMapFromArray(keys []string, values []interface{}, unsafe. } } -// 给定回调函数对原始内容进行遍历,回调函数返回true表示继续遍历,否则停止遍历 +// Iterator iterates the hash map with custom callback function . +// If f returns true, then continue iterating; or false to stop. func (gm *StringInterfaceMap) Iterator(f func (k string, v interface{}) bool) { gm.mu.RLock() defer gm.mu.RUnlock() @@ -58,12 +71,12 @@ func (gm *StringInterfaceMap) Iterator(f func (k string, v interface{}) bool) { } } -// 哈希表克隆. +// Clone returns a new hash map with copy of current map data. func (gm *StringInterfaceMap) Clone() *StringInterfaceMap { return NewStringInterfaceMapFrom(gm.Map(), !gm.mu.IsSafe()) } -// 返回当前哈希表的数据Map. +// Map returns a copy of the data of the hash map. func (gm *StringInterfaceMap) Map() map[string]interface{} { m := make(map[string]interface{}) gm.mu.RLock() @@ -74,14 +87,14 @@ func (gm *StringInterfaceMap) Map() map[string]interface{} { return m } -// 设置键值对 +// Set sets key-value to the hash map. func (gm *StringInterfaceMap) Set(key string, val interface{}) { gm.mu.Lock() gm.m[key] = val gm.mu.Unlock() } -// 批量设置键值对 +// BatchSet batch sets key-values to the hash map. func (gm *StringInterfaceMap) BatchSet(m map[string]interface{}) { gm.mu.Lock() for k, v := range m { @@ -90,7 +103,7 @@ func (gm *StringInterfaceMap) BatchSet(m map[string]interface{}) { gm.mu.Unlock() } -// 获取键值 +// Get returns the value by given . func (gm *StringInterfaceMap) Get(key string) interface{} { gm.mu.RLock() val, _ := gm.m[key] @@ -98,8 +111,15 @@ func (gm *StringInterfaceMap) Get(key string) interface{} { return val } -// 设置kv缓存键值对,内部会对键名的存在性使用写锁进行二次检索确认,如果存在则不再写入;返回键名对应的键值。 -// 在高并发下有用,防止数据写入的并发逻辑错误。 +// doSetWithLockCheck checks whether value of the key exists with mutex.Lock, +// if not exists, set value to the map with given , +// or else just return the existing value. +// +// When setting value, if is type of , +// it will be executed with mutex.Lock of the hash map, +// and its return value will be set to the map with . +// +// It returns value with given . func (gm *StringInterfaceMap) doSetWithLockCheck(key string, value interface{}) interface{} { gm.mu.Lock() defer gm.mu.Unlock() @@ -115,7 +135,8 @@ func (gm *StringInterfaceMap) doSetWithLockCheck(key string, value interface{}) return value } -// 当键名存在时返回其键值,否则写入指定的键值 +// GetOrSet returns the value by key, +// or set value with given if not exist and returns this value. func (gm *StringInterfaceMap) GetOrSet(key string, value interface{}) interface{} { if v := gm.Get(key); v == nil { return gm.doSetWithLockCheck(key, value) @@ -124,7 +145,9 @@ func (gm *StringInterfaceMap) GetOrSet(key string, value interface{}) interface{ } } -// 当键名存在时返回其键值,否则写入指定的键值,键值由指定的函数生成 +// GetOrSetFunc returns the value by key, +// or sets value with return value of callback function if not exist +// and returns this value. func (gm *StringInterfaceMap) GetOrSetFunc(key string, f func() interface{}) interface{} { if v := gm.Get(key); v == nil { return gm.doSetWithLockCheck(key, f()) @@ -133,7 +156,12 @@ func (gm *StringInterfaceMap) GetOrSetFunc(key string, f func() interface{}) int } } -// 与GetOrSetFunc不同的是,f是在写锁机制内执行 +// GetOrSetFuncLock returns the value by key, +// or sets value with return value of callback function if not exist +// and returns this value. +// +// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function +// with mutex.Lock of the hash map. func (gm *StringInterfaceMap) GetOrSetFuncLock(key string, f func() interface{}) interface{} { if v := gm.Get(key); v == nil { return gm.doSetWithLockCheck(key, f) @@ -142,7 +170,8 @@ func (gm *StringInterfaceMap) GetOrSetFuncLock(key string, f func() interface{}) } } -// 当键名不存在时写入,并返回true;否则返回false。 +// SetIfNotExist sets to the map if the does not exist, then return true. +// It returns false if exists, and would be ignored. func (gm *StringInterfaceMap) SetIfNotExist(key string, value interface{}) bool { if !gm.Contains(key) { gm.doSetWithLockCheck(key, value) @@ -151,7 +180,30 @@ func (gm *StringInterfaceMap) SetIfNotExist(key string, value interface{}) bool return false } -// 批量删除键值对 +// SetIfNotExistFunc sets value with return value of callback function , then return true. +// It returns false if exists, and would be ignored. +func (gm *StringInterfaceMap) SetIfNotExistFunc(key string, 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 , then return true. +// It returns false if exists, and would be ignored. +// +// SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that +// it executes function with mutex.Lock of the hash map. +func (gm *StringInterfaceMap) SetIfNotExistFuncLock(key string, 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 *StringInterfaceMap) BatchRemove(keys []string) { gm.mu.Lock() for _, key := range keys { @@ -160,7 +212,7 @@ func (gm *StringInterfaceMap) BatchRemove(keys []string) { gm.mu.Unlock() } -// 返回对应的键值,并删除该键值 +// Remove deletes value from map by given , and return this deleted value. func (gm *StringInterfaceMap) Remove(key string) interface{} { gm.mu.Lock() val, exists := gm.m[key] @@ -171,7 +223,7 @@ func (gm *StringInterfaceMap) Remove(key string) interface{} { return val } -// 返回键列表 +// Keys returns all keys of the map as a slice. func (gm *StringInterfaceMap) Keys() []string { gm.mu.RLock() keys := make([]string, 0) @@ -182,7 +234,7 @@ func (gm *StringInterfaceMap) Keys() []string { return keys } -// 返回值列表(注意是随机排序) +// Values returns all values of the map as a slice. func (gm *StringInterfaceMap) Values() []interface{} { gm.mu.RLock() vals := make([]interface{}, 0) @@ -193,7 +245,8 @@ func (gm *StringInterfaceMap) Values() []interface{} { return vals } -// 是否存在某个键 +// Contains checks whether a key exists. +// It returns true if the exists, or else false. func (gm *StringInterfaceMap) Contains(key string) bool { gm.mu.RLock() _, exists := gm.m[key] @@ -201,7 +254,7 @@ func (gm *StringInterfaceMap) Contains(key string) bool { return exists } -// 哈希表大小 +// Size returns the size of the map. func (gm *StringInterfaceMap) Size() int { gm.mu.RLock() length := len(gm.m) @@ -209,7 +262,8 @@ func (gm *StringInterfaceMap) Size() int { return length } -// 哈希表是否为空 +// IsEmpty checks whether the map is empty. +// It returns true if map is empty, or else false. func (gm *StringInterfaceMap) IsEmpty() bool { gm.mu.RLock() empty := len(gm.m) == 0 @@ -217,28 +271,28 @@ func (gm *StringInterfaceMap) IsEmpty() bool { return empty } -// 清空哈希表 +// Clear deletes all data of the map, it will remake a new underlying map data map. func (gm *StringInterfaceMap) Clear() { gm.mu.Lock() gm.m = make(map[string]interface{}) gm.mu.Unlock() } -// 并发安全写锁操作,使用自定义方法执行加锁修改操作 +// LockFunc locks writing with given callback function and mutex.Lock. func (gm *StringInterfaceMap) LockFunc(f func(m map[string]interface{})) { gm.mu.Lock() defer gm.mu.Unlock() f(gm.m) } -// 并发安全读锁操作,使用自定义方法执行加锁读取操作 +// RLockFunc locks reading with given callback function and mutex.RLock. func (gm *StringInterfaceMap) RLockFunc(f func(m map[string]interface{})) { gm.mu.RLock() defer gm.mu.RUnlock() f(gm.m) } -// 交换Map中的键和值. +// Flip exchanges key-value of the map, it will change key-value to value-key. func (gm *StringInterfaceMap) Flip() { gm.mu.Lock() defer gm.mu.Unlock() @@ -249,15 +303,16 @@ func (gm *StringInterfaceMap) Flip() { gm.m = n } -// 合并两个Map. -func (gm *StringInterfaceMap) Merge(m *StringInterfaceMap) { +// Merge merges two hash maps. +// The map will be merged into the map . +func (gm *StringInterfaceMap) Merge(other *StringInterfaceMap) { gm.mu.Lock() defer gm.mu.Unlock() - if m != gm { - m.mu.RLock() - defer m.mu.RUnlock() + if other != gm { + other.mu.RLock() + defer other.mu.RUnlock() } - for k, v := range m.m { + for k, v := range other.m { gm.m[k] = v } } \ No newline at end of file diff --git a/g/container/gmap/gmap_string_string_map.go b/g/container/gmap/gmap_string_string_map.go index 5c61e742a..8eb906853 100644 --- a/g/container/gmap/gmap_string_string_map.go +++ b/g/container/gmap/gmap_string_string_map.go @@ -16,6 +16,9 @@ type StringStringMap struct { m map[string]string } +// NewStringStringMap returns an empty StringStringMap object. +// The param used to specify whether using map with un-concurrent-safety, +// which is false in default, means concurrent-safe. func NewStringStringMap(unsafe...bool) *StringStringMap { return &StringStringMap{ m : make(map[string]string), @@ -23,6 +26,9 @@ func NewStringStringMap(unsafe...bool) *StringStringMap { } } +// NewStringStringMapFrom returns an StringStringMap object from given map . +// Notice that, the param map is a type of pointer, +// there might be some concurrent-safe issues when changing the map outside. func NewStringStringMapFrom(m map[string]string, unsafe...bool) *StringStringMap { return &StringStringMap{ m : m, @@ -30,6 +36,12 @@ func NewStringStringMapFrom(m map[string]string, unsafe...bool) *StringStringMap } } +// NewStringStringMapFromArray returns an StringStringMap object from given array. +// The param given as the keys of the map, +// and as its corresponding values. +// +// If length of is greater than that of , +// the corresponding overflow map values will be the default value of its type. func NewStringStringMapFromArray(keys []string, values []string, unsafe...bool) *StringStringMap { m := make(map[string]string) l := len(values) @@ -46,7 +58,8 @@ func NewStringStringMapFromArray(keys []string, values []string, unsafe...bool) } } -// 给定回调函数对原始内容进行遍历,回调函数返回true表示继续遍历,否则停止遍历 +// Iterator iterates the hash map with custom callback function . +// If f returns true, then continue iterating; or false to stop. func (gm *StringStringMap) Iterator(f func (k string, v string) bool) { gm.mu.RLock() defer gm.mu.RUnlock() @@ -57,12 +70,12 @@ func (gm *StringStringMap) Iterator(f func (k string, v string) bool) { } } -// 哈希表克隆. +// Clone returns a new hash map with copy of current map data. func (gm *StringStringMap) Clone() *StringStringMap { return NewStringStringMapFrom(gm.Map(), !gm.mu.IsSafe()) } -// 返回当前哈希表的数据Map. +// Map returns a copy of the data of the hash map. func (gm *StringStringMap) Map() map[string]string { m := make(map[string]string) gm.mu.RLock() @@ -73,14 +86,14 @@ func (gm *StringStringMap) Map() map[string]string { return m } -// 设置键值对 +// Set sets key-value to the hash map. func (gm *StringStringMap) Set(key string, val string) { gm.mu.Lock() gm.m[key] = val gm.mu.Unlock() } -// 批量设置键值对 +// BatchSet batch sets key-values to the hash map. func (gm *StringStringMap) BatchSet(m map[string]string) { gm.mu.Lock() for k, v := range m { @@ -89,7 +102,7 @@ func (gm *StringStringMap) BatchSet(m map[string]string) { gm.mu.Unlock() } -// 获取键值 +// Get returns the value by given . func (gm *StringStringMap) Get(key string) string { gm.mu.RLock() val, _ := gm.m[key] @@ -97,8 +110,11 @@ func (gm *StringStringMap) Get(key string) string { return val } -// 设置kv缓存键值对,内部会对键名的存在性使用写锁进行二次检索确认,如果存在则不再写入;返回键名对应的键值。 -// 在高并发下有用,防止数据写入的并发逻辑错误。 +// doSetWithLockCheck checks whether value of the key exists with mutex.Lock, +// if not exists, set value to the map with given , +// or else just return the existing value. +// +// It returns value with given . func (gm *StringStringMap) doSetWithLockCheck(key string, value string) string { gm.mu.Lock() if v, ok := gm.m[key]; ok { @@ -110,7 +126,8 @@ func (gm *StringStringMap) doSetWithLockCheck(key string, value string) string { return value } -// 当键名存在时返回其键值,否则写入指定的键值 +// GetOrSet returns the value by key, +// or set value with given if not exist and returns this value. func (gm *StringStringMap) GetOrSet(key string, value string) string { gm.mu.RLock() v, ok := gm.m[key] @@ -122,7 +139,9 @@ func (gm *StringStringMap) GetOrSet(key string, value string) string { } } -// 当键名存在时返回其键值,否则写入指定的键值,键值由指定的函数生成 +// GetOrSetFunc returns the value by key, +// or sets value with return value of callback function if not exist +// and returns this value. func (gm *StringStringMap) GetOrSetFunc(key string, f func() string) string { gm.mu.RLock() v, ok := gm.m[key] @@ -134,7 +153,12 @@ func (gm *StringStringMap) GetOrSetFunc(key string, f func() string) string { } } -// 与GetOrSetFunc不同的是,f是在写锁机制内执行 +// GetOrSetFuncLock returns the value by key, +// or sets value with return value of callback function if not exist +// and returns this value. +// +// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function +// with mutex.Lock of the hash map. func (gm *StringStringMap) GetOrSetFuncLock(key string, f func() string) string { gm.mu.RLock() val, ok := gm.m[key] @@ -143,10 +167,9 @@ func (gm *StringStringMap) GetOrSetFuncLock(key string, f func() string) string gm.mu.Lock() defer gm.mu.Unlock() if v, ok := gm.m[key]; ok { - gm.mu.Unlock() return v } - val = f() + val = f() gm.m[key] = val return val } else { @@ -154,7 +177,8 @@ func (gm *StringStringMap) GetOrSetFuncLock(key string, f func() string) string } } -// 当键名不存在时写入,并返回true;否则返回false。 +// SetIfNotExist sets to the map if the does not exist, then return true. +// It returns false if exists, and would be ignored. func (gm *StringStringMap) SetIfNotExist(key string, value string) bool { if !gm.Contains(key) { gm.doSetWithLockCheck(key, value) @@ -163,7 +187,34 @@ func (gm *StringStringMap) SetIfNotExist(key string, value string) bool { return false } -// 批量删除键值对 +// SetIfNotExistFunc sets value with return value of callback function , then return true. +// It returns false if exists, and would be ignored. +func (gm *StringStringMap) SetIfNotExistFunc(key string, f func() string) bool { + if !gm.Contains(key) { + gm.doSetWithLockCheck(key, f()) + return true + } + return false +} + +// SetIfNotExistFuncLock sets value with return value of callback function , then return true. +// It returns false if exists, and would be ignored. +// +// SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that +// it executes function with mutex.Lock of the hash map. +func (gm *StringStringMap) SetIfNotExistFuncLock(key string, f func() string) bool { + if !gm.Contains(key) { + gm.mu.Lock() + defer gm.mu.Unlock() + if _, ok := gm.m[key]; !ok { + gm.m[key] = f() + } + return true + } + return false +} + +// BatchRemove batch deletes values of the map by keys. func (gm *StringStringMap) BatchRemove(keys []string) { gm.mu.Lock() for _, key := range keys { @@ -172,7 +223,7 @@ func (gm *StringStringMap) BatchRemove(keys []string) { gm.mu.Unlock() } -// 返回对应的键值,并删除该键值 +// Remove deletes value from map by given , and return this deleted value. func (gm *StringStringMap) Remove(key string) string { gm.mu.Lock() val, exists := gm.m[key] @@ -183,7 +234,7 @@ func (gm *StringStringMap) Remove(key string) string { return val } -// 返回键列表 +// Keys returns all keys of the map as a slice. func (gm *StringStringMap) Keys() []string { gm.mu.RLock() keys := make([]string, 0) @@ -194,7 +245,7 @@ func (gm *StringStringMap) Keys() []string { return keys } -// 返回值列表(注意是随机排序) +// Values returns all values of the map as a slice. func (gm *StringStringMap) Values() []string { gm.mu.RLock() vals := make([]string, 0) @@ -205,7 +256,8 @@ func (gm *StringStringMap) Values() []string { return vals } -// 是否存在某个键 +// Contains checks whether a key exists. +// It returns true if the exists, or else false. func (gm *StringStringMap) Contains(key string) bool { gm.mu.RLock() _, exists := gm.m[key] @@ -213,7 +265,7 @@ func (gm *StringStringMap) Contains(key string) bool { return exists } -// 哈希表大小 +// Size returns the size of the map. func (gm *StringStringMap) Size() int { gm.mu.RLock() length := len(gm.m) @@ -221,7 +273,8 @@ func (gm *StringStringMap) Size() int { return length } -// 哈希表是否为空 +// IsEmpty checks whether the map is empty. +// It returns true if map is empty, or else false. func (gm *StringStringMap) IsEmpty() bool { gm.mu.RLock() empty := len(gm.m) == 0 @@ -229,28 +282,28 @@ func (gm *StringStringMap) IsEmpty() bool { return empty } -// 清空哈希表 +// Clear deletes all data of the map, it will remake a new underlying map data map. func (gm *StringStringMap) Clear() { gm.mu.Lock() gm.m = make(map[string]string) gm.mu.Unlock() } -// 并发安全写锁操作,使用自定义方法执行加锁修改操作 +// LockFunc locks writing with given callback function and mutex.Lock. func (gm *StringStringMap) LockFunc(f func(m map[string]string)) { gm.mu.Lock() defer gm.mu.Unlock() f(gm.m) } -// 并发安全读锁操作,使用自定义方法执行加锁读取操作 +// RLockFunc locks reading with given callback function and mutex.RLock. func (gm *StringStringMap) RLockFunc(f func(m map[string]string)) { gm.mu.RLock() defer gm.mu.RUnlock() f(gm.m) } -// 交换Map中的键和值. +// Flip exchanges key-value of the map, it will change key-value to value-key. func (gm *StringStringMap) Flip() { gm.mu.Lock() defer gm.mu.Unlock() @@ -261,15 +314,16 @@ func (gm *StringStringMap) Flip() { gm.m = n } -// 合并两个Map. -func (gm *StringStringMap) Merge(m *StringStringMap) { +// Merge merges two hash maps. +// The map will be merged into the map . +func (gm *StringStringMap) Merge(other *StringStringMap) { gm.mu.Lock() defer gm.mu.Unlock() - if m != gm { - m.mu.RLock() - defer m.mu.RUnlock() + if other != gm { + other.mu.RLock() + defer other.mu.RUnlock() } - for k, v := range m.m { + for k, v := range other.m { gm.m[k] = v } } diff --git a/g/container/gpool/gpool.go b/g/container/gpool/gpool.go index a687f11a1..e61b97b94 100644 --- a/g/container/gpool/gpool.go +++ b/g/container/gpool/gpool.go @@ -5,8 +5,6 @@ // You can obtain one at https://github.com/gogf/gf. // Package gpool provides a object-reusable concurrent-safe pool. -// -// 对象复用池. package gpool import ( diff --git a/g/container/gring/gring.go b/g/container/gring/gring.go index 0d34b1424..35479669d 100644 --- a/g/container/gring/gring.go +++ b/g/container/gring/gring.go @@ -4,9 +4,7 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -// Package gring provides a concurrent-safe(alternative) ring(circular lists). -// -// 并发安全环. +// Package gring provides a concurrent-safe/unsafe ring(circular lists). package gring import ( diff --git a/g/container/gset/gset.go b/g/container/gset/gset.go index 3d56f541e..106f23a8c 100644 --- a/g/container/gset/gset.go +++ b/g/container/gset/gset.go @@ -4,9 +4,7 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -// Package gset provides kinds of concurrent-safe(alternative) sets. -// -// 并发安全集合. +// Package gset provides kinds of concurrent-safe/unsafe sets. package gset import ( diff --git a/g/container/gtype/gtype.go b/g/container/gtype/gtype.go index 85cc324bf..d23d509bb 100644 --- a/g/container/gtype/gtype.go +++ b/g/container/gtype/gtype.go @@ -4,9 +4,7 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -// Package gtype provides kinds of high performance, concurrent-safe basic variable types. -// -// 并发安全基本类型. +// Package gtype provides kinds of high performance, concurrent-safe/unsafe basic variable types. package gtype type Type = Interface diff --git a/g/container/gvar/gvar.go b/g/container/gvar/gvar.go index 7e1f9c492..90f7d684e 100644 --- a/g/container/gvar/gvar.go +++ b/g/container/gvar/gvar.go @@ -5,8 +5,6 @@ // You can obtain one at https://github.com/gogf/gf. // Package gvar provides an universal variable type, like generics. -// -// 通用动态变量. package gvar import ( diff --git a/g/database/gdb/gdb.go b/g/database/gdb/gdb.go index bbc2175aa..ad76190ac 100644 --- a/g/database/gdb/gdb.go +++ b/g/database/gdb/gdb.go @@ -148,23 +148,23 @@ type Map = map[string]interface{} type List = []Map const ( - OPTION_INSERT = 0 - OPTION_REPLACE = 1 - OPTION_SAVE = 2 - OPTION_IGNORE = 3 - // 默认批量操作的数量值(Batch*操作) - gDEFAULT_BATCH_NUM = 10 - // 默认的连接池连接存活时间(秒) - gDEFAULT_CONN_MAX_LIFE_TIME = 30 + OPTION_INSERT = 0 + OPTION_REPLACE = 1 + OPTION_SAVE = 2 + OPTION_IGNORE = 3 + gDEFAULT_BATCH_NUM = 10 // Per count for batch insert/replace/save + gDEFAULT_CONN_MAX_LIFE_TIME = 30 // Max life time for per connection in pool. ) var ( - // 单例对象Map + // Instance map. instances = gmap.NewStringInterfaceMap() ) -// 使用默认/指定分组配置进行连接,数据库集群配置项:default -func New(name...string) (db DB, err error) { +// New creates ORM DB object with global configurations. +// The param specifies the configuration group name, +// which is DEFAULT_GROUP_NAME in default. +func New(name ...string) (db DB, err error) { group := configs.defaultGroup if len(name) > 0 { group = name[0] @@ -209,8 +209,10 @@ func New(name...string) (db DB, err error) { } } -// 获得数据库操作对象单例 -func Instance(name...string) (db DB, err error) { +// Instance returns an instance for DB operations. +// The param specifies the configuration group name, +// which is DEFAULT_GROUP_NAME in default. +func Instance(name ...string) (db DB, err error) { group := configs.defaultGroup if len(name) > 0 { group = name[0] diff --git a/g/database/gredis/gredis_config.go b/g/database/gredis/gredis_config.go index 82f43c68f..1f1dba16f 100644 --- a/g/database/gredis/gredis_config.go +++ b/g/database/gredis/gredis_config.go @@ -9,18 +9,16 @@ package gredis import "github.com/gogf/gf/g/container/gmap" const ( - // 默认分组名称 + // Default configuration group name. DEFAULT_GROUP_NAME = "default" ) var ( - // 分组配置 + // Configuration groups. configs = gmap.NewStringInterfaceMap() ) // SetConfig sets the global configuration for specified group. // If is not passed, it sets configuration for the default group name. -// -// 设置全局分组配置,name为非必需参数,默认为默认分组名称。 func SetConfig(config Config, name...string) { group := DEFAULT_GROUP_NAME if len(name) > 0 { @@ -30,10 +28,8 @@ func SetConfig(config Config, name...string) { instances.Remove(group) } -// GetConfig returns the global configuration with specified group. -// If is not passed, it returns configuration of the default group name. -// -// 获取指定全局分组配置,group为非必需参数,默认为默认分组名称。 +// GetConfig returns the global configuration with specified group name. +// If is not passed, it returns configuration of the default group name. func GetConfig(name...string) (config Config, ok bool) { group := DEFAULT_GROUP_NAME if len(name) > 0 { @@ -47,8 +43,6 @@ func GetConfig(name...string) (config Config, ok bool) { // RemoveConfig removes the global configuration with specified group. // If is not passed, it removes configuration of the default group name. -// -// 删除指定全局分组配置,name为非必需参数,默认为默认分组名称。 func RemoveConfig(name...string) { group := DEFAULT_GROUP_NAME if len(name) > 0 { @@ -59,8 +53,6 @@ func RemoveConfig(name...string) { } // ClearConfig removes all configurations and instances of redis. -// -// 清除所有的配置内容。 func ClearConfig() { configs.Clear() instances.Clear() diff --git a/g/frame/gins/gins.go b/g/frame/gins/gins.go index 04a0c6d18..1c936adfe 100644 --- a/g/frame/gins/gins.go +++ b/g/frame/gins/gins.go @@ -8,25 +8,21 @@ package gins import ( - "fmt" - "github.com/gogf/gf/g/container/gmap" - "github.com/gogf/gf/g/database/gdb" - "github.com/gogf/gf/g/database/gredis" - "github.com/gogf/gf/g/internal/cmdenv" - "github.com/gogf/gf/g/os/gcfg" - "github.com/gogf/gf/g/os/gfile" - "github.com/gogf/gf/g/os/gfsnotify" - "github.com/gogf/gf/g/os/glog" - "github.com/gogf/gf/g/os/gview" - "github.com/gogf/gf/g/text/gregex" - "github.com/gogf/gf/g/text/gstr" - "github.com/gogf/gf/g/util/gconv" - "time" + "fmt" + "github.com/gogf/gf/g/container/gmap" + "github.com/gogf/gf/g/database/gdb" + "github.com/gogf/gf/g/database/gredis" + "github.com/gogf/gf/g/os/gcfg" + "github.com/gogf/gf/g/os/gfsnotify" + "github.com/gogf/gf/g/os/glog" + "github.com/gogf/gf/g/os/gview" + "github.com/gogf/gf/g/text/gregex" + "github.com/gogf/gf/g/text/gstr" + "github.com/gogf/gf/g/util/gconv" + "time" ) const ( - gFRAME_CORE_COMPONENT_NAME_VIEW = "gf.core.component.view" - gFRAME_CORE_COMPONENT_NAME_CONFIG = "gf.core.component.config" gFRAME_CORE_COMPONENT_NAME_REDIS = "gf.core.component.redis" gFRAME_CORE_COMPONENT_NAME_DATABASE = "gf.core.component.database" ) @@ -64,48 +60,20 @@ func SetIfNotExist(key string, value interface{}) bool { return instances.SetIfNotExist(key, value) } -// 核心对象:View -func View(name...string) *gview.View { - group := "default" - if len(name) > 0 { - group = name[0] - } - key := fmt.Sprintf("%s.%s", gFRAME_CORE_COMPONENT_NAME_VIEW, group) - return instances.GetOrSetFuncLock(key, func() interface{} { - view := gview.New(gfile.Pwd()) - // 自定义的环境变量/启动参数路径,优先级最高,覆盖默认的工作目录 - if envPath := cmdenv.Get("gf.gview.path").String(); envPath != "" && gfile.Exists(envPath) { - view.SetPath(envPath) - } - // 二进制文件执行目录 - if selfPath := gfile.SelfDir(); selfPath != "" && gfile.Exists(selfPath) { - view.AddPath(selfPath) - } - // 开发环境源码main包目录 - if mainPath := gfile.MainPkgPath(); mainPath != "" && gfile.Exists(mainPath) { - view.AddPath(mainPath) - } - // 框架内置函数 - view.BindFunc("config", funcConfig) - return view - }).(*gview.View) +// View returns an instance of View with default settings. +// The param is the name for the instance. +func View(name ...string) *gview.View { + return gview.Instance(name ...) } -// 核心对象:Config -// 配置文件目录查找依次为:启动参数cfgpath、当前程序运行目录 -func Config(file...string) *gcfg.Config { - configFile := gcfg.DEFAULT_CONFIG_FILE - if len(file) > 0 { - configFile = file[0] - } - key := fmt.Sprintf("%s.%s", gFRAME_CORE_COMPONENT_NAME_CONFIG, configFile) - return instances.GetOrSetFuncLock(key, func() interface{} { - return gcfg.New(configFile) - }).(*gcfg.Config) +// Config returns an instance of View with default settings. +// The param is the name for the instance. +func Config(name ...string) *gcfg.Config { + return gcfg.Instance(name ...) } // 数据库操作对象,使用了连接池 -func Database(name...string) gdb.DB { +func Database(name ...string) gdb.DB { config := Config() group := gdb.DEFAULT_GROUP_NAME if len(name) > 0 { diff --git a/g/os/gcfg/gcfg.go b/g/os/gcfg/gcfg.go index d486f0a40..76da73e1f 100644 --- a/g/os/gcfg/gcfg.go +++ b/g/os/gcfg/gcfg.go @@ -38,7 +38,8 @@ type Config struct { } // New returns a new configuration management object. -func New(file...string) *Config { +// The param specifies the default configuration file name for reading. +func New(file ...string) *Config { name := DEFAULT_CONFIG_FILE if len(file) > 0 { name = file[0] @@ -49,19 +50,24 @@ func New(file...string) *Config { jsons : gmap.NewStringInterfaceMap(), vc : gtype.NewBool(), } - // Dir path of working dir. - c.SetPath(gfile.Pwd()) - // Dir path from env/cmd, most high priority, will overwrite previous dir path setting. - if envPath := cmdenv.Get("gf.gcfg.path").String(); envPath != "" && gfile.Exists(envPath) { - c.SetPath(envPath) - } - // Dir path of binary. - if selfPath := gfile.SelfDir(); selfPath != "" && gfile.Exists(selfPath) { - c.AddPath(selfPath) - } - // Dir path of main package. - if mainPath := gfile.MainPkgPath(); mainPath != "" && gfile.Exists(mainPath) { - c.AddPath(mainPath) + // Customized dir path from env/cmd. + if envPath := cmdenv.Get("gf.gcfg.path").String(); envPath != "" { + if gfile.Exists(envPath) { + c.SetPath(envPath) + } else { + glog.Errorfln("Configuration directory path does not exist: %s", envPath) + } + } else { + // Dir path of working dir. + c.SetPath(gfile.Pwd()) + // Dir path of binary. + if selfPath := gfile.SelfDir(); selfPath != "" && gfile.Exists(selfPath) { + c.AddPath(selfPath) + } + // Dir path of main package. + if mainPath := gfile.MainPkgPath(); mainPath != "" && gfile.Exists(mainPath) { + c.AddPath(mainPath) + } } return c } diff --git a/g/os/gcfg/gcfg_config.go b/g/os/gcfg/gcfg_config.go index 196fa20be..2145a6f9a 100644 --- a/g/os/gcfg/gcfg_config.go +++ b/g/os/gcfg/gcfg_config.go @@ -15,17 +15,25 @@ var ( // SetContent sets customized configuration content for specified . // The is unnecessary param, default is DEFAULT_CONFIG_FILE. -func SetContent(content string, file...string) { +func SetContent(content string, file ...string) { name := DEFAULT_CONFIG_FILE if len(file) > 0 { name = file[0] } - configs.Set(name, content) + // Clear file cache for instances which cached . + instances.LockFunc(func(m map[string]interface{}) { + if configs.Contains(name) { + for _, v := range m { + v.(*Config).jsons.Remove(name) + } + } + configs.Set(name, content) + }) } // GetContent returns customized configuration content for specified . // The is unnecessary param, default is DEFAULT_CONFIG_FILE. -func GetContent(file...string) string { +func GetContent(file ...string) string { name := DEFAULT_CONFIG_FILE if len(file) > 0 { name = file[0] @@ -33,7 +41,31 @@ func GetContent(file...string) string { return configs.Get(name) } +// RemoveConfig removes the global configuration with specified group. +// If is not passed, it removes configuration of the default group name. +func RemoveConfig(file ...string) { + name := DEFAULT_CONFIG_FILE + if len(file) > 0 { + name = file[0] + } + // Clear file cache for instances which cached . + instances.LockFunc(func(m map[string]interface{}) { + if configs.Contains(name) { + for _, v := range m { + v.(*Config).jsons.Remove(name) + } + configs.Remove(name) + } + }) +} + // ClearContent removes all global configuration contents. func ClearContent() { configs.Clear() + // Clear cache for all instances. + instances.LockFunc(func(m map[string]interface{}) { + for _, v := range m { + v.(*Config).jsons.Clear() + } + }) } \ No newline at end of file diff --git a/g/os/gcfg/gcfg_instance.go b/g/os/gcfg/gcfg_instance.go index 9d73e5c77..fce9e0f28 100644 --- a/g/os/gcfg/gcfg_instance.go +++ b/g/os/gcfg/gcfg_instance.go @@ -10,18 +10,23 @@ import ( "github.com/gogf/gf/g/container/gmap" ) +const ( + // Default group name for instance usage. + DEFAULT_GROUP_NAME = "default" +) var ( // Instances map. instances = gmap.NewStringInterfaceMap() ) -// Instance returns an instance of Config. -func Instance(file...string) *Config { - configFile := DEFAULT_CONFIG_FILE - if len(file) > 0 { - configFile = file[0] +// Instance returns an instance of Config with default settings. +// The param is the name for the instance. +func Instance(name ...string) *Config { + key := DEFAULT_GROUP_NAME + if len(name) > 0 { + key = name[0] } - return instances.GetOrSetFuncLock(configFile, func() interface{} { - return New(configFile) + return instances.GetOrSetFuncLock(key, func() interface{} { + return New() }).(*Config) } diff --git a/g/os/gview/gview.go b/g/os/gview/gview.go index bad53824a..4a3c42212 100644 --- a/g/os/gview/gview.go +++ b/g/os/gview/gview.go @@ -5,8 +5,6 @@ // You can obtain one at https://github.com/gogf/gf. // Package gview implements a template engine based on text/template. -// -// 模板引擎. package gview import ( @@ -18,6 +16,7 @@ import ( "github.com/gogf/gf/g/encoding/ghash" "github.com/gogf/gf/g/encoding/ghtml" "github.com/gogf/gf/g/encoding/gurl" + "github.com/gogf/gf/g/internal/cmdenv" "github.com/gogf/gf/g/os/gfcache" "github.com/gogf/gf/g/os/gfile" "github.com/gogf/gf/g/os/glog" @@ -46,19 +45,19 @@ type Params = map[string]interface{} type FuncMap = map[string]interface{} // 默认的视图对象 -var viewObj *View +var defaultViewObj *View // 初始化默认的视图对象, 默认加载包不会初始化,使用包方法才会初始化模板引擎对象。 func checkAndInitDefaultView() { - if viewObj == nil { - viewObj = New(gfile.Pwd()) + if defaultViewObj == nil { + defaultViewObj = New(gfile.Pwd()) } } // 直接解析模板内容,返回解析后的内容 func ParseContent(content string, params Params) ([]byte, error) { checkAndInitDefaultView() - return viewObj.ParseContent(content, params) + return defaultViewObj.ParseContent(content, params) } // 生成一个视图对象 @@ -71,6 +70,26 @@ func New(path...string) *View { } if len(path) > 0 && len(path[0]) > 0 { view.SetPath(path[0]) + } else { + // Customized dir path from env/cmd. + if envPath := cmdenv.Get("gf.gview.path").String(); envPath != "" { + if gfile.Exists(envPath) { + view.SetPath(envPath) + } else { + glog.Errorfln("Template directory path does not exist: %s", envPath) + } + } else { + // Dir path of working dir. + view.SetPath(gfile.Pwd()) + // Dir path of binary. + if selfPath := gfile.SelfDir(); selfPath != "" && gfile.Exists(selfPath) { + view.AddPath(selfPath) + } + // Dir path of main package. + if mainPath := gfile.MainPkgPath(); mainPath != "" && gfile.Exists(mainPath) { + view.AddPath(mainPath) + } + } } view.SetDelimiters("{{", "}}") // 内置变量 diff --git a/g/os/gview/gview_instance.go b/g/os/gview/gview_instance.go new file mode 100644 index 000000000..703c093fc --- /dev/null +++ b/g/os/gview/gview_instance.go @@ -0,0 +1,30 @@ +// 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 this file, +// You can obtain one at https://github.com/gogf/gf. + +package gview + +import "github.com/gogf/gf/g/container/gmap" + +const ( + // Default group name for instance usage. + DEFAULT_INSTANCE_NAME = "default" +) +var ( + // Instances map. + instances = gmap.NewStringInterfaceMap() +) + +// Instance returns an instance of View with default settings. +// The param is the name for the instance. +func Instance(name ...string) *View { + key := DEFAULT_INSTANCE_NAME + if len(name) > 0 { + key = name[0] + } + return instances.GetOrSetFuncLock(key, func() interface{} { + return New() + }).(*View) +} diff --git a/geg/other/test.go b/geg/other/test.go index 342ea80c2..7028e0f04 100644 --- a/geg/other/test.go +++ b/geg/other/test.go @@ -2,21 +2,10 @@ package main import ( "fmt" - "github.com/gogf/gf/g/encoding/gjson" + "github.com/gogf/gf/g/os/gcfg" ) func main() { - config := ` -v1 = 1 -v2 = "true" -v3 = "off" -v4 = "1.23" -array = [1,2,3] -[redis] - disk = "127.0.0.1:6379,0" - cache = "127.0.0.1:6379,1" -` - j, err := gjson.LoadContent(config) - fmt.Println(err) - fmt.Println(j.ToJsonIndentString()) -} + fmt.Println(gcfg.Instance().GetString("viewpath")) + fmt.Println(gcfg.Instance().GetString("database.default.0.host")) +} \ No newline at end of file