diff --git a/g/container/gchan/gchan_test.go b/g/container/gchan/gchan_bench_test.go similarity index 100% rename from g/container/gchan/gchan_test.go rename to g/container/gchan/gchan_bench_test.go diff --git a/g/container/gpool/gpool.go b/g/container/gpool/gpool.go index 69bbfc6cc..43f0647d7 100644 --- a/g/container/gpool/gpool.go +++ b/g/container/gpool/gpool.go @@ -43,10 +43,11 @@ type ExpireFunc func(interface{}) // New returns a new object pool. // To ensure execution efficiency, the expiration time cannot be modified once it is set. -// Expire: +// +// Expiration logistics: // expire = 0 : not expired; -// expire < 0 : immediate recovery after use; -// expire > 0 : timeout recovery; +// expire < 0 : immediate expired after use; +// expire > 0 : timeout expired; // Note that the expiration time unit is ** milliseconds **. func New(expire int, newFunc NewFunc, expireFunc...ExpireFunc) *Pool { r := &Pool { @@ -103,14 +104,26 @@ func (p *Pool) Size() int { return p.list.Len() } -// Close closes the pool. +// Close closes the pool. If
has ExpireFunc,
+// then it automatically closes all items using this function before it's closed.
func (p *Pool) Close() {
p.closed.Set(true)
}
-// checkExpire secondly removes expired items from pool.
+// checkExpire removes expired items from pool every second.
func (p *Pool) checkExpire() {
if p.closed.Val() {
+ // If p has ExpireFunc,
+ // then it must close all items using this function.
+ if p.ExpireFunc != nil {
+ for {
+ if r := p.list.PopFront(); r != nil {
+ p.ExpireFunc(r.(*poolItem).value)
+ } else {
+ break
+ }
+ }
+ }
gtimer.Exit()
}
for {
diff --git a/g/container/gpool/gpool_test.go b/g/container/gpool/gpool_bench_test.go
similarity index 87%
rename from g/container/gpool/gpool_test.go
rename to g/container/gpool/gpool_bench_test.go
index d86172519..d2f243479 100644
--- a/g/container/gpool/gpool_test.go
+++ b/g/container/gpool/gpool_bench_test.go
@@ -6,14 +6,15 @@
// go test *.go -bench=".*"
-package gpool
+package gpool_test
import (
- "testing"
+ "github.com/gogf/gf/g/container/gpool"
+ "testing"
"sync"
)
-var pool = New(99999999, nil)
+var pool = gpool.New(99999999, nil)
var syncp = sync.Pool{}
func BenchmarkGPoolPut(b *testing.B) {
diff --git a/g/os/gtime/gtime_format.go b/g/os/gtime/gtime_format.go
index f0ef77a16..2df378f1f 100644
--- a/g/os/gtime/gtime_format.go
+++ b/g/os/gtime/gtime_format.go
@@ -75,56 +75,9 @@ var (
dayOfMonth = []int{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}
)
-// 将自定义的格式转换为标准库时间格式
-func formatToStdLayout(format string) string {
- b := bytes.NewBuffer(nil)
- for i := 0; i < len(format); {
- switch format[i] {
- case '\\':
- if i < len(format)-1 {
- b.WriteByte(format[i+1])
- i += 2
- continue
- } else {
- return b.String()
- }
-
- default:
- if f, ok := formats[format[i]]; ok {
- // 有几个转换的符号需要特殊处理
- switch format[i] {
- case 'j': b.WriteString("02")
- case 'G': b.WriteString("15")
- case 'u':
- if i > 0 && format[i-1] == '.' {
- b.WriteString("000")
- } else {
- b.WriteString(".000")
- }
-
- default:
- b.WriteString(f)
- }
- } else {
- b.WriteByte(format[i])
- }
- i++
- }
- }
- return b.String()
-}
-
-// 将format格式转换为正则表达式规则
-func formatToRegexPattern(format string) string {
- s := gregex.Quote(formatToStdLayout(format))
- s, _ = gregex.ReplaceString(`[0-9]`, `[0-9]`, s)
- s, _ = gregex.ReplaceString(`[A-Za-z]`, `[A-Za-z]`, s)
- return s
-}
-
-// 格式化,使用自定义日期格式
+// 使用自定义日期格式格式化输出日期。
func (t *Time) Format(format string) string {
- runes := []rune(format)
+ runes := []rune(format)
buffer := bytes.NewBuffer(nil)
for i := 0; i < len(runes); {
switch runes[i] {
@@ -165,14 +118,21 @@ func (t *Time) Format(format string) string {
return buffer.String()
}
-// 每月天数后面的英文后缀,2 个字符st nd,rd 或者 th
-func formatMonthDaySuffixMap(day string) string {
- switch day {
- case "01": return "st"
- case "02": return "nd"
- case "03": return "rd"
- default: return "th"
- }
+// 通过自定义格式转换当前日期为新的日期。
+func (t *Time) FormatTo(format string) *Time {
+ t.Time = NewFromStr(t.Format(format)).Time
+ return t
+}
+
+// 使用标准库格式格式化输出日期。
+func (t *Time) Layout(layout string) string {
+ return t.Time.Format(layout)
+}
+
+// 通过标准库格式转换当前日期为新的日期。
+func (t *Time) LayoutTo(layout string) *Time {
+ t.Time = NewFromStr(t.Layout(layout)).Time
+ return t
}
// 返回是否是润年
@@ -221,7 +181,61 @@ func (t *Time) WeeksOfYear() int {
return week
}
-// 格式化使用标准库格式
-func (t *Time) Layout(layout string) string {
- return t.Time.Format(layout)
+// 将自定义的格式转换为标准库时间格式
+func formatToStdLayout(format string) string {
+ b := bytes.NewBuffer(nil)
+ for i := 0; i < len(format); {
+ switch format[i] {
+ case '\\':
+ if i < len(format)-1 {
+ b.WriteByte(format[i+1])
+ i += 2
+ continue
+ } else {
+ return b.String()
+ }
+
+ default:
+ if f, ok := formats[format[i]]; ok {
+ // 有几个转换的符号需要特殊处理
+ switch format[i] {
+ case 'j': b.WriteString("02")
+ case 'G': b.WriteString("15")
+ case 'u':
+ if i > 0 && format[i-1] == '.' {
+ b.WriteString("000")
+ } else {
+ b.WriteString(".000")
+ }
+
+ default:
+ b.WriteString(f)
+ }
+ } else {
+ b.WriteByte(format[i])
+ }
+ i++
+ }
+ }
+ return b.String()
}
+
+// 将format格式转换为正则表达式规则
+func formatToRegexPattern(format string) string {
+ s := gregex.Quote(formatToStdLayout(format))
+ s, _ = gregex.ReplaceString(`[0-9]`, `[0-9]`, s)
+ s, _ = gregex.ReplaceString(`[A-Za-z]`, `[A-Za-z]`, s)
+ return s
+}
+
+// 每月天数后面的英文后缀,2 个字符st nd,rd 或者 th
+func formatMonthDaySuffixMap(day string) string {
+ switch day {
+ case "01": return "st"
+ case "02": return "nd"
+ case "03": return "rd"
+ default: return "th"
+ }
+}
+
+
diff --git a/g/os/gtime/gtime_time.go b/g/os/gtime/gtime_time.go
index 3256945e6..f017472cb 100644
--- a/g/os/gtime/gtime_time.go
+++ b/g/os/gtime/gtime_time.go
@@ -13,7 +13,7 @@ type Time struct {
}
// 创建一个空的时间对象,参数可以是标准库时间对象,可选
-func New (t...time.Time) *Time {
+func New(t...time.Time) *Time {
if len(t) > 0 {
return NewFromTime(t[0])
}
@@ -30,14 +30,14 @@ func Now() *Time {
}
// 标准时间对象转换为自定义的时间对象
-func NewFromTime (t time.Time) *Time {
+func NewFromTime(t time.Time) *Time {
return &Time{
t,
}
}
// 从字符串转换为时间对象,复杂的时间字符串需要给定格式
-func NewFromStr (str string) *Time {
+func NewFromStr(str string) *Time {
if t, err := StrToTime(str); err == nil {
return t
}
@@ -45,7 +45,7 @@ func NewFromStr (str string) *Time {
}
// 从字符串转换为时间对象,指定字符串时间格式,format格式形如:Y-m-d H:i:s
-func NewFromStrFormat (str string, format string) *Time {
+func NewFromStrFormat(str string, format string) *Time {
if t, err := StrToTimeFormat(str, format); err == nil {
return t
}
@@ -53,7 +53,7 @@ func NewFromStrFormat (str string, format string) *Time {
}
// 从字符串转换为时间对象,通过标准库layout格式进行解析,layout格式形如:2006-01-02 15:04:05
-func NewFromStrLayout (str string, layout string) *Time {
+func NewFromStrLayout(str string, layout string) *Time {
if t, err := StrToTimeLayout(str, layout); err == nil {
return t
}
@@ -61,7 +61,7 @@ func NewFromStrLayout (str string, layout string) *Time {
}
// 时间戳转换为时间对象,时间戳支持到纳秒的数值
-func NewFromTimeStamp (timestamp int64) *Time {
+func NewFromTimeStamp(timestamp int64) *Time {
if timestamp == 0 {
return &Time {}
}
@@ -98,7 +98,8 @@ func (t *Time) String() string {
return t.Format("Y-m-d H:i:s")
}
-// 转换为标准库日期对象
+// Deprecated.
+// Directly use t.Time instead.
func (t *Time) ToTime() time.Time {
return t.Time
}
@@ -121,13 +122,12 @@ func (t *Time) ToLocation(location *time.Location) *Time {
}
// 时区转换为指定的时区(通过时区名称,如:Asia/Shanghai)
-func (t *Time) ToZone(zone string) *Time {
+func (t *Time) ToZone(zone string) (*Time, error) {
if l, err := time.LoadLocation(zone); err == nil {
t.Time = t.Time.In(l)
- return t
+ return t, nil
} else {
- //panic(err)
- return nil
+ return nil, err
}
}
diff --git a/g/os/gtime/gtime_z_unit_format_test.go b/g/os/gtime/gtime_z_unit_format_test.go
index 6a67df146..d4abb1b11 100644
--- a/g/os/gtime/gtime_z_unit_format_test.go
+++ b/g/os/gtime/gtime_z_unit_format_test.go
@@ -85,9 +85,24 @@ func Test_Format(t *testing.T) {
})
}
+func Test_FormatTo(t *testing.T) {
+ gtest.Case(t, func() {
+ timeTemp := gtime.Now()
+ gtest.Assert(timeTemp.FormatTo("Y-m-01 00:00:01"), timeTemp.Time.Format("2006-01") + "-01 00:00:01")
+ })
+}
+
+
func Test_Layout(t *testing.T) {
gtest.Case(t, func() {
timeTemp := gtime.Now()
gtest.Assert(timeTemp.Layout("2006-01-02 15:04:05"), timeTemp.Time.Format("2006-01-02 15:04:05"))
})
}
+
+func Test_LayoutTo(t *testing.T) {
+ gtest.Case(t, func() {
+ timeTemp := gtime.Now()
+ gtest.Assert(timeTemp.LayoutTo("2006-01-02 00:00:00"), timeTemp.Time.Format("2006-01-02 00:00:00"))
+ })
+}
diff --git a/g/os/gtime/gtime_z_unit_time_test.go b/g/os/gtime/gtime_z_unit_time_test.go
index 22dbe5e46..f00b2d760 100644
--- a/g/os/gtime/gtime_z_unit_time_test.go
+++ b/g/os/gtime/gtime_z_unit_time_test.go
@@ -137,7 +137,7 @@ func Test_ToZone(t *testing.T) {
timeTemp.ToLocation(loc)
gtest.Assert(timeTemp.Time.Location().String(), "Asia/Shanghai")
- timeTemp1 := timeTemp.ToZone("errZone")
+ timeTemp1, _ := timeTemp.ToZone("errZone")
if timeTemp1 != nil {
t.Error("test fail")
}
diff --git a/g/util/gconv/gconv_struct.go b/g/util/gconv/gconv_struct.go
index 8b1b6a325..e84455496 100644
--- a/g/util/gconv/gconv_struct.go
+++ b/g/util/gconv/gconv_struct.go
@@ -40,10 +40,8 @@ func Struct(params interface{}, pointer interface{}, mapping...map[string]string
}
// Using reflect to do the converting,
// it also supports type of reflect.Value for