mirror of
https://github.com/duanhf2012/origin.git
synced 2026-02-11 13:04:41 +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