mirror of
https://github.com/duanhf2012/origin.git
synced 2026-03-13 19:59:31 +08:00
新增工具库
This commit is contained in:
76
util/deepcopy.go
Normal file
76
util/deepcopy.go
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
// reference: https://github.com/mohae/deepcopy
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
func deepCopy(dst, src reflect.Value) {
|
||||||
|
switch src.Kind() {
|
||||||
|
case reflect.Interface:
|
||||||
|
value := src.Elem()
|
||||||
|
if !value.IsValid() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
newValue := reflect.New(value.Type()).Elem()
|
||||||
|
deepCopy(newValue, value)
|
||||||
|
dst.Set(newValue)
|
||||||
|
case reflect.Ptr:
|
||||||
|
value := src.Elem()
|
||||||
|
if !value.IsValid() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dst.Set(reflect.New(value.Type()))
|
||||||
|
deepCopy(dst.Elem(), value)
|
||||||
|
case reflect.Map:
|
||||||
|
dst.Set(reflect.MakeMap(src.Type()))
|
||||||
|
keys := src.MapKeys()
|
||||||
|
for _, key := range keys {
|
||||||
|
value := src.MapIndex(key)
|
||||||
|
newValue := reflect.New(value.Type()).Elem()
|
||||||
|
deepCopy(newValue, value)
|
||||||
|
dst.SetMapIndex(key, newValue)
|
||||||
|
}
|
||||||
|
case reflect.Slice:
|
||||||
|
dst.Set(reflect.MakeSlice(src.Type(), src.Len(), src.Cap()))
|
||||||
|
for i := 0; i < src.Len(); i++ {
|
||||||
|
deepCopy(dst.Index(i), src.Index(i))
|
||||||
|
}
|
||||||
|
case reflect.Struct:
|
||||||
|
typeSrc := src.Type()
|
||||||
|
for i := 0; i < src.NumField(); i++ {
|
||||||
|
value := src.Field(i)
|
||||||
|
tag := typeSrc.Field(i).Tag
|
||||||
|
if value.CanSet() && tag.Get("deepcopy") != "-" {
|
||||||
|
deepCopy(dst.Field(i), value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
dst.Set(src)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeepCopy(dst, src interface{}) {
|
||||||
|
typeDst := reflect.TypeOf(dst)
|
||||||
|
typeSrc := reflect.TypeOf(src)
|
||||||
|
if typeDst != typeSrc {
|
||||||
|
panic("DeepCopy: " + typeDst.String() + " != " + typeSrc.String())
|
||||||
|
}
|
||||||
|
if typeSrc.Kind() != reflect.Ptr {
|
||||||
|
panic("DeepCopy: pass arguments by address")
|
||||||
|
}
|
||||||
|
|
||||||
|
valueDst := reflect.ValueOf(dst).Elem()
|
||||||
|
valueSrc := reflect.ValueOf(src).Elem()
|
||||||
|
if !valueDst.IsValid() || !valueSrc.IsValid() {
|
||||||
|
panic("DeepCopy: invalid arguments")
|
||||||
|
}
|
||||||
|
|
||||||
|
deepCopy(valueDst, valueSrc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeepClone(v interface{}) interface{} {
|
||||||
|
dst := reflect.New(reflect.TypeOf(v)).Elem()
|
||||||
|
deepCopy(dst, reflect.ValueOf(v))
|
||||||
|
return dst.Interface()
|
||||||
|
}
|
||||||
92
util/example_test.go
Normal file
92
util/example_test.go
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
package util_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/name5566/leaf/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExampleMap() {
|
||||||
|
m := new(util.Map)
|
||||||
|
|
||||||
|
fmt.Println(m.Get("key"))
|
||||||
|
m.Set("key", "value")
|
||||||
|
fmt.Println(m.Get("key"))
|
||||||
|
m.Del("key")
|
||||||
|
fmt.Println(m.Get("key"))
|
||||||
|
|
||||||
|
m.Set(1, "1")
|
||||||
|
m.Set(2, 2)
|
||||||
|
m.Set("3", 3)
|
||||||
|
|
||||||
|
fmt.Println(m.Len())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// <nil>
|
||||||
|
// value
|
||||||
|
// <nil>
|
||||||
|
// 3
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleRandGroup() {
|
||||||
|
i := util.RandGroup(0, 0, 50, 50)
|
||||||
|
switch i {
|
||||||
|
case 2, 3:
|
||||||
|
fmt.Println("ok")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleRandInterval() {
|
||||||
|
v := util.RandInterval(-1, 1)
|
||||||
|
switch v {
|
||||||
|
case -1, 0, 1:
|
||||||
|
fmt.Println("ok")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleRandIntervalN() {
|
||||||
|
r := util.RandIntervalN(-1, 0, 2)
|
||||||
|
if r[0] == -1 && r[1] == 0 ||
|
||||||
|
r[0] == 0 && r[1] == -1 {
|
||||||
|
fmt.Println("ok")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleDeepCopy() {
|
||||||
|
src := []int{1, 2, 3}
|
||||||
|
|
||||||
|
var dst []int
|
||||||
|
util.DeepCopy(&dst, &src)
|
||||||
|
|
||||||
|
for _, v := range dst {
|
||||||
|
fmt.Println(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1
|
||||||
|
// 2
|
||||||
|
// 3
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleDeepClone() {
|
||||||
|
src := []int{1, 2, 3}
|
||||||
|
|
||||||
|
dst := util.DeepClone(src).([]int)
|
||||||
|
|
||||||
|
for _, v := range dst {
|
||||||
|
fmt.Println(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 1
|
||||||
|
// 2
|
||||||
|
// 3
|
||||||
|
}
|
||||||
101
util/map.go
Normal file
101
util/map.go
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Map struct {
|
||||||
|
sync.RWMutex
|
||||||
|
m map[interface{}]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Map) init() {
|
||||||
|
if m.m == nil {
|
||||||
|
m.m = make(map[interface{}]interface{})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Map) UnsafeGet(key interface{}) interface{} {
|
||||||
|
if m.m == nil {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return m.m[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Map) Get(key interface{}) interface{} {
|
||||||
|
m.RLock()
|
||||||
|
defer m.RUnlock()
|
||||||
|
return m.UnsafeGet(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Map) UnsafeSet(key interface{}, value interface{}) {
|
||||||
|
m.init()
|
||||||
|
m.m[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Map) Set(key interface{}, value interface{}) {
|
||||||
|
m.Lock()
|
||||||
|
defer m.Unlock()
|
||||||
|
m.UnsafeSet(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Map) TestAndSet(key interface{}, value interface{}) interface{} {
|
||||||
|
m.Lock()
|
||||||
|
defer m.Unlock()
|
||||||
|
|
||||||
|
m.init()
|
||||||
|
|
||||||
|
if v, ok := m.m[key]; ok {
|
||||||
|
return v
|
||||||
|
} else {
|
||||||
|
m.m[key] = value
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Map) UnsafeDel(key interface{}) {
|
||||||
|
m.init()
|
||||||
|
delete(m.m, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Map) Del(key interface{}) {
|
||||||
|
m.Lock()
|
||||||
|
defer m.Unlock()
|
||||||
|
m.UnsafeDel(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Map) UnsafeLen() int {
|
||||||
|
if m.m == nil {
|
||||||
|
return 0
|
||||||
|
} else {
|
||||||
|
return len(m.m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Map) Len() int {
|
||||||
|
m.RLock()
|
||||||
|
defer m.RUnlock()
|
||||||
|
return m.UnsafeLen()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Map) UnsafeRange(f func(interface{}, interface{})) {
|
||||||
|
if m.m == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for k, v := range m.m {
|
||||||
|
f(k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Map) RLockRange(f func(interface{}, interface{})) {
|
||||||
|
m.RLock()
|
||||||
|
defer m.RUnlock()
|
||||||
|
m.UnsafeRange(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Map) LockRange(f func(interface{}, interface{})) {
|
||||||
|
m.Lock()
|
||||||
|
defer m.Unlock()
|
||||||
|
m.UnsafeRange(f)
|
||||||
|
}
|
||||||
91
util/rand.go
Normal file
91
util/rand.go
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
}
|
||||||
|
|
||||||
|
func RandGroup(p ...uint32) int {
|
||||||
|
if p == nil {
|
||||||
|
panic("args not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
r := make([]uint32, len(p))
|
||||||
|
for i := 0; i < len(p); i++ {
|
||||||
|
if i == 0 {
|
||||||
|
r[0] = p[0]
|
||||||
|
} else {
|
||||||
|
r[i] = r[i-1] + p[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rl := r[len(r)-1]
|
||||||
|
if rl == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
rn := uint32(rand.Int63n(int64(rl)))
|
||||||
|
for i := 0; i < len(r); i++ {
|
||||||
|
if rn < r[i] {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
panic("bug")
|
||||||
|
}
|
||||||
|
|
||||||
|
func RandInterval(b1, b2 int32) int32 {
|
||||||
|
if b1 == b2 {
|
||||||
|
return b1
|
||||||
|
}
|
||||||
|
|
||||||
|
min, max := int64(b1), int64(b2)
|
||||||
|
if min > max {
|
||||||
|
min, max = max, min
|
||||||
|
}
|
||||||
|
return int32(rand.Int63n(max-min+1) + min)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RandIntervalN(b1, b2 int32, n uint32) []int32 {
|
||||||
|
if b1 == b2 {
|
||||||
|
return []int32{b1}
|
||||||
|
}
|
||||||
|
|
||||||
|
min, max := int64(b1), int64(b2)
|
||||||
|
if min > max {
|
||||||
|
min, max = max, min
|
||||||
|
}
|
||||||
|
l := max - min + 1
|
||||||
|
if int64(n) > l {
|
||||||
|
n = uint32(l)
|
||||||
|
}
|
||||||
|
|
||||||
|
r := make([]int32, n)
|
||||||
|
m := make(map[int32]int32)
|
||||||
|
for i := uint32(0); i < n; i++ {
|
||||||
|
v := int32(rand.Int63n(l) + min)
|
||||||
|
|
||||||
|
if mv, ok := m[v]; ok {
|
||||||
|
r[i] = mv
|
||||||
|
} else {
|
||||||
|
r[i] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
lv := int32(l - 1 + min)
|
||||||
|
if v != lv {
|
||||||
|
if mv, ok := m[lv]; ok {
|
||||||
|
m[v] = mv
|
||||||
|
} else {
|
||||||
|
m[v] = lv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
l--
|
||||||
|
}
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
15
util/semaphore.go
Normal file
15
util/semaphore.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
type Semaphore chan struct{}
|
||||||
|
|
||||||
|
func MakeSemaphore(n int) Semaphore {
|
||||||
|
return make(Semaphore, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Semaphore) Acquire() {
|
||||||
|
s <- struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Semaphore) Release() {
|
||||||
|
<-s
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user