Compare commits
122 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b065fccf5c | ||
![]() |
489449c65d | ||
![]() |
7078a16983 | ||
![]() |
ba4b733a80 | ||
![]() |
d40b258a47 | ||
![]() |
ad5656a00a | ||
![]() |
ccfa6c4f99 | ||
![]() |
db5e615704 | ||
![]() |
b9c7e05031 | ||
![]() |
dd6cf60934 | ||
![]() |
f715cffbce | ||
![]() |
6d58535a91 | ||
![]() |
5c996e016a | ||
![]() |
a0122ba8e5 | ||
![]() |
883eff90e5 | ||
![]() |
91b9c416fb | ||
![]() |
8877d9e02a | ||
![]() |
763b161e26 | ||
![]() |
a26208f76e | ||
![]() |
9afe1aa679 | ||
![]() |
de3dc89691 | ||
![]() |
47f75d8247 | ||
![]() |
3ade5a2266 | ||
![]() |
e7e95ff498 | ||
![]() |
9048589a4d | ||
![]() |
06880e9f72 | ||
![]() |
4f7255c731 | ||
![]() |
0ec6d9a142 | ||
![]() |
75b0c72d72 | ||
![]() |
fc08e4f8c5 | ||
![]() |
70d3baf515 | ||
![]() |
9ab4817ec5 | ||
![]() |
3eeb9788ce | ||
![]() |
01573c9947 | ||
![]() |
67c14c72ff | ||
![]() |
7f080f238e | ||
![]() |
a6abd190f9 | ||
![]() |
61a612b594 | ||
![]() |
583a9d2358 | ||
![]() |
decda354c8 | ||
![]() |
3d4c6f692f | ||
![]() |
50cb269954 | ||
![]() |
ef6a02719b | ||
![]() |
72f4aa8132 | ||
![]() |
aa48a0c524 | ||
![]() |
b590bbd0fe | ||
![]() |
867867b5d6 | ||
![]() |
f0ba360bdc | ||
![]() |
a784d12ab4 | ||
![]() |
37aba94237 | ||
![]() |
fe65489de2 | ||
![]() |
2ce4c46c71 | ||
![]() |
a28a913a90 | ||
![]() |
50a75088ae | ||
![]() |
d72fab5c83 | ||
![]() |
87bea6ab2c | ||
![]() |
f913e480a2 | ||
![]() |
ed967899c4 | ||
![]() |
9823133648 | ||
![]() |
8716d301c6 | ||
![]() |
9377182985 | ||
![]() |
b343ad660a | ||
![]() |
aecf26a45c | ||
![]() |
7bffd9a638 | ||
![]() |
0644461bc7 | ||
![]() |
dacdd2a5db | ||
![]() |
efae915742 | ||
![]() |
2418793e3d | ||
![]() |
67c974caa2 | ||
![]() |
cadab4f094 | ||
![]() |
490774a7a3 | ||
![]() |
6a998e6eea | ||
![]() |
b62848491f | ||
![]() |
96e7c20cf0 | ||
![]() |
73c047e43f | ||
![]() |
85a82957ca | ||
![]() |
607a4887d0 | ||
![]() |
d82df9df79 | ||
![]() |
562242ca3f | ||
![]() |
bc3b2825a6 | ||
![]() |
03ffea28fe | ||
![]() |
c832144308 | ||
![]() |
a7c34b44d7 | ||
![]() |
70271a1b60 | ||
![]() |
56027b3c56 | ||
![]() |
1e70d9f893 | ||
![]() |
80edf5bfe5 | ||
![]() |
877ac12ec2 | ||
![]() |
e21d2e3b5d | ||
![]() |
f9776ebd7c | ||
![]() |
933ed5c972 | ||
![]() |
7442ad5d81 | ||
![]() |
ef23a486d3 | ||
![]() |
b50a0152e1 | ||
![]() |
0067fe79b2 | ||
![]() |
00b7f9e2ea | ||
![]() |
adf774f543 | ||
![]() |
1d9c4287fb | ||
![]() |
190668be5f | ||
![]() |
2a26b63c85 | ||
![]() |
f62a41fba7 | ||
![]() |
5b8b5563e9 | ||
![]() |
88b284f7de | ||
![]() |
6fd253d455 | ||
![]() |
e0ae331d17 | ||
![]() |
a3ab521064 | ||
![]() |
7ab75e421e | ||
![]() |
7749a036a0 | ||
![]() |
a3412f2da9 | ||
![]() |
8360f367bc | ||
![]() |
de0c368e4c | ||
![]() |
f58f61120a | ||
![]() |
a9b6ae14e7 | ||
![]() |
e934b0c6ca | ||
![]() |
9e16bd764d | ||
![]() |
4192dcc9fc | ||
![]() |
f54243a465 | ||
![]() |
5d0b0eacad | ||
![]() |
d1c788bb06 | ||
![]() |
a8b0821963 | ||
![]() |
924eed81d1 | ||
![]() |
3e730f5d26 |
29
algorithm.go
Normal file
29
algorithm.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package q5
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sort"
|
||||||
|
)
|
||||||
|
|
||||||
|
type sortImpl[T any] struct {
|
||||||
|
data []*T
|
||||||
|
lessCb func(*T, *T) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *sortImpl[T]) Len() int {
|
||||||
|
return len(this.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *sortImpl[T]) Swap(i int, j int) {
|
||||||
|
this.data[i], this.data[j] = this.data[j], this.data[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *sortImpl[T]) Less(i int, j int) bool {
|
||||||
|
return this.lessCb(this.data[i], this.data[j])
|
||||||
|
}
|
||||||
|
|
||||||
|
func Sort[T any](data []*T, lessCb func(*T, *T) bool) {
|
||||||
|
impl := new(sortImpl[T])
|
||||||
|
impl.data = data
|
||||||
|
impl.lessCb = lessCb
|
||||||
|
sort.Sort(impl)
|
||||||
|
}
|
228
convert.go
Normal file
228
convert.go
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
package q5
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ToInt converts a value to an integer.
|
||||||
|
func ToInt32[T string | int | int32 | int64 | float32 | float64](value T) int32 {
|
||||||
|
return int32(ToInt64(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToInt converts a value to an integer.
|
||||||
|
func ToInt[T string | int32 | int64 | float32 | float64](value T) int {
|
||||||
|
return int(ToInt64(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToInt64 converts a value to an int64.
|
||||||
|
func ToInt64[T string | int | int32 | int64 | float32 | float64](value T) int64 {
|
||||||
|
var x interface{} = value
|
||||||
|
switch i := x.(type) {
|
||||||
|
case int:
|
||||||
|
return int64(i)
|
||||||
|
case int32:
|
||||||
|
return int64(i)
|
||||||
|
case int64:
|
||||||
|
return i
|
||||||
|
case float32:
|
||||||
|
return int64(i)
|
||||||
|
case float64:
|
||||||
|
return int64(i)
|
||||||
|
case string:
|
||||||
|
intValue, err := strconv.ParseInt(i, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return intValue
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToFloat32[T string | int | int32 | int64 | float32 | float64](value T) float32 {
|
||||||
|
return float32(ToFloat64(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToFloat converts a value to a float64.
|
||||||
|
func ToFloat64[T string | int | int32 | int64 | float32 | float64](value T) float64 {
|
||||||
|
var x interface{} = value
|
||||||
|
switch i := x.(type) {
|
||||||
|
case int:
|
||||||
|
return float64(i)
|
||||||
|
case int32:
|
||||||
|
return float64(i)
|
||||||
|
case int64:
|
||||||
|
return float64(i)
|
||||||
|
case float32:
|
||||||
|
return float64(i)
|
||||||
|
case float64:
|
||||||
|
return i
|
||||||
|
case string:
|
||||||
|
f, _ := strconv.ParseFloat(strings.TrimSpace(i), 64)
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
return 0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToString converts a value to a string.
|
||||||
|
func ToString[T string | int | int32 | int64 | float32 | float64](value T) string {
|
||||||
|
var x interface{} = value
|
||||||
|
switch i := x.(type) {
|
||||||
|
case int:
|
||||||
|
return strconv.Itoa(i)
|
||||||
|
case int32:
|
||||||
|
return strconv.Itoa(int(i))
|
||||||
|
case int64:
|
||||||
|
return strconv.FormatInt(i, 10)
|
||||||
|
case float32:
|
||||||
|
return strconv.FormatFloat(float64(i), 'f', -1, 32)
|
||||||
|
case float64:
|
||||||
|
return strconv.FormatFloat(i, 'f', -1, 64)
|
||||||
|
case string:
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToInt64Ex(x interface{}) (int64, error) {
|
||||||
|
switch i := x.(type) {
|
||||||
|
case int:
|
||||||
|
return int64(i), nil
|
||||||
|
case int32:
|
||||||
|
return int64(i), nil
|
||||||
|
case int64:
|
||||||
|
return i, nil
|
||||||
|
case float32:
|
||||||
|
return int64(i), nil
|
||||||
|
case float64:
|
||||||
|
return int64(i), nil
|
||||||
|
case string:
|
||||||
|
intValue, err := strconv.ParseInt(i, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
return intValue, nil
|
||||||
|
}
|
||||||
|
return 0, errors.New("ToInt64Ex error type")
|
||||||
|
}
|
||||||
|
|
||||||
|
func SafeToInt64(x interface{}) int64 {
|
||||||
|
val, _ := ToInt64Ex(x)
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
func SafeToInt32(x interface{}) int32 {
|
||||||
|
val, _ := ToInt64Ex(x)
|
||||||
|
return int32(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToFloat64Ex(x interface{}) (float64, error) {
|
||||||
|
switch i := x.(type) {
|
||||||
|
case int:
|
||||||
|
return float64(i), nil
|
||||||
|
case int32:
|
||||||
|
return float64(i), nil
|
||||||
|
case int64:
|
||||||
|
return float64(i), nil
|
||||||
|
case float32:
|
||||||
|
return float64(i), nil
|
||||||
|
case float64:
|
||||||
|
return i, nil
|
||||||
|
case string:
|
||||||
|
f, _ := strconv.ParseFloat(strings.TrimSpace(i), 64)
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
|
return 0, errors.New("ToFloat64Ex error type")
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToStringEx(x interface{}) (string, error) {
|
||||||
|
switch i := x.(type) {
|
||||||
|
case int:
|
||||||
|
return strconv.Itoa(i), nil
|
||||||
|
case int32:
|
||||||
|
return strconv.Itoa(int(i)), nil
|
||||||
|
case int64:
|
||||||
|
return strconv.FormatInt(i, 10), nil
|
||||||
|
case float32:
|
||||||
|
return strconv.FormatFloat(float64(i), 'f', -1, 32), nil
|
||||||
|
case float64:
|
||||||
|
return strconv.FormatFloat(i, 'f', -1, 64), nil
|
||||||
|
case string:
|
||||||
|
return i, nil
|
||||||
|
}
|
||||||
|
return "", errors.New("ToStringEx error type")
|
||||||
|
}
|
||||||
|
|
||||||
|
func SafeToString(x interface{}) string {
|
||||||
|
val, _ := ToStringEx(x)
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
func DuckToSimple[T string | int | int32 | int64 | float32 | float64](
|
||||||
|
d interface{}, s *T) bool {
|
||||||
|
var sx interface{} = s
|
||||||
|
switch sv := sx.(type) {
|
||||||
|
case *int:
|
||||||
|
{
|
||||||
|
if val, err := ToInt64Ex(d); err == nil {
|
||||||
|
*sv = int(val)
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case *int32:
|
||||||
|
{
|
||||||
|
if val, err := ToInt64Ex(d); err == nil {
|
||||||
|
*sv = int32(val)
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case *int64:
|
||||||
|
{
|
||||||
|
if val, err := ToInt64Ex(d); err == nil {
|
||||||
|
*sv = val
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case *float32:
|
||||||
|
{
|
||||||
|
if val, err := ToFloat64Ex(d); err == nil {
|
||||||
|
*sv = float32(val)
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case *float64:
|
||||||
|
{
|
||||||
|
if val, err := ToFloat64Ex(d); err == nil {
|
||||||
|
*sv = val
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case *string:
|
||||||
|
{
|
||||||
|
if val, err := ToStringEx(d); err == nil {
|
||||||
|
*sv = val
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToBool[T int32 | int64 ](value T) bool {
|
||||||
|
return value != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func BoolToInt32(value bool) int32 {
|
||||||
|
if value {
|
||||||
|
return 1
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
63
functional.go
Normal file
63
functional.go
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package q5
|
||||||
|
|
||||||
|
func Map[T any](arr []T, cb func(T) T) []T {
|
||||||
|
newList := []T{}
|
||||||
|
for _, val := range arr {
|
||||||
|
newList = append(newList, cb(val))
|
||||||
|
}
|
||||||
|
return newList
|
||||||
|
}
|
||||||
|
|
||||||
|
func Reduce[T any](arr []T, cb func(T, T) T, initVal *T) T {
|
||||||
|
var result T
|
||||||
|
if initVal != nil {
|
||||||
|
result = *initVal
|
||||||
|
}
|
||||||
|
if len(arr) > 0 {
|
||||||
|
if initVal == nil {
|
||||||
|
result = arr[0]
|
||||||
|
for i := 1; i < len(arr); i++ {
|
||||||
|
result = cb(result, arr[i])
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for i := 0; i < len(arr); i++ {
|
||||||
|
result = cb(result, arr[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func Filter[T any](arr []T, cb func(T) bool) []T {
|
||||||
|
newList := []T{}
|
||||||
|
for _, val := range arr {
|
||||||
|
if cb(val) {
|
||||||
|
newList = append(newList, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newList
|
||||||
|
}
|
||||||
|
|
||||||
|
func Max[T string | int | int32 | int64 | float32 | float64](a T, b T) T {
|
||||||
|
if a < b {
|
||||||
|
return b
|
||||||
|
} else {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Min[T string | int | int32 | int64 | float32 | float64](a T, b T) T {
|
||||||
|
if a < b {
|
||||||
|
return a
|
||||||
|
} else {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToInterfaces[T any](values []T) []interface{} {
|
||||||
|
result := []interface{}{}
|
||||||
|
for _, val := range values {
|
||||||
|
result = append(result, val)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
10
go.mod
Normal file
10
go.mod
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
module q5
|
||||||
|
|
||||||
|
go 1.20
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/garyburd/redigo v1.6.2
|
||||||
|
github.com/go-sql-driver/mysql v1.5.0
|
||||||
|
github.com/gomodule/redigo v1.8.3
|
||||||
|
golang.org/x/crypto v0.13.0 // indirect
|
||||||
|
)
|
18
go.sum
Normal file
18
go.sum
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/garyburd/redigo v1.6.2 h1:yE/pwKCrbLpLpQICzYTeZ7JsTA/C53wFTJHaEtRqniM=
|
||||||
|
github.com/garyburd/redigo v1.6.2/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
||||||
|
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||||
|
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
|
github.com/gomodule/redigo v1.8.3 h1:HR0kYDX2RJZvAup8CsiJwxB4dTCSC0AaUq6S4SiLwUc=
|
||||||
|
github.com/gomodule/redigo v1.8.3/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||||
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
|
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
|
||||||
|
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
120
httpcli.go
Normal file
120
httpcli.go
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
package q5
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
net_url "net/url"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
HTTP_OPT_ADD_HEADER = iota
|
||||||
|
HTTP_OPT_SET_PROXY = iota
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
HTTP_HEADER_JSON = "application/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
func internalSetOpt(client *http.Client, request *http.Request, opt int32,
|
||||||
|
key string, val string) {
|
||||||
|
switch opt {
|
||||||
|
case HTTP_OPT_ADD_HEADER:
|
||||||
|
request.Header.Add(key, val)
|
||||||
|
default:
|
||||||
|
panic("error http opt")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func HttpGet(url string, params map[string]string) (string, error) {
|
||||||
|
return HttpGetEx(url, params, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func HttpGetEx(url string, params map[string]string,
|
||||||
|
initFunc func(setOpt func(int32, string, string))) (string, error) {
|
||||||
|
if !StrContains(url, "?") {
|
||||||
|
url = url + "?"
|
||||||
|
}
|
||||||
|
{
|
||||||
|
u := net_url.Values{}
|
||||||
|
for key, val := range params {
|
||||||
|
u.Set(key, val)
|
||||||
|
}
|
||||||
|
url = url + u.Encode()
|
||||||
|
}
|
||||||
|
client := &http.Client{}
|
||||||
|
request, err := http.NewRequest("GET", url, nil)
|
||||||
|
if err != nil {
|
||||||
|
panic("http.NewRequest error")
|
||||||
|
}
|
||||||
|
if initFunc != nil {
|
||||||
|
initFunc(func(opt int32, key string, val string) {
|
||||||
|
internalSetOpt(client, request, opt, key, val)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if resp, err := client.Do(request); err == nil {
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
return "", errors.New("HttpGet error Status:" + resp.Status)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
if bytes, err := ioutil.ReadAll(resp.Body); err == nil {
|
||||||
|
return string(bytes), nil
|
||||||
|
} else {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func HttpGetEx2(url string, params map[string]string) (*http.Response, string, error) {
|
||||||
|
if !StrContains(url, "?") {
|
||||||
|
url = url + "?"
|
||||||
|
}
|
||||||
|
{
|
||||||
|
u := net_url.Values{}
|
||||||
|
for key, val := range params {
|
||||||
|
u.Set(key, val)
|
||||||
|
}
|
||||||
|
url = url + u.Encode()
|
||||||
|
}
|
||||||
|
client := &http.Client{}
|
||||||
|
request, err := http.NewRequest("GET", url, nil)
|
||||||
|
if err != nil {
|
||||||
|
panic("http.NewRequest error")
|
||||||
|
}
|
||||||
|
if resp, err := client.Do(request); err == nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
if bytes, err := ioutil.ReadAll(resp.Body); err == nil {
|
||||||
|
return resp, string(bytes), nil
|
||||||
|
} else {
|
||||||
|
return resp, "", err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func HttpPost(url string, params map[string]string, contentType string, body string) (string, error) {
|
||||||
|
if !StrContains(url, "?") {
|
||||||
|
url = url + "?"
|
||||||
|
}
|
||||||
|
{
|
||||||
|
u := net_url.Values{}
|
||||||
|
for key, val := range params {
|
||||||
|
u.Set(key, val)
|
||||||
|
}
|
||||||
|
url = url + u.Encode()
|
||||||
|
}
|
||||||
|
resp, err := http.Post(url, contentType, strings.NewReader(body))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
if bytes, err := ioutil.ReadAll(resp.Body); err == nil {
|
||||||
|
return string(bytes), nil
|
||||||
|
} else {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
137
listhead.go
Normal file
137
listhead.go
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
package q5
|
||||||
|
|
||||||
|
type ListHead_Foreach_Func func(interface{}) bool
|
||||||
|
|
||||||
|
type ListHead struct {
|
||||||
|
next *ListHead
|
||||||
|
prev *ListHead
|
||||||
|
data interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ListHead) Init(data interface{}) {
|
||||||
|
this.next = this
|
||||||
|
this.prev = this
|
||||||
|
this.data = data
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ListHead) GetData() interface{} {
|
||||||
|
return this.data
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ListHead) Del() {
|
||||||
|
this.next.prev = this.prev
|
||||||
|
this.prev.next = this.next
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ListHead) AddTail(pnew *ListHead) {
|
||||||
|
prev := this.prev
|
||||||
|
next := this
|
||||||
|
|
||||||
|
next.prev = pnew
|
||||||
|
pnew.next = next
|
||||||
|
pnew.prev = prev
|
||||||
|
prev.next = pnew
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ListHead) AddHead(pnew *ListHead) {
|
||||||
|
prev := this
|
||||||
|
next := this.prev
|
||||||
|
|
||||||
|
next.prev = pnew
|
||||||
|
pnew.next = next
|
||||||
|
pnew.prev = prev
|
||||||
|
prev.next = pnew
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ListHead) FirstEntry() interface{} {
|
||||||
|
if !this.next.isCursor() {
|
||||||
|
return this.next.data
|
||||||
|
}
|
||||||
|
for pos := this.next; pos != this; pos = pos.next {
|
||||||
|
if !pos.isCursor() {
|
||||||
|
return pos.data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ListHead) Replace(pnew *ListHead) {
|
||||||
|
pnew.next = this.next
|
||||||
|
pnew.next.prev = pnew
|
||||||
|
pnew.prev = this.prev
|
||||||
|
pnew.prev.next = pnew
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ListHead) ReplaceInit(pnew *ListHead) {
|
||||||
|
this.Replace(pnew)
|
||||||
|
this.next = this
|
||||||
|
this.prev = this
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ListHead) Empty() bool {
|
||||||
|
if this.next == this {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if !this.next.isCursor() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for pos := this.next; pos != this; pos = pos.next {
|
||||||
|
if !pos.isCursor() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ListHead) DelInit() {
|
||||||
|
this.Del()
|
||||||
|
this.next = this
|
||||||
|
this.prev = this
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ListHead) Size() int32 {
|
||||||
|
num := int32(0)
|
||||||
|
this.ForEach(
|
||||||
|
func(data interface{}) bool {
|
||||||
|
num++
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return num
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ListHead) isCursor() bool {
|
||||||
|
return this.data == this
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ListHead) IsFirst(entry* ListHead) bool {
|
||||||
|
return this.next == entry
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ListHead) ForEach(cb ListHead_Foreach_Func) {
|
||||||
|
for pos := this.next; pos != this; pos = pos.next {
|
||||||
|
if !cb(pos.data) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
cursor := ListHead{}
|
||||||
|
cursor.data = &cursor
|
||||||
|
this.AddHead(&cursor)
|
||||||
|
defer cursor.Del()
|
||||||
|
for cursor.next != this {
|
||||||
|
oldN := cursor.next
|
||||||
|
if !cursor.next.isCursor() && !cb(cursor.next.data) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if cursor.next == oldN {
|
||||||
|
oldN.Del()
|
||||||
|
cursor.AddTail(oldN)
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewListHead() *ListHead {
|
||||||
|
l := new(ListHead)
|
||||||
|
l.Init(nil)
|
||||||
|
return l
|
||||||
|
}
|
77
mysql.go
Normal file
77
mysql.go
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
package q5
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Mysql struct {
|
||||||
|
host string
|
||||||
|
port int32
|
||||||
|
user string
|
||||||
|
passwd string
|
||||||
|
database string
|
||||||
|
db *sql.DB
|
||||||
|
maxOpenConns int32
|
||||||
|
maxIdleConns int32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Mysql) init(host string, port int32, user string, passwd string, database string,
|
||||||
|
maxOpenConns int32, maxIdleConns int32) {
|
||||||
|
this.host = host
|
||||||
|
this.port = port
|
||||||
|
this.user = user
|
||||||
|
this.passwd = passwd
|
||||||
|
this.database = database
|
||||||
|
this.maxOpenConns = maxOpenConns
|
||||||
|
this.maxIdleConns = maxIdleConns
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Mysql) Open() error {
|
||||||
|
connStr := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8",
|
||||||
|
this.user,
|
||||||
|
this.passwd,
|
||||||
|
this.host,
|
||||||
|
this.port,
|
||||||
|
this.database)
|
||||||
|
db, err := sql.Open("mysql", connStr)
|
||||||
|
this.db = db
|
||||||
|
if err == nil {
|
||||||
|
this.db.SetMaxOpenConns(int(this.maxOpenConns))
|
||||||
|
this.db.SetMaxIdleConns(int(this.maxIdleConns))
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Mysql) Close() {
|
||||||
|
if this.db != nil {
|
||||||
|
this.db.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Mysql) Ping() error {
|
||||||
|
return this.db.Ping()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Mysql) Query(query string, args ...interface{}) (*sql.Rows, error) {
|
||||||
|
rows, err := this.db.Query(query, args...)
|
||||||
|
return rows, err
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
func (this *Mysql) QueryRow(query string, args ...interface{}) *sql.Row {
|
||||||
|
return this.db.QueryRow(query, args...)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
func (this *Mysql) Exec(query string, args ...interface{}) (sql.Result, error) {
|
||||||
|
result, err := this.db.Exec(query, args...)
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMysql(host string, port int32, user string, passwd string, database string, maxOpenConns int32, maxIdleConns int32) *Mysql {
|
||||||
|
conn := new(Mysql)
|
||||||
|
conn.init(host, port, user, passwd, database, maxOpenConns, maxIdleConns)
|
||||||
|
return conn
|
||||||
|
}
|
20
password.go
Normal file
20
password.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package q5
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HashPassword returns the bcrypt hash of the password
|
||||||
|
func HashPassword(password string) (string, error) {
|
||||||
|
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to hash password: %w", err)
|
||||||
|
}
|
||||||
|
return string(hashedPassword), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckPassword checks if the provided password is correct or not
|
||||||
|
func CheckPassword(password string, hashedPassword string) error {
|
||||||
|
return bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))
|
||||||
|
}
|
41
queue.go
Normal file
41
queue.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package q5
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Queue struct {
|
||||||
|
msgMutex sync.Mutex
|
||||||
|
msgList ListHead
|
||||||
|
WorkList ListHead
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Queue) Init() {
|
||||||
|
this.msgList.Init(nil)
|
||||||
|
this.WorkList.Init(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Queue) Push(node *ListHead) {
|
||||||
|
this.msgMutex.Lock()
|
||||||
|
defer this.msgMutex.Unlock()
|
||||||
|
this.msgList.AddTail(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Queue) Fetch() {
|
||||||
|
if this.WorkList.Empty() {
|
||||||
|
this.msgMutex.Lock()
|
||||||
|
defer this.msgMutex.Unlock()
|
||||||
|
if !this.msgList.Empty() {
|
||||||
|
this.msgList.ReplaceInit(&this.WorkList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Queue) IsEmpty() bool {
|
||||||
|
if !this.WorkList.Empty() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
this.msgMutex.Lock()
|
||||||
|
defer this.msgMutex.Unlock()
|
||||||
|
return this.msgList.Empty()
|
||||||
|
}
|
21
random.go
Normal file
21
random.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package q5
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RandomString generates a random string of length n
|
||||||
|
const alphabet = "abcdefghijklmnopqrstuvwxyz"
|
||||||
|
|
||||||
|
func RandomString(n int) string {
|
||||||
|
var sb strings.Builder
|
||||||
|
k := len(alphabet)
|
||||||
|
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
c := alphabet[rand.Intn(k)]
|
||||||
|
sb.WriteByte(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.String()
|
||||||
|
}
|
24
redis.go
Normal file
24
redis.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package q5
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gomodule/redigo/redis"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Redis struct {
|
||||||
|
host string
|
||||||
|
port int32
|
||||||
|
passwd string
|
||||||
|
conn *redis.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Redis) Init(host string, port int32, passwd string) {
|
||||||
|
this.host = host
|
||||||
|
this.port = port
|
||||||
|
this.passwd = passwd
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Redis) Open() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Redis) Close() {
|
||||||
|
}
|
200
reflect.go
Normal file
200
reflect.go
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
package q5
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
func IsSimpleReflectKind(kind reflect.Kind) bool {
|
||||||
|
switch kind {
|
||||||
|
case reflect.Bool,
|
||||||
|
reflect.Int,
|
||||||
|
reflect.Int8,
|
||||||
|
reflect.Int16,
|
||||||
|
reflect.Int32,
|
||||||
|
reflect.Int64,
|
||||||
|
reflect.Uint,
|
||||||
|
reflect.Uint8,
|
||||||
|
reflect.Uint16,
|
||||||
|
reflect.Uint32,
|
||||||
|
reflect.Uint64,
|
||||||
|
reflect.Float32,
|
||||||
|
reflect.Float64,
|
||||||
|
reflect.String:
|
||||||
|
{
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func StrToSimpleReflectValue(val string, kind reflect.Kind) *reflect.Value {
|
||||||
|
switch kind {
|
||||||
|
case reflect.Bool:
|
||||||
|
{
|
||||||
|
v := reflect.ValueOf(val == "1" || val == "true")
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
case reflect.Int:
|
||||||
|
{
|
||||||
|
v := reflect.ValueOf(int(ToInt64(val)))
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
case reflect.Int8:
|
||||||
|
{
|
||||||
|
v := reflect.ValueOf(int8(ToInt64(val)))
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
case reflect.Int16:
|
||||||
|
{
|
||||||
|
v := reflect.ValueOf(int16(ToInt64(val)))
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
case reflect.Int32:
|
||||||
|
{
|
||||||
|
v := reflect.ValueOf(int32(ToInt64(val)))
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
case reflect.Int64:
|
||||||
|
{
|
||||||
|
v := reflect.ValueOf(ToInt64(val))
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
case reflect.Uint:
|
||||||
|
{
|
||||||
|
v := reflect.ValueOf(uint(ToInt64(val)))
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
case reflect.Uint8:
|
||||||
|
{
|
||||||
|
v := reflect.ValueOf(uint8(ToInt64(val)))
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
case reflect.Uint16:
|
||||||
|
{
|
||||||
|
v := reflect.ValueOf(uint16(ToInt64(val)))
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
case reflect.Uint32:
|
||||||
|
{
|
||||||
|
v := reflect.ValueOf(uint32(ToInt64(val)))
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
case reflect.Uint64:
|
||||||
|
{
|
||||||
|
v := reflect.ValueOf(uint64(ToInt64(val)))
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
case reflect.Float32,
|
||||||
|
reflect.Float64:
|
||||||
|
{
|
||||||
|
v := reflect.ValueOf(ToFloat64(val))
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
case reflect.String:
|
||||||
|
{
|
||||||
|
v := reflect.ValueOf(val)
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func StrToSimplePtrReflectValue(val string, kind reflect.Kind) *reflect.Value {
|
||||||
|
result := reflect.Value{}
|
||||||
|
switch kind {
|
||||||
|
case reflect.Bool:
|
||||||
|
{
|
||||||
|
v := val == "1" || val == "true"
|
||||||
|
result = reflect.ValueOf(&v)
|
||||||
|
return &result
|
||||||
|
}
|
||||||
|
case reflect.Int:
|
||||||
|
{
|
||||||
|
v := int(ToInt64(val))
|
||||||
|
result = reflect.ValueOf(&v)
|
||||||
|
return &result
|
||||||
|
}
|
||||||
|
case reflect.Int8:
|
||||||
|
{
|
||||||
|
v := int8(ToInt64(val))
|
||||||
|
result = reflect.ValueOf(&v)
|
||||||
|
return &result
|
||||||
|
}
|
||||||
|
case reflect.Int16:
|
||||||
|
{
|
||||||
|
v := int16(ToInt64(val))
|
||||||
|
result = reflect.ValueOf(&v)
|
||||||
|
return &result
|
||||||
|
}
|
||||||
|
case reflect.Int32:
|
||||||
|
{
|
||||||
|
v := int32(ToInt64(val))
|
||||||
|
result = reflect.ValueOf(&v)
|
||||||
|
return &result
|
||||||
|
}
|
||||||
|
case reflect.Int64:
|
||||||
|
{
|
||||||
|
v := ToInt64(val)
|
||||||
|
result = reflect.ValueOf(&v)
|
||||||
|
return &result
|
||||||
|
}
|
||||||
|
case reflect.Uint:
|
||||||
|
{
|
||||||
|
v := uint(ToInt64(val))
|
||||||
|
result = reflect.ValueOf(&v)
|
||||||
|
return &result
|
||||||
|
}
|
||||||
|
case reflect.Uint8:
|
||||||
|
{
|
||||||
|
v := uint8(ToInt64(val))
|
||||||
|
result = reflect.ValueOf(&v)
|
||||||
|
return &result
|
||||||
|
}
|
||||||
|
case reflect.Uint16:
|
||||||
|
{
|
||||||
|
v := uint16(ToInt64(val))
|
||||||
|
result = reflect.ValueOf(&v)
|
||||||
|
return &result
|
||||||
|
}
|
||||||
|
case reflect.Uint32:
|
||||||
|
{
|
||||||
|
v := uint32(ToInt64(val))
|
||||||
|
result = reflect.ValueOf(&v)
|
||||||
|
return &result
|
||||||
|
}
|
||||||
|
case reflect.Uint64:
|
||||||
|
{
|
||||||
|
v := uint64(ToInt64(val))
|
||||||
|
result = reflect.ValueOf(&v)
|
||||||
|
return &result
|
||||||
|
}
|
||||||
|
case reflect.Float32:
|
||||||
|
{
|
||||||
|
v := float32(ToFloat64(val))
|
||||||
|
result = reflect.ValueOf(&v)
|
||||||
|
return &result
|
||||||
|
}
|
||||||
|
case reflect.Float64:
|
||||||
|
{
|
||||||
|
v := float64(ToFloat64(val))
|
||||||
|
result = reflect.ValueOf(&v)
|
||||||
|
return &result
|
||||||
|
}
|
||||||
|
case reflect.String:
|
||||||
|
{
|
||||||
|
v := val
|
||||||
|
result = reflect.ValueOf(&v)
|
||||||
|
return &result
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
142
strutils.go
142
strutils.go
@ -1,6 +1,144 @@
|
|||||||
package q5
|
package q5
|
||||||
|
|
||||||
func Test()(a string) {
|
import (
|
||||||
return "testa"
|
"crypto/md5"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
|
"hash/crc32"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
JSON_NONE = 0
|
||||||
|
JSON_ARRAY = iota
|
||||||
|
JSON_OBJECT = iota
|
||||||
|
)
|
||||||
|
|
||||||
|
func Md5Str(data string) string {
|
||||||
|
h := md5.New()
|
||||||
|
h.Write([]byte(data))
|
||||||
|
return hex.EncodeToString(h.Sum(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Base64Encode(data string) string {
|
||||||
|
strbytes := []byte(data)
|
||||||
|
encoded := base64.StdEncoding.EncodeToString(strbytes)
|
||||||
|
return encoded
|
||||||
|
}
|
||||||
|
|
||||||
|
func Base64Decode(data string) (string, error) {
|
||||||
|
decoded, err := base64.StdEncoding.DecodeString(data)
|
||||||
|
return string(decoded), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func Crc32(data string) uint32 {
|
||||||
|
ieee := crc32.NewIEEE()
|
||||||
|
io.WriteString(ieee, data)
|
||||||
|
|
||||||
|
code := ieee.Sum32()
|
||||||
|
return code
|
||||||
|
}
|
||||||
|
|
||||||
|
func JsonStrType(data string) int32 {
|
||||||
|
arrayIdx := strings.IndexByte(data, '[')
|
||||||
|
objectIdx := strings.IndexByte(data, '{')
|
||||||
|
if arrayIdx < 0 && objectIdx < 0 {
|
||||||
|
return JSON_NONE
|
||||||
|
} else {
|
||||||
|
if arrayIdx < 0 {
|
||||||
|
return JSON_OBJECT
|
||||||
|
}
|
||||||
|
if objectIdx < 0 {
|
||||||
|
return JSON_ARRAY
|
||||||
|
}
|
||||||
|
if arrayIdx < objectIdx {
|
||||||
|
return JSON_ARRAY
|
||||||
|
} else {
|
||||||
|
return JSON_OBJECT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func EncodeJson(p interface{}) string {
|
||||||
|
if jsonBytes, err := json.Marshal(p); err == nil {
|
||||||
|
return string(jsonBytes)
|
||||||
|
} else {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DecodeJson(data string, p interface{}) error {
|
||||||
|
err := json.Unmarshal([]byte(data), &p)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func StrSplit(s string, sep string) []string {
|
||||||
|
return strings.Split(s, sep)
|
||||||
|
}
|
||||||
|
|
||||||
|
func StrContains(s string, substr string) bool {
|
||||||
|
return strings.Contains(s, substr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ConvertUpperCamelCase(name string) string {
|
||||||
|
newName := ""
|
||||||
|
preIs_ := false
|
||||||
|
for i := 0; i < len(name); i++ {
|
||||||
|
if i == 0 {
|
||||||
|
newName += strings.ToUpper(name[i : i+1])
|
||||||
|
preIs_ = name[i] == '_'
|
||||||
|
} else {
|
||||||
|
if preIs_ {
|
||||||
|
if name[i] != '_' {
|
||||||
|
newName += strings.ToUpper(name[i : i+1])
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if name[i] != '_' {
|
||||||
|
newName += name[i : i+1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
preIs_ = name[i] == '_'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newName
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewEmptyStrPtr() *string {
|
||||||
|
tmpStr := ""
|
||||||
|
return &tmpStr
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsPureNumber(str string) bool {
|
||||||
|
for i := 0; i < len(str); i++ {
|
||||||
|
if !(str[i] >= '0' && str[i] <= '9') {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenFieldKvEmptyAsNull(key string, val string) []string {
|
||||||
|
if val == "" {
|
||||||
|
return []string{"!" + key, "NULL"}
|
||||||
|
} else {
|
||||||
|
return []string{key, val}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsWeb3ZeroAddress(address string) bool {
|
||||||
|
return address == "0x0000000000000000000000000000000000000000"
|
||||||
|
}
|
||||||
|
|
||||||
|
func BigIntStrCmp(a string, b string) int {
|
||||||
|
if len(a) == len(b) {
|
||||||
|
return strings.Compare(a, b)
|
||||||
|
} else {
|
||||||
|
if len(a) < len(b) {
|
||||||
|
return -1
|
||||||
|
} else {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
88
sync.go
Normal file
88
sync.go
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
package q5
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ConcurrentMap[T1 string | int | int32 | int64, T2 any] struct {
|
||||||
|
kvHash sync.Map
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ConcurrentMap[T1, T2]) CompareAndDelete(key T1, old *T2) bool {
|
||||||
|
return this.kvHash.CompareAndDelete(key, old)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ConcurrentMap[T1, T2]) CompareAndSwap(key T1, old T2, new T2) bool {
|
||||||
|
return this.kvHash.CompareAndSwap(key, old, new)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ConcurrentMap[T1, T2]) Delete(key T1) {
|
||||||
|
this.kvHash.Delete(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ConcurrentMap[T1, T2]) Load(key T1) (*T2, bool) {
|
||||||
|
value, ok := this.kvHash.Load(key)
|
||||||
|
if ok {
|
||||||
|
tmpValue := value.(T2)
|
||||||
|
return &tmpValue, ok
|
||||||
|
} else {
|
||||||
|
return nil, ok
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ConcurrentMap[T1, T2]) LoadAndDelete(key T1) (*T2, bool) {
|
||||||
|
value, loaded := this.kvHash.LoadAndDelete(key)
|
||||||
|
if loaded {
|
||||||
|
tmpValue := value.(T2)
|
||||||
|
return &tmpValue, loaded
|
||||||
|
} else {
|
||||||
|
return nil, loaded
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ConcurrentMap[T1, T2]) LoadOrStore(key T1, value T2) (*T2, bool) {
|
||||||
|
actual, loaded := this.kvHash.LoadOrStore(key, value)
|
||||||
|
if loaded {
|
||||||
|
tmpActual := actual.(T2)
|
||||||
|
return &tmpActual, loaded
|
||||||
|
} else {
|
||||||
|
return nil, loaded
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ConcurrentMap[T1, T2]) Range(f func(key T1, value T2) bool) {
|
||||||
|
this.kvHash.Range(func (key, value interface{}) bool {
|
||||||
|
return f(key.(T1), value.(T2))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ConcurrentMap[T1, T2]) GetSize() int {
|
||||||
|
var size int
|
||||||
|
this.kvHash.Range(func (key, value interface{}) bool {
|
||||||
|
size += 1
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ConcurrentMap[T1, T2]) Store(key T1, value T2) {
|
||||||
|
this.kvHash.Store(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ConcurrentMap[T1, T2]) Swap(key T1, value T2) (*T2, bool) {
|
||||||
|
previous, loaded := this.kvHash.Swap(key, value)
|
||||||
|
if loaded {
|
||||||
|
tmpPrevious := previous.(T2)
|
||||||
|
return &tmpPrevious, loaded
|
||||||
|
} else {
|
||||||
|
return nil, loaded
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AtomicStoreInt64WhenGreater(srcVal *int64, trgVal *int64) {
|
||||||
|
tmpVal := atomic.LoadInt64(srcVal)
|
||||||
|
if tmpVal > *trgVal {
|
||||||
|
atomic.StoreInt64(trgVal, tmpVal)
|
||||||
|
}
|
||||||
|
}
|
381
sysutils.go
Normal file
381
sysutils.go
Normal file
@ -0,0 +1,381 @@
|
|||||||
|
package q5
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"hash/crc32"
|
||||||
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetDaySeconds(seconds int64, timeZone int64) int64 {
|
||||||
|
return ((seconds+timeZone*3600)/3600/24)*3600*24 - 3600*timeZone
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetYesterDaySeconds(seconds int64, timeZone int64) int64 {
|
||||||
|
return ((seconds+timeZone*3600)/3600/24)*3600*24 - 3600*timeZone
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTickCount() int64 {
|
||||||
|
return time.Now().UnixNano() / 1e6
|
||||||
|
}
|
||||||
|
|
||||||
|
func MkUInt16(b1 byte, b2 byte) uint16 {
|
||||||
|
return uint16(b1) + (uint16(b2) << 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MkUInt32(b1 byte, b2 byte, b3 byte, b4 byte) uint32 {
|
||||||
|
return uint32(b1) +
|
||||||
|
(uint32(b2) << 8) +
|
||||||
|
(uint32(b3) << 16) +
|
||||||
|
(uint32(b4) << 24)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MkInt64(lo32 int32, hi32 int32) int64 {
|
||||||
|
return int64(lo32) + (int64(hi32) << 32)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Request(r *http.Request, name string) string {
|
||||||
|
if r.Form == nil {
|
||||||
|
r.ParseForm()
|
||||||
|
}
|
||||||
|
if vs, ok := r.Form[name]; ok {
|
||||||
|
if len(vs) > 0 {
|
||||||
|
return vs[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func Response(w *http.ResponseWriter, data string) {
|
||||||
|
(*w).Write([]byte(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
func ResponseOk(w *http.ResponseWriter) {
|
||||||
|
(*w).Write([]byte(`{"errcode":0, "errmsg":""}`))
|
||||||
|
}
|
||||||
|
|
||||||
|
func ResponseErr(w *http.ResponseWriter, errCode int32, errMsg string) {
|
||||||
|
rspObj := map[string]interface{}{}
|
||||||
|
rspObj["errcode"] = errCode
|
||||||
|
rspObj["errmsg"] = errMsg
|
||||||
|
jsonObj, _ := json.Marshal(rspObj)
|
||||||
|
Response(w, string(jsonObj))
|
||||||
|
}
|
||||||
|
|
||||||
|
func ResponseInt32Ok(w *http.ResponseWriter, key string, val int32) {
|
||||||
|
(*w).Write([]byte(fmt.Sprintf(`{"errcode":0, "errmsg":"", "%s":%d}`, key, val)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPostBody(r *http.Request) string {
|
||||||
|
body, err := ioutil.ReadAll(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return string(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetRequestRemoteAddr(r *http.Request) string {
|
||||||
|
remoteAddr := r.RemoteAddr
|
||||||
|
if ip := r.Header.Get("X-Real-Ip"); ip != "" {
|
||||||
|
remoteAddr = ip
|
||||||
|
} else if ip = r.Header.Get("X-Forwarded-For"); ip != "" {
|
||||||
|
remoteAddr = ip
|
||||||
|
} else {
|
||||||
|
remoteAddr, _, _ = net.SplitHostPort(remoteAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if remoteAddr == "::1" {
|
||||||
|
remoteAddr = "127.0.0.1"
|
||||||
|
}
|
||||||
|
|
||||||
|
return remoteAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
func ForceCreateDir(dir string) bool {
|
||||||
|
os.MkdirAll(dir, os.ModePerm)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsNumberType(v interface{}) bool {
|
||||||
|
switch reflect.TypeOf(v).Kind() {
|
||||||
|
case
|
||||||
|
reflect.Int,
|
||||||
|
reflect.Int8,
|
||||||
|
reflect.Int16,
|
||||||
|
reflect.Int32,
|
||||||
|
reflect.Int64,
|
||||||
|
reflect.Uint8,
|
||||||
|
reflect.Uint16,
|
||||||
|
reflect.Uint32,
|
||||||
|
reflect.Uint64,
|
||||||
|
reflect.Float32,
|
||||||
|
reflect.Float64:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func FormatUnixDateTime(sec int64, loc *time.Location) string {
|
||||||
|
strTime := time.Unix(sec, 0).In(loc).Format("2006-01-02 15:04:05")
|
||||||
|
return strTime
|
||||||
|
}
|
||||||
|
|
||||||
|
func FormatUnixDate(sec int64, loc *time.Location) string {
|
||||||
|
strTime := time.Unix(sec, 0).In(loc).Format("2006-01-02")
|
||||||
|
return strTime
|
||||||
|
}
|
||||||
|
|
||||||
|
func FormatUnixDateEx(sec int64, loc *time.Location) string {
|
||||||
|
strTime := time.Unix(sec, 0).In(loc).Format("20060102")
|
||||||
|
return strTime
|
||||||
|
}
|
||||||
|
|
||||||
|
func HasBitFlag(val int64, bitNum int32) bool {
|
||||||
|
if bitNum < 0 || bitNum > 63 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
mask := int64(1) << bitNum
|
||||||
|
return (val & mask) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetBitFlag(val *int64, bitNum int32) {
|
||||||
|
if bitNum < 0 || bitNum > 63 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
*val |= int64(1) << bitNum
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnSetBitFlag(val *int64, bitNum int32) {
|
||||||
|
if bitNum < 0 || bitNum > 63 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
*val &= ^(int64(1) << bitNum)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetLocalIP() string {
|
||||||
|
conn, err := net.Dial("udp", "8.8.8.8:80")
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
localAddr := conn.LocalAddr().(*net.UDPAddr)
|
||||||
|
return localAddr.IP.String()
|
||||||
|
|
||||||
|
//interfaces, err := net.Interfaces()
|
||||||
|
//if err != nil {
|
||||||
|
// panic(err)
|
||||||
|
//}
|
||||||
|
//ipList := []string{}
|
||||||
|
//for _, iface := range interfaces {
|
||||||
|
// if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagLoopback != 0 {
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
// addrs, err := iface.Addrs()
|
||||||
|
// if err != nil {
|
||||||
|
// panic(err)
|
||||||
|
// }
|
||||||
|
// for _, addr := range addrs {
|
||||||
|
// ipnet, ok := addr.(*net.IPNet)
|
||||||
|
// if !ok || ipnet.IP.IsLoopback() {
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
// if ipnet.IP.To4() != nil {
|
||||||
|
// ipList = append(ipList, ipnet.IP.String())
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//if len(ipList) != 1 {
|
||||||
|
// panic("GetLocalIP error")
|
||||||
|
//} else {
|
||||||
|
// return ipList[0]
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSlice[T any](s *[]T, len int32, cap int32) {
|
||||||
|
*s = make([]T, len, cap)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSliceElement[T any](s *[]T) *T {
|
||||||
|
v := new(T)
|
||||||
|
*s = append(*s, *v)
|
||||||
|
return &(*s)[len(*s)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func AppendSlice[T any](s *[]T, val T) {
|
||||||
|
*s = append(*s, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTypeName(v interface{}) string {
|
||||||
|
return reflect.TypeOf(v).String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func PrintCallStack() {
|
||||||
|
// 获取当前函数的调用者信息
|
||||||
|
pc, file, line, ok := runtime.Caller(1)
|
||||||
|
if !ok {
|
||||||
|
fmt.Println("runtime.Caller error")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
funcName := runtime.FuncForPC(pc).Name()
|
||||||
|
fmt.Printf("Function: %s\nFile: %s\nLine: %d\n", funcName, file, line)
|
||||||
|
|
||||||
|
// 使用Stack打印完整的调用栈信息,可以用于debug
|
||||||
|
buf := make([]byte, 1024)
|
||||||
|
for {
|
||||||
|
n := runtime.Stack(buf, false)
|
||||||
|
if n < len(buf) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
buf = make([]byte, 2*len(buf))
|
||||||
|
}
|
||||||
|
fmt.Println(string(buf))
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetCallStack() string {
|
||||||
|
// 获取当前函数的调用者信息
|
||||||
|
//pc, file, line, ok := runtime.Caller(1)
|
||||||
|
_, _, _, ok := runtime.Caller(1)
|
||||||
|
if !ok {
|
||||||
|
fmt.Println("runtime.Caller error")
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
//funcName := runtime.FuncForPC(pc).Name()
|
||||||
|
//fmt.Printf("Function: %s\nFile: %s\nLine: %d\n", funcName, file, line)
|
||||||
|
|
||||||
|
// 使用Stack打印完整的调用栈信息,可以用于debug
|
||||||
|
buf := make([]byte, 1024)
|
||||||
|
for {
|
||||||
|
n := runtime.Stack(buf, false)
|
||||||
|
if n < len(buf) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
buf = make([]byte, 2*len(buf))
|
||||||
|
}
|
||||||
|
return string(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CalcCrc32(data string) uint32 {
|
||||||
|
tbl := crc32.MakeTable(crc32.Castagnoli)
|
||||||
|
c := crc32.New(tbl)
|
||||||
|
|
||||||
|
if _, err := c.Write([]byte(data)); err != nil {
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Sum32()
|
||||||
|
}
|
||||||
|
|
||||||
|
func SmartParseTimeToMills(timeStr string) int64 {
|
||||||
|
if IsPureNumber(timeStr) {
|
||||||
|
return ToInt64(timeStr) * 1000
|
||||||
|
}
|
||||||
|
if StrContains(timeStr, "T") {
|
||||||
|
t, err := time.Parse(time.RFC3339, timeStr)
|
||||||
|
if err == nil {
|
||||||
|
return t.UnixNano() / int64(time.Millisecond)
|
||||||
|
}
|
||||||
|
} else if StrContains(timeStr, ".") {
|
||||||
|
const layout = "2006-01-02 15:04:05.000"
|
||||||
|
if len(timeStr) > len(layout) {
|
||||||
|
timeStr = timeStr[0:len(layout)]
|
||||||
|
}
|
||||||
|
t, err := time.Parse(layout, timeStr)
|
||||||
|
if err == nil {
|
||||||
|
return t.UnixNano() / int64(time.Millisecond)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const layout = "2006-01-02 15:04:05"
|
||||||
|
t, err := time.Parse(layout, timeStr)
|
||||||
|
if err == nil {
|
||||||
|
return t.UnixNano() / int64(time.Millisecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadFileAsString(fileName string) (string, error) {
|
||||||
|
if f, err := os.Open(fileName); err == nil {
|
||||||
|
data, err1 := ioutil.ReadAll(bufio.NewReader(f))
|
||||||
|
return string(data), err1
|
||||||
|
} else {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSyncMapSize(m sync.Map) int {
|
||||||
|
var size int
|
||||||
|
m.Range(func(key, value interface{}) bool {
|
||||||
|
size++
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
|
||||||
|
func MapClone(m map[string]interface{}) map[string]interface{} {
|
||||||
|
result := map[string]interface{}{}
|
||||||
|
for k, v := range m {
|
||||||
|
result[k] = v
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func AdjustRangeValue[T int | int32 | int64 | float32 | float64](value T, minV T, maxV T) T {
|
||||||
|
if value < minV {
|
||||||
|
value = minV
|
||||||
|
}
|
||||||
|
if value > maxV {
|
||||||
|
value = maxV
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateCondTimer(ch chan int64, cond *sync.Cond, initSeconds int64) {
|
||||||
|
waitSecond := initSeconds
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case waitSecond = <-ch:
|
||||||
|
if waitSecond < 10 {
|
||||||
|
waitSecond = 10
|
||||||
|
}
|
||||||
|
case <-time.After(time.Second * time.Duration(waitSecond)):
|
||||||
|
cond.Broadcast()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExcUntilOk(cb func() bool) {
|
||||||
|
for !cb() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadTextFile(fileName string) (string, error) {
|
||||||
|
if f, err := os.Open(fileName); err == nil {
|
||||||
|
data, err := ioutil.ReadAll(bufio.NewReader(f))
|
||||||
|
return string(data), err
|
||||||
|
} else {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsDebug() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func PowInt64(base int64, exponent int64) int64 {
|
||||||
|
var result int64 = 1
|
||||||
|
var i int64 = 0
|
||||||
|
for ; i < exponent; i++ {
|
||||||
|
result *= base
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
389
timer.go
Normal file
389
timer.go
Normal file
@ -0,0 +1,389 @@
|
|||||||
|
package q5
|
||||||
|
|
||||||
|
const CONFIG_BASE_SMALL = false
|
||||||
|
const TVN_BITS = 6
|
||||||
|
const TVR_BITS = 8
|
||||||
|
const TVN_SIZE = 1 << TVN_BITS
|
||||||
|
const TVR_SIZE = 1 << TVR_BITS
|
||||||
|
const TVN_MASK = TVN_SIZE - 1
|
||||||
|
const TVR_MASK = TVR_SIZE - 1
|
||||||
|
|
||||||
|
const (
|
||||||
|
TIMEOUT_TIMER = 0
|
||||||
|
INTERVAL_TIMER = iota
|
||||||
|
)
|
||||||
|
|
||||||
|
type XTimerDestoryHandleNode struct {
|
||||||
|
entry ListHead
|
||||||
|
cb func()
|
||||||
|
}
|
||||||
|
|
||||||
|
type XTimer struct {
|
||||||
|
freeTimerNum int32
|
||||||
|
freeTimerList ListHead
|
||||||
|
runningTimer *XTimerList
|
||||||
|
timerTick int64
|
||||||
|
getTickCount func(interface{}) int64
|
||||||
|
context interface{}
|
||||||
|
cacheTimerNum int32
|
||||||
|
tv1 [TVR_SIZE]ListHead
|
||||||
|
tv2 [TVN_SIZE]ListHead
|
||||||
|
tv3 [TVN_SIZE]ListHead
|
||||||
|
tv4 [TVN_SIZE]ListHead
|
||||||
|
tv5 [TVN_SIZE]ListHead
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) Init(
|
||||||
|
getTickCount func(interface{}) int64,
|
||||||
|
context interface{},
|
||||||
|
gcTime int32,
|
||||||
|
cacheTimerNum int32) {
|
||||||
|
initListHeadFunc := func(head *ListHead) {
|
||||||
|
head.Init(nil)
|
||||||
|
}
|
||||||
|
initListHeadFunc(&this.freeTimerList)
|
||||||
|
for i := 0; i < len(this.tv1); i++ {
|
||||||
|
initListHeadFunc(&this.tv1[i])
|
||||||
|
}
|
||||||
|
for i := 0; i < len(this.tv2); i++ {
|
||||||
|
initListHeadFunc(&this.tv2[i])
|
||||||
|
}
|
||||||
|
for i := 0; i < len(this.tv3); i++ {
|
||||||
|
initListHeadFunc(&this.tv3[i])
|
||||||
|
}
|
||||||
|
for i := 0; i < len(this.tv4); i++ {
|
||||||
|
initListHeadFunc(&this.tv4[i])
|
||||||
|
}
|
||||||
|
for i := 0; i < len(this.tv5); i++ {
|
||||||
|
initListHeadFunc(&this.tv5[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
this.timerTick = getTickCount(context)
|
||||||
|
this.context = context
|
||||||
|
this.getTickCount = getTickCount
|
||||||
|
this.cacheTimerNum = cacheTimerNum
|
||||||
|
this.SetInterval(gcTime, this.gcTimerFunc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) UnInit() {
|
||||||
|
this.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) clear() {
|
||||||
|
freeTimerFunc := func(head *ListHead) {
|
||||||
|
for !head.Empty() {
|
||||||
|
timerList := head.FirstEntry().(*XTimerList)
|
||||||
|
this.detachTimer(timerList)
|
||||||
|
if !timerList.attachEntry.Empty() {
|
||||||
|
timerList.attachEntry.DelInit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
freeTimerFunc(&this.freeTimerList)
|
||||||
|
for i := 0; i < len(this.tv1); i++ {
|
||||||
|
freeTimerFunc(&this.tv1[i])
|
||||||
|
}
|
||||||
|
for i := 0; i < len(this.tv2); i++ {
|
||||||
|
freeTimerFunc(&this.tv2[i])
|
||||||
|
}
|
||||||
|
for i := 0; i < len(this.tv3); i++ {
|
||||||
|
freeTimerFunc(&this.tv3[i])
|
||||||
|
}
|
||||||
|
for i := 0; i < len(this.tv4); i++ {
|
||||||
|
freeTimerFunc(&this.tv4[i])
|
||||||
|
}
|
||||||
|
for i := 0; i < len(this.tv5); i++ {
|
||||||
|
freeTimerFunc(&this.tv5[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) Update() {
|
||||||
|
for this.getTickCount(this.context) >= this.timerTick {
|
||||||
|
index := uint32(this.timerTick & TVR_MASK)
|
||||||
|
|
||||||
|
if index == 0 &&
|
||||||
|
this.cascade(&this.tv2, this.getTimerIndex(0)) == 0 &&
|
||||||
|
this.cascade(&this.tv3, this.getTimerIndex(1)) == 0 &&
|
||||||
|
this.cascade(&this.tv4, this.getTimerIndex(2)) == 0 {
|
||||||
|
this.cascade(&this.tv5, this.getTimerIndex(3))
|
||||||
|
}
|
||||||
|
this.timerTick++
|
||||||
|
|
||||||
|
var workList ListHead
|
||||||
|
this.tv1[index].ReplaceInit(&workList)
|
||||||
|
for !workList.Empty() {
|
||||||
|
timer := workList.FirstEntry().(*XTimerList)
|
||||||
|
this.runningTimer = timer
|
||||||
|
timer.cb(TIMER_EXEC_EVENT, nil)
|
||||||
|
if this.runningTimer != nil {
|
||||||
|
switch this.runningTimer.timerType {
|
||||||
|
case TIMEOUT_TIMER:
|
||||||
|
this.internalDelete(timer, false, true)
|
||||||
|
case INTERVAL_TIMER:
|
||||||
|
this.internalModifyTime(timer, timer.expireTime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.runningTimer = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) NewTimerAttacher() *XTimerAttacher {
|
||||||
|
attacher := new(XTimerAttacher)
|
||||||
|
attacher.timer = this
|
||||||
|
attacher.timers.Init(nil)
|
||||||
|
return attacher
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) SetTimeout(expireTime int32, cb TimerCb) {
|
||||||
|
this.internalSetTimeout(expireTime, cb, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) SetTimeoutEx(expireTime int32, cb TimerCb, attacher *XTimerAttacher) {
|
||||||
|
this.internalSetTimeout(expireTime, cb, attacher, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) SetTimeoutWp(expireTime int32, cb TimerCb) *XTimerWp {
|
||||||
|
var wp *XTimerWp
|
||||||
|
this.internalSetTimeout(expireTime, cb, nil, &wp)
|
||||||
|
return wp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) SetTimeoutExWp(expireTime int32, cb TimerCb, attacher *XTimerAttacher) *XTimerWp {
|
||||||
|
var wp *XTimerWp
|
||||||
|
this.internalSetTimeout(expireTime, cb, attacher, &wp)
|
||||||
|
return wp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) SetInterval(expireTime int32, cb TimerCb) {
|
||||||
|
this.internalSetInterval(expireTime, cb, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) SetIntervalEx(expireTime int32, cb TimerCb, attacher *XTimerAttacher) {
|
||||||
|
this.internalSetInterval(expireTime, cb, attacher, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) SetIntervalWp(expireTime int32, cb TimerCb) *XTimerWp {
|
||||||
|
var wp *XTimerWp
|
||||||
|
this.internalSetInterval(expireTime, cb, nil, &wp)
|
||||||
|
return wp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) SetIntervalExWp(expireTime int32, cb TimerCb, attacher *XTimerAttacher) *XTimerWp {
|
||||||
|
var wp *XTimerWp
|
||||||
|
this.internalSetInterval(expireTime, cb, attacher, &wp)
|
||||||
|
return wp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) internalSetTimeout(expireTime int32, cb TimerCb, attacher *XTimerAttacher, wpPp **XTimerWp) {
|
||||||
|
timer := this.newTimerList()
|
||||||
|
timer.initTimerList(this, TIMEOUT_TIMER, expireTime, cb)
|
||||||
|
if attacher != nil {
|
||||||
|
attacher.timers.AddTail(&timer.attachEntry)
|
||||||
|
}
|
||||||
|
this.internalModifyTime(timer, expireTime)
|
||||||
|
if wpPp != nil {
|
||||||
|
timer.wp = &XTimerWp{
|
||||||
|
timer: timer,
|
||||||
|
}
|
||||||
|
*wpPp = timer.wp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) internalSetInterval(expireTime int32, cb TimerCb, attacher *XTimerAttacher, wpPp **XTimerWp) {
|
||||||
|
timer := this.newTimerList()
|
||||||
|
timer.initTimerList(this, INTERVAL_TIMER, expireTime, cb)
|
||||||
|
if attacher != nil {
|
||||||
|
attacher.timers.AddTail(&timer.attachEntry)
|
||||||
|
}
|
||||||
|
this.internalModifyTime(timer, expireTime)
|
||||||
|
if wpPp != nil {
|
||||||
|
timer.wp = &XTimerWp{
|
||||||
|
timer: timer,
|
||||||
|
}
|
||||||
|
*wpPp = timer.wp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) ModifyTimer(timerWp *XTimerWp, expireTime int32) {
|
||||||
|
if timerWp.Expired() {
|
||||||
|
panic("Xtimer ModifyTimer expired timer")
|
||||||
|
}
|
||||||
|
this.internalModifyTime(timerWp.timer, expireTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) Delete(timerWp *XTimerWp) {
|
||||||
|
if timerWp.Expired() {
|
||||||
|
panic("Xtimer Delete expired timer")
|
||||||
|
}
|
||||||
|
this.internalDelete(timerWp.timer, false, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) GetRemainTime(timerWp *XTimerWp) int64 {
|
||||||
|
if timerWp.Expired() {
|
||||||
|
panic("Xtimer GetRemainTime expired timer")
|
||||||
|
}
|
||||||
|
return this.internalGetRemainTime(timerWp.timer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) internalGetRemainTime(timer *XTimerList) int64 {
|
||||||
|
remainTime := timer.expires - this.getTickCount(this.context)
|
||||||
|
if remainTime < 0 {
|
||||||
|
return 0
|
||||||
|
} else {
|
||||||
|
return remainTime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) GetIdleTime() int64 {
|
||||||
|
var idleTime int64 = 1
|
||||||
|
for i := (this.timerTick & TVR_MASK); i < TVR_SIZE; i++ {
|
||||||
|
if !this.tv1[i].Empty() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
idleTime++
|
||||||
|
}
|
||||||
|
return idleTime
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) detachTimer(timerList *XTimerList) {
|
||||||
|
if !timerList.entry.Empty() {
|
||||||
|
timerList.entry.DelInit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) addToFreeList(timerList *XTimerList) {
|
||||||
|
timerList.reset()
|
||||||
|
this.freeTimerList.AddTail(&timerList.entry)
|
||||||
|
this.freeTimerNum++
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) cascade(tv *[TVN_SIZE]ListHead, index uint32) uint32 {
|
||||||
|
var cascadeList ListHead
|
||||||
|
tv[index].ReplaceInit(&cascadeList)
|
||||||
|
|
||||||
|
if !cascadeList.Empty() {
|
||||||
|
pos := cascadeList.next
|
||||||
|
next := pos.next
|
||||||
|
for pos != &cascadeList {
|
||||||
|
this.internalAddTimer(pos.data.(*XTimerList))
|
||||||
|
pos = next
|
||||||
|
next = pos.next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) internalAddTimer(timerList *XTimerList) {
|
||||||
|
timerList.entry.data = timerList
|
||||||
|
expires := timerList.expires
|
||||||
|
idx := expires - this.timerTick
|
||||||
|
var vec *ListHead
|
||||||
|
var index uint32
|
||||||
|
|
||||||
|
if idx < 0 {
|
||||||
|
index = (uint32)(this.timerTick & TVR_MASK)
|
||||||
|
vec = &this.tv1[index]
|
||||||
|
} else if idx < TVR_SIZE {
|
||||||
|
index = (uint32)(expires & TVR_MASK)
|
||||||
|
vec = &this.tv1[index]
|
||||||
|
} else if idx < (1 << (TVR_BITS + TVN_BITS)) {
|
||||||
|
index = (uint32)((expires >> TVR_BITS) & TVN_MASK)
|
||||||
|
vec = &this.tv2[index]
|
||||||
|
} else if idx < (1 << (TVR_BITS + 2*TVN_BITS)) {
|
||||||
|
index = (uint32)((expires >> (TVR_BITS + 1*TVN_BITS)) & TVN_MASK)
|
||||||
|
vec = &this.tv3[index]
|
||||||
|
} else if idx < (1 << (TVR_BITS + 3*TVN_BITS)) {
|
||||||
|
index = (uint32)((expires >> (TVR_BITS + 2*TVN_BITS)) & TVN_MASK)
|
||||||
|
vec = &this.tv4[index]
|
||||||
|
} else {
|
||||||
|
index = (uint32)((expires >> (TVR_BITS + 3*TVN_BITS)) & TVN_MASK)
|
||||||
|
vec = &this.tv5[index]
|
||||||
|
}
|
||||||
|
vec.AddTail(&timerList.entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) getTimerIndex(index uint32) uint32 {
|
||||||
|
return (uint32)((this.timerTick >> (TVR_BITS + index*TVN_BITS)) & TVN_MASK)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) newTimerList() *XTimerList {
|
||||||
|
if !this.freeTimerList.Empty() {
|
||||||
|
timerList := this.freeTimerList.FirstEntry().(*XTimerList)
|
||||||
|
this.freeTimerNum--
|
||||||
|
return timerList
|
||||||
|
} else {
|
||||||
|
timerList := new(XTimerList)
|
||||||
|
timerList.init()
|
||||||
|
return timerList
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) gcTimerFunc(ev int32, args *Args) {
|
||||||
|
if ev == TIMER_EXEC_EVENT {
|
||||||
|
count := 0
|
||||||
|
for !this.freeTimerList.Empty() && this.freeTimerNum > this.cacheTimerNum {
|
||||||
|
timerList := this.freeTimerList.FirstEntry().(*XTimerList)
|
||||||
|
timerList.entry.DelInit()
|
||||||
|
this.freeTimerNum--
|
||||||
|
count++
|
||||||
|
if count > 1000 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) internalDelete(timer *XTimerList, isDestory bool, toFreeList bool) {
|
||||||
|
if timer == nil {
|
||||||
|
panic("Xtimer.internalDelete error")
|
||||||
|
}
|
||||||
|
if this.runningTimer == timer {
|
||||||
|
this.runningTimer = nil
|
||||||
|
}
|
||||||
|
this.detachTimer(timer)
|
||||||
|
if !timer.attachEntry.Empty() {
|
||||||
|
timer.attachEntry.DelInit()
|
||||||
|
}
|
||||||
|
for !timer.destoryHandleList.Empty() {
|
||||||
|
handle := timer.destoryHandleList.FirstEntry().(XTimerDestoryHandleNode)
|
||||||
|
handle.entry.DelInit()
|
||||||
|
handle.cb()
|
||||||
|
}
|
||||||
|
if isDestory {
|
||||||
|
timer.cb(TIMER_DESTORY_EVENT, nil)
|
||||||
|
} else {
|
||||||
|
timer.cb(TIMER_DELETE_EVENT, nil)
|
||||||
|
}
|
||||||
|
timer.cb = nil
|
||||||
|
if timer.wp != nil {
|
||||||
|
timer.wp.timer = nil
|
||||||
|
timer.wp = nil
|
||||||
|
}
|
||||||
|
if toFreeList {
|
||||||
|
this.addToFreeList(timer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) internalModifyTime(timer *XTimerList, expireTime int32) {
|
||||||
|
this.detachTimer(timer)
|
||||||
|
timer.expireTime = expireTime
|
||||||
|
timer.expires = this.getTickCount(this.context) + int64(expireTime)
|
||||||
|
this.internalAddTimer(timer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) clearAttacher(attacher *XTimerAttacher) {
|
||||||
|
var workList ListHead
|
||||||
|
attacher.timers.ReplaceInit(&workList)
|
||||||
|
for !workList.Empty() {
|
||||||
|
timer := workList.FirstEntry().(*XTimerList)
|
||||||
|
this.internalDelete(timer, false, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimer) DeleteRunningTimer() {
|
||||||
|
if this.runningTimer != nil {
|
||||||
|
this.internalDelete(this.runningTimer, false, true)
|
||||||
|
this.runningTimer = nil
|
||||||
|
}
|
||||||
|
}
|
60
timerlist.go
Normal file
60
timerlist.go
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
package q5
|
||||||
|
|
||||||
|
type XTimerWp struct {
|
||||||
|
timer *XTimerList
|
||||||
|
}
|
||||||
|
|
||||||
|
type XTimerAttacher struct {
|
||||||
|
timer *XTimer
|
||||||
|
timers ListHead
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimerAttacher) ClearTimers() {
|
||||||
|
this.timer.clearAttacher(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
type XTimerList struct {
|
||||||
|
destoryHandleList ListHead
|
||||||
|
entry ListHead
|
||||||
|
attachEntry ListHead
|
||||||
|
timerType int8
|
||||||
|
expireTime int32
|
||||||
|
expires int64
|
||||||
|
|
||||||
|
cb TimerCb
|
||||||
|
wp *XTimerWp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimerWp) Expired() bool {
|
||||||
|
return this.timer == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimerList) initTimerList(
|
||||||
|
timer interface{},
|
||||||
|
timerType int8,
|
||||||
|
expireTime int32,
|
||||||
|
cb TimerCb) {
|
||||||
|
this.timerType = timerType
|
||||||
|
this.expireTime = expireTime
|
||||||
|
this.cb = cb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimerList) reset() {
|
||||||
|
if !this.entry.Empty() {
|
||||||
|
this.entry.DelInit()
|
||||||
|
}
|
||||||
|
if !this.attachEntry.Empty() {
|
||||||
|
this.attachEntry.DelInit()
|
||||||
|
}
|
||||||
|
this.cb = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimerList) init() {
|
||||||
|
this.entry.Init(this)
|
||||||
|
this.attachEntry.Init(this)
|
||||||
|
this.destoryHandleList.Init(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *XTimerList) Attach(timerAttacher *XTimerAttacher) {
|
||||||
|
timerAttacher.timers.AddTail(&this.attachEntry)
|
||||||
|
}
|
13
types.go
Normal file
13
types.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package q5
|
||||||
|
|
||||||
|
type TimerCb func(int32, *Args)
|
||||||
|
type Args []interface{}
|
||||||
|
|
||||||
|
type Module interface {
|
||||||
|
Init()
|
||||||
|
UnInit()
|
||||||
|
}
|
||||||
|
|
||||||
|
const TIMER_EXEC_EVENT = 1
|
||||||
|
const TIMER_DELETE_EVENT = 2
|
||||||
|
const TIMER_DESTORY_EVENT = 3
|
51
uuid.go
Normal file
51
uuid.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package q5
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const Q5_EPOCH = 1419120000000
|
||||||
|
|
||||||
|
const MACHINE_ID_BIT_NUM = 12
|
||||||
|
const SEQUNCE_ID_BIT_NUM = 10
|
||||||
|
const MAX_MACHINE_ID = (1 << MACHINE_ID_BIT_NUM) - 1
|
||||||
|
const MAX_SEQUNCE_ID = (1 << SEQUNCE_ID_BIT_NUM) - 1
|
||||||
|
|
||||||
|
type Uuid struct {
|
||||||
|
machineId int32
|
||||||
|
sequenceId int32
|
||||||
|
lastGenerateTick int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Uuid) Generate() int64 {
|
||||||
|
var value int64
|
||||||
|
tick := GetTickCount()
|
||||||
|
if tick == this.lastGenerateTick {
|
||||||
|
this.sequenceId++
|
||||||
|
if this.sequenceId >= MAX_SEQUNCE_ID {
|
||||||
|
for tick <= this.lastGenerateTick {
|
||||||
|
time.Sleep(time.Millisecond * 1)
|
||||||
|
tick = GetTickCount()
|
||||||
|
}
|
||||||
|
this.sequenceId = 0
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.sequenceId = 0
|
||||||
|
}
|
||||||
|
this.lastGenerateTick = tick
|
||||||
|
// 保留后41位时间
|
||||||
|
value = (tick - Q5_EPOCH) << 22
|
||||||
|
//中间12位是机器ID
|
||||||
|
value |= int64((int64(this.machineId) & int64(MAX_MACHINE_ID)) << SEQUNCE_ID_BIT_NUM)
|
||||||
|
//最后10位是sequenceID
|
||||||
|
value |= int64(this.sequenceId & MAX_SEQUNCE_ID)
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Uuid) SetMachineId(macId int32) {
|
||||||
|
if macId > MAX_MACHINE_ID || macId < 1 {
|
||||||
|
panic(fmt.Sprintf("Uuid.SetMachineId error %d", macId))
|
||||||
|
}
|
||||||
|
this.machineId = macId
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user