mirror of
https://gitee.com/johng/gf
synced 2026-06-25 01:05:41 +08:00
改进gtype.Set方法,增加Set原子操作返回旧的变量值;改进gcron,增加自定义的Cron管理对象,增加New/Start/Stop方法;TODO++
This commit is contained in:
3
TODO
3
TODO
@ -37,6 +37,9 @@ ghttp.Request增加对输入参数的自动HtmlEncode机制;
|
||||
Cookie设置中文失效问题;
|
||||
ghttp hook回调使用方式在注册路由比较多的时候,优先级可能使得开发者混乱,考虑方式便于管理;
|
||||
使用gconv将slice映射到struct属性上,例如redis hscan的结果集;
|
||||
项目参考:
|
||||
https://github.com/namreg/godown
|
||||
https://github.com/Masterminds/sprig
|
||||
|
||||
|
||||
|
||||
|
||||
@ -30,12 +30,14 @@ func (t *Bool) Clone() *Bool {
|
||||
return NewBool(t.Val())
|
||||
}
|
||||
|
||||
func (t *Bool) Set(value bool) {
|
||||
// 并发安全设置变量值,返回之前的旧值
|
||||
func (t *Bool) Set(value bool) (old bool) {
|
||||
if value {
|
||||
atomic.StoreInt32(&t.val, 1)
|
||||
old = atomic.SwapInt32(&t.val, 1) == 1
|
||||
} else {
|
||||
atomic.StoreInt32(&t.val, 0)
|
||||
old = atomic.SwapInt32(&t.val, 0) == 1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (t *Bool) Val() bool {
|
||||
|
||||
@ -25,8 +25,9 @@ func (t *Byte) Clone() *Byte {
|
||||
return NewByte(t.Val())
|
||||
}
|
||||
|
||||
func (t *Byte) Set(value byte) {
|
||||
atomic.StoreInt32(&t.val, int32(value))
|
||||
// 并发安全设置变量值,返回之前的旧值
|
||||
func (t *Byte) Set(value byte) (old byte) {
|
||||
return byte(atomic.SwapInt32(&t.val, int32(value)))
|
||||
}
|
||||
|
||||
func (t *Byte) Val() byte {
|
||||
|
||||
@ -24,13 +24,14 @@ func (t *Bytes) Clone() *Bytes {
|
||||
return NewBytes(t.Val())
|
||||
}
|
||||
|
||||
func (t *Bytes) Set(value []byte) {
|
||||
func (t *Bytes) Set(value []byte) (old []byte) {
|
||||
old = t.Val()
|
||||
t.val.Store(value)
|
||||
return
|
||||
}
|
||||
|
||||
func (t *Bytes) Val() []byte {
|
||||
s := t.val.Load()
|
||||
if s != nil {
|
||||
if s := t.val.Load(); s != nil {
|
||||
return s.([]byte)
|
||||
}
|
||||
return nil
|
||||
|
||||
@ -26,8 +26,8 @@ func (t *Float32) Clone() *Float32 {
|
||||
return NewFloat32(t.Val())
|
||||
}
|
||||
|
||||
func (t *Float32) Set(value float32) {
|
||||
atomic.StoreUint32(&t.val, float32ToUint32InBits(value) )
|
||||
func (t *Float32) Set(value float32) (old float32) {
|
||||
return uint32ToFloat32InBits(atomic.SwapUint32(&t.val, float32ToUint32InBits(value)))
|
||||
}
|
||||
|
||||
func (t *Float32) Val() float32 {
|
||||
|
||||
@ -26,8 +26,8 @@ func (t *Float64) Clone() *Float64 {
|
||||
return NewFloat64(t.Val())
|
||||
}
|
||||
|
||||
func (t *Float64) Set(value float64) {
|
||||
atomic.StoreUint64(&t.val, float64ToUint64InBits(value) )
|
||||
func (t *Float64) Set(value float64) (old float64) {
|
||||
return uint64ToFloat64InBits(atomic.SwapUint64(&t.val, float64ToUint64InBits(value)))
|
||||
}
|
||||
|
||||
func (t *Float64) Val() float64 {
|
||||
|
||||
@ -25,8 +25,9 @@ func (t *Int) Clone() *Int {
|
||||
return NewInt(t.Val())
|
||||
}
|
||||
|
||||
func (t *Int) Set(value int) {
|
||||
atomic.StoreInt64(&t.val, int64(value))
|
||||
// 并发安全设置变量值,返回之前的旧值
|
||||
func (t *Int) Set(value int) (old int) {
|
||||
return int(atomic.SwapInt64(&t.val, int64(value)))
|
||||
}
|
||||
|
||||
func (t *Int) Val() int {
|
||||
|
||||
@ -25,8 +25,8 @@ func (t *Int32) Clone() *Int32 {
|
||||
return NewInt32(t.Val())
|
||||
}
|
||||
|
||||
func (t *Int32) Set(value int32) {
|
||||
atomic.StoreInt32(&t.val, value)
|
||||
func (t *Int32) Set(value int32) (old int32) {
|
||||
return atomic.SwapInt32(&t.val, value)
|
||||
}
|
||||
|
||||
func (t *Int32) Val() int32 {
|
||||
|
||||
@ -25,8 +25,8 @@ func (t *Int64) Clone() *Int64 {
|
||||
return NewInt64(t.Val())
|
||||
}
|
||||
|
||||
func (t *Int64) Set(value int64) {
|
||||
atomic.StoreInt64(&t.val, value)
|
||||
func (t *Int64) Set(value int64) (old int64) {
|
||||
return atomic.SwapInt64(&t.val, value)
|
||||
}
|
||||
|
||||
func (t *Int64) Val() int64 {
|
||||
|
||||
@ -23,15 +23,17 @@ func NewInterface(value...interface{}) *Interface {
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *Interface) Clone() *Interface{
|
||||
func (t *Interface) Clone() *Interface {
|
||||
return NewInterface(t.Val())
|
||||
}
|
||||
|
||||
func (t *Interface) Set(value interface{}) {
|
||||
func (t *Interface) Set(value interface{}) (old interface{}) {
|
||||
if value == nil {
|
||||
return
|
||||
}
|
||||
old = t.Val()
|
||||
t.val.Store(value)
|
||||
return
|
||||
}
|
||||
|
||||
func (t *Interface) Val() interface{} {
|
||||
|
||||
@ -26,8 +26,10 @@ func (t *String) Clone() *String {
|
||||
return NewString(t.Val())
|
||||
}
|
||||
|
||||
func (t *String) Set(value string) {
|
||||
func (t *String) Set(value string) (old string) {
|
||||
old = t.Val()
|
||||
t.val.Store(value)
|
||||
return
|
||||
}
|
||||
|
||||
func (t *String) Val() string {
|
||||
|
||||
@ -25,8 +25,8 @@ func (t *Uint) Clone() *Uint {
|
||||
return NewUint(t.Val())
|
||||
}
|
||||
|
||||
func (t *Uint) Set(value uint) {
|
||||
atomic.StoreUint64(&t.val, uint64(value))
|
||||
func (t *Uint) Set(value uint) (old uint) {
|
||||
return uint(atomic.SwapUint64(&t.val, uint64(value)))
|
||||
}
|
||||
|
||||
func (t *Uint) Val() uint {
|
||||
|
||||
@ -25,8 +25,8 @@ func (t *Uint32) Clone() *Uint32 {
|
||||
return NewUint32(t.Val())
|
||||
}
|
||||
|
||||
func (t *Uint32) Set(value uint32) {
|
||||
atomic.StoreUint32(&t.val, value)
|
||||
func (t *Uint32) Set(value uint32) (old uint32) {
|
||||
return atomic.SwapUint32(&t.val, value)
|
||||
}
|
||||
|
||||
func (t *Uint32) Val() uint32 {
|
||||
|
||||
@ -25,8 +25,8 @@ func (t *Uint64) Clone() *Uint64 {
|
||||
return NewUint64(t.Val())
|
||||
}
|
||||
|
||||
func (t *Uint64) Set(value uint64) {
|
||||
atomic.StoreUint64(&t.val, value)
|
||||
func (t *Uint64) Set(value uint64) (old uint64) {
|
||||
return atomic.SwapUint64(&t.val, value)
|
||||
}
|
||||
|
||||
func (t *Uint64) Val() uint64 {
|
||||
|
||||
@ -8,107 +8,69 @@
|
||||
package gcron
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"gitee.com/johng/gf/g/container/garray"
|
||||
"gitee.com/johng/gf/g/container/gtype"
|
||||
"gitee.com/johng/gf/g/os/gtime"
|
||||
"gitee.com/johng/gf/third/github.com/robfig/cron"
|
||||
"reflect"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// 定时任务项
|
||||
type Entry struct {
|
||||
Spec string // 注册定时任务时间格式
|
||||
Cmd string // 注册定时任务名称
|
||||
Time *gtime.Time // 注册时间
|
||||
Name string // 定时任务名称
|
||||
cron *cron.Cron // 底层定时管理对象
|
||||
Spec string // 注册定时任务时间格式
|
||||
Cmd string // 注册定时任务名称
|
||||
Time *gtime.Time // 注册时间
|
||||
Name string // 定时任务名称
|
||||
Status *gtype.Int // 定时任务状态(0: 未执行; > 0: 运行中)
|
||||
cron *cron.Cron // 定时任务单独的底层定时管理对象
|
||||
}
|
||||
|
||||
// 定时任务管理对象
|
||||
type Cron struct {
|
||||
cron *cron.Cron // 底层定时管理对象
|
||||
entries *garray.Array // 定时任务注册项
|
||||
status *gtype.Int // 默认定时任务管理对象状态(不带名称的定时任务,0: 未执行; > 0: 运行中)
|
||||
}
|
||||
|
||||
var (
|
||||
// 默认的cron管理对象
|
||||
defaultCron = cron.New()
|
||||
// 当前cron的运行状态(0: 未执行; > 0: 运行中)
|
||||
cronStatus = gtype.NewInt()
|
||||
// 注册定时任务项
|
||||
cronEntries = garray.New(0, 0, true)
|
||||
defaultCron = New()
|
||||
)
|
||||
|
||||
// 创建自定义的定时任务管理对象
|
||||
func New() *Cron {
|
||||
return &Cron {
|
||||
cron : cron.New(),
|
||||
entries : garray.New(0, 0, true),
|
||||
status : gtype.NewInt(),
|
||||
}
|
||||
}
|
||||
|
||||
// 添加执行方法,可以给定名字,以便于后续执行删除
|
||||
func Add(spec string, f func(), name ... string) error {
|
||||
if len(name) > 0 {
|
||||
if Search(name[0]) != nil {
|
||||
return errors.New(fmt.Sprintf(`cron job "%s" already exists`, name[0]))
|
||||
}
|
||||
c := cron.New()
|
||||
if err := c.AddFunc(spec, f); err == nil {
|
||||
cronEntries.Append(Entry{
|
||||
Spec : spec,
|
||||
Cmd : runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name(),
|
||||
Time : gtime.Now(),
|
||||
Name : name[0],
|
||||
cron : c,
|
||||
})
|
||||
go c.Run()
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := defaultCron.AddFunc(spec, f); err == nil {
|
||||
if cronStatus.Add(1) == 1 {
|
||||
go defaultCron.Run()
|
||||
}
|
||||
cronEntries.Append(Entry{
|
||||
Spec : spec,
|
||||
Cmd : runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name(),
|
||||
Time : gtime.Now(),
|
||||
})
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return defaultCron.Add(spec, f, name...)
|
||||
}
|
||||
|
||||
// 检索指定名称的定时任务
|
||||
func Search(name string) *Entry {
|
||||
entry, _ := searchEntry(name)
|
||||
return entry
|
||||
}
|
||||
|
||||
// 检索指定名称的定时任务
|
||||
func searchEntry(name string) (*Entry, int) {
|
||||
entry := (*Entry)(nil)
|
||||
index := -1
|
||||
cronEntries.RLockFunc(func(array []interface{}) {
|
||||
for k, v := range array {
|
||||
e := v.(Entry)
|
||||
if e.Name == name {
|
||||
entry = &e
|
||||
index = k
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
return entry, index
|
||||
return defaultCron.Search(name)
|
||||
}
|
||||
|
||||
// 根据指定名称删除定时任务
|
||||
func Remove(name string) {
|
||||
if entry, index := searchEntry(name); index >= 0 {
|
||||
entry.cron.Stop()
|
||||
cronEntries.Remove(index)
|
||||
}
|
||||
defaultCron.Remove(name)
|
||||
}
|
||||
|
||||
// 获取所有已注册的定时任务项
|
||||
func Entries() []Entry {
|
||||
length := cronEntries.Len()
|
||||
entries := make([]Entry, length)
|
||||
for i := 0; i < length; i++ {
|
||||
entries[i] = cronEntries.Get(i).(Entry)
|
||||
}
|
||||
return entries
|
||||
func Entries() []*Entry {
|
||||
return defaultCron.Entries()
|
||||
}
|
||||
|
||||
// 启动指定的定时任务
|
||||
func Start(name string) {
|
||||
defaultCron.Start(name)
|
||||
}
|
||||
|
||||
// 停止指定的定时任务
|
||||
func Stop(name string) {
|
||||
defaultCron.Stop(name)
|
||||
}
|
||||
|
||||
132
g/os/gcron/gcron_cron.go
Normal file
132
g/os/gcron/gcron_cron.go
Normal file
@ -0,0 +1,132 @@
|
||||
// Copyright 2018 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
|
||||
package gcron
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"gitee.com/johng/gf/g/container/gtype"
|
||||
"gitee.com/johng/gf/g/os/gtime"
|
||||
"gitee.com/johng/gf/third/github.com/robfig/cron"
|
||||
"reflect"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// 添加定时任务
|
||||
func (c *Cron) Add(spec string, f func(), name ... string) error {
|
||||
if len(name) > 0 {
|
||||
if Search(name[0]) != nil {
|
||||
return errors.New(fmt.Sprintf(`cron job "%s" already exists`, name[0]))
|
||||
}
|
||||
jobCron := cron.New()
|
||||
if err := jobCron.AddFunc(spec, f); err == nil {
|
||||
entry := &Entry{
|
||||
Spec : spec,
|
||||
Cmd : runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name(),
|
||||
Time : gtime.Now(),
|
||||
Name : name[0],
|
||||
Status : gtype.NewInt(0),
|
||||
cron : jobCron,
|
||||
}
|
||||
entry.Start()
|
||||
c.entries.Append(entry)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := c.cron.AddFunc(spec, f); err == nil {
|
||||
entry := &Entry{
|
||||
Spec : spec,
|
||||
Cmd : runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name(),
|
||||
Time : gtime.Now(),
|
||||
Status : c.status,
|
||||
cron : c.cron,
|
||||
}
|
||||
entry.Start()
|
||||
c.entries.Append(entry)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 检索指定名称的定时任务
|
||||
func (c *Cron) Search(name string) *Entry {
|
||||
entry, _ := c.searchEntry(name)
|
||||
return entry
|
||||
}
|
||||
|
||||
// 检索指定名称的定时任务
|
||||
func (c *Cron) searchEntry(name string) (*Entry, int) {
|
||||
entry := (*Entry)(nil)
|
||||
index := -1
|
||||
c.entries.RLockFunc(func(array []interface{}) {
|
||||
for k, v := range array {
|
||||
e := v.(*Entry)
|
||||
if e.Name == name {
|
||||
entry = e
|
||||
index = k
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
return entry, index
|
||||
}
|
||||
|
||||
// 根据指定名称删除定时任务
|
||||
func (c *Cron) Remove(name string) {
|
||||
if entry, index := c.searchEntry(name); index >= 0 {
|
||||
entry.cron.Stop()
|
||||
c.entries.Remove(index)
|
||||
}
|
||||
}
|
||||
|
||||
// 开启定时任务执行(可以指定特定名称的一个或若干个定时任务)
|
||||
func (c *Cron) Start(name...string) {
|
||||
if len(name) > 0 {
|
||||
for _, v := range name {
|
||||
if entry := c.Search(v); entry != nil {
|
||||
entry.Start()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
c.entries.RLockFunc(func(array []interface{}) {
|
||||
for _, v := range array {
|
||||
v.(*Entry).Start()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭定时任务执行(可以指定特定名称的一个或若干个定时任务)
|
||||
func (c *Cron) Stop(name...string) {
|
||||
if len(name) > 0 {
|
||||
for _, v := range name {
|
||||
if entry := c.Search(v); entry != nil {
|
||||
entry.Stop()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
c.entries.RLockFunc(func(array []interface{}) {
|
||||
for _, v := range array {
|
||||
v.(*Entry).Stop()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 获取所有已注册的定时任务项
|
||||
func (c *Cron) Entries() []*Entry {
|
||||
length := c.entries.Len()
|
||||
entries := make([]*Entry, length)
|
||||
for i := 0; i < length; i++ {
|
||||
entries[i] = c.entries.Get(i).(*Entry)
|
||||
}
|
||||
return entries
|
||||
}
|
||||
21
g/os/gcron/gcron_entry.go
Normal file
21
g/os/gcron/gcron_entry.go
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2018 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
|
||||
package gcron
|
||||
|
||||
// 启动定时任务
|
||||
func (entry *Entry) Start() {
|
||||
if entry.Status.Set(1) == 0 {
|
||||
entry.cron.Start()
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭定时任务
|
||||
func (entry *Entry) Stop() {
|
||||
if entry.Status.Set(0) == 1 {
|
||||
entry.cron.Stop()
|
||||
}
|
||||
}
|
||||
@ -1,22 +1,26 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitee.com/johng/gf/g"
|
||||
"gitee.com/johng/gf/g/os/gcron"
|
||||
"gitee.com/johng/gf/g/os/glog"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
gcron.Add("0 30 * * * *", func() { fmt.Println("Every hour on the half hour") })
|
||||
gcron.Add("* * * * * *", func() { fmt.Println("Every second") }, "second-cron")
|
||||
gcron.Add("@hourly", func() { fmt.Println("Every hour") })
|
||||
gcron.Add("@every 1h30m", func() { fmt.Println("Every hour thirty") })
|
||||
gcron.Add("0 30 * * * *", func() { glog.Println("Every hour on the half hour") })
|
||||
gcron.Add("* * * * * *", func() { glog.Println("Every second") }, "second-cron")
|
||||
gcron.Add("@hourly", func() { glog.Println("Every hour") })
|
||||
gcron.Add("@every 1h30m", func() { glog.Println("Every hour thirty") })
|
||||
g.Dump(gcron.Entries())
|
||||
|
||||
time.Sleep(3*time.Second)
|
||||
|
||||
gcron.Remove("second-cron")
|
||||
gcron.Stop("second-cron")
|
||||
|
||||
time.Sleep(3*time.Second)
|
||||
|
||||
gcron.Start("second-cron")
|
||||
|
||||
time.Sleep(3*time.Second)
|
||||
}
|
||||
@ -2,7 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitee.com/johng/gf/g/container/gvar"
|
||||
"gitee.com/johng/gf/g/container/gtype"
|
||||
)
|
||||
|
||||
func test() {
|
||||
@ -11,7 +11,7 @@ func test() {
|
||||
}
|
||||
|
||||
func main() {
|
||||
var v *gvar.Var
|
||||
//v := new(gvar.Var)
|
||||
fmt.Println(v.String())
|
||||
v := gtype.NewInt(1)
|
||||
fmt.Println(v.Set(2))
|
||||
fmt.Println(v.Set(2))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user