Compare commits
No commits in common. "master" and "v1.0.0" have entirely different histories.
29
algorithm.go
29
algorithm.go
@ -1,29 +0,0 @@
|
|||||||
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
228
convert.go
@ -1,228 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
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
10
go.mod
@ -1,10 +0,0 @@
|
|||||||
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
18
go.sum
@ -1,18 +0,0 @@
|
|||||||
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
120
httpcli.go
@ -1,120 +0,0 @@
|
|||||||
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
137
listhead.go
@ -1,137 +0,0 @@
|
|||||||
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
77
mysql.go
@ -1,77 +0,0 @@
|
|||||||
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
20
password.go
@ -1,20 +0,0 @@
|
|||||||
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
41
queue.go
@ -1,41 +0,0 @@
|
|||||||
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
21
random.go
@ -1,21 +0,0 @@
|
|||||||
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
24
redis.go
@ -1,24 +0,0 @@
|
|||||||
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
200
reflect.go
@ -1,200 +0,0 @@
|
|||||||
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,144 +1,6 @@
|
|||||||
package q5
|
package q5
|
||||||
|
|
||||||
import (
|
func Test()(a string) {
|
||||||
"crypto/md5"
|
return "testa"
|
||||||
"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
88
sync.go
@ -1,88 +0,0 @@
|
|||||||
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
381
sysutils.go
@ -1,381 +0,0 @@
|
|||||||
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
389
timer.go
@ -1,389 +0,0 @@
|
|||||||
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
60
timerlist.go
@ -1,60 +0,0 @@
|
|||||||
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
13
types.go
@ -1,13 +0,0 @@
|
|||||||
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
51
uuid.go
@ -1,51 +0,0 @@
|
|||||||
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