From 8ae927673214d428ad3f774d12d552fefe7d389e Mon Sep 17 00:00:00 2001 From: John Date: Tue, 12 Mar 2019 00:24:31 +0800 Subject: [PATCH] add disable cache feature option for package gspath --- g/container/garray/garray_normal_int.go | 8 +- g/container/garray/garray_normal_interface.go | 8 +- g/container/garray/garray_normal_string.go | 8 +- g/container/garray/garray_sorted_int.go | 8 +- g/container/garray/garray_sorted_interface.go | 8 +- g/container/garray/garray_sorted_string.go | 8 +- g/container/gmap/gmap.go | 8 +- g/container/gmap/gmap_int_bool_map.go | 8 +- g/container/gmap/gmap_int_int_map.go | 8 +- g/container/gmap/gmap_int_interface_map.go | 4 +- g/container/gmap/gmap_int_string_map.go | 8 +- g/container/gmap/gmap_string_bool_map.go | 8 +- g/container/gmap/gmap_string_int_map.go | 8 +- g/container/gmap/gmap_string_interface_map.go | 8 +- g/container/gmap/gmap_string_string_map.go | 8 +- g/container/gring/gring.go | 16 +- g/container/gset/gset.go | 8 +- g/container/gset/gset_int_set.go | 8 +- g/container/gset/gset_string_set.go | 8 +- g/encoding/gjson/gjson.go | 28 ++- g/frame/gins/gins.go | 4 +- g/frame/gins/gins_test.go | 142 +++++++++++++++ g/os/gfile/gfile.go | 18 +- g/os/gspath/gspath.go | 162 ++++++++---------- g/os/gspath/gspath_cache.go | 109 ++++++++++++ g/os/gview/gview.go | 2 +- 26 files changed, 424 insertions(+), 197 deletions(-) create mode 100644 g/frame/gins/gins_test.go create mode 100644 g/os/gspath/gspath_cache.go diff --git a/g/container/garray/garray_normal_int.go b/g/container/garray/garray_normal_int.go index 93e3c0282..bf10d1f58 100644 --- a/g/container/garray/garray_normal_int.go +++ b/g/container/garray/garray_normal_int.go @@ -441,8 +441,8 @@ func (a *IntArray) Unique() *IntArray { // // 使用自定义方法执行加锁修改操作。 func (a *IntArray) LockFunc(f func(array []int)) *IntArray { - a.mu.Lock(true) - defer a.mu.Unlock(true) + a.mu.Lock() + defer a.mu.Unlock() f(a.array) return a } @@ -451,8 +451,8 @@ func (a *IntArray) LockFunc(f func(array []int)) *IntArray { // // 使用自定义方法执行加锁读取操作。 func (a *IntArray) RLockFunc(f func(array []int)) *IntArray { - a.mu.RLock(true) - defer a.mu.RUnlock(true) + a.mu.RLock() + defer a.mu.RUnlock() f(a.array) return a } diff --git a/g/container/garray/garray_normal_interface.go b/g/container/garray/garray_normal_interface.go index 6c1f76a5f..75f25bda7 100644 --- a/g/container/garray/garray_normal_interface.go +++ b/g/container/garray/garray_normal_interface.go @@ -433,8 +433,8 @@ func (a *Array) Unique() *Array { // // 使用自定义方法执行加锁修改操作 func (a *Array) LockFunc(f func(array []interface{})) *Array { - a.mu.Lock(true) - defer a.mu.Unlock(true) + a.mu.Lock() + defer a.mu.Unlock() f(a.array) return a } @@ -443,8 +443,8 @@ func (a *Array) LockFunc(f func(array []interface{})) *Array { // // 使用自定义方法执行加锁读取操作 func (a *Array) RLockFunc(f func(array []interface{})) *Array { - a.mu.RLock(true) - defer a.mu.RUnlock(true) + a.mu.RLock() + defer a.mu.RUnlock() f(a.array) return a } diff --git a/g/container/garray/garray_normal_string.go b/g/container/garray/garray_normal_string.go index c44438b70..2cd13911d 100644 --- a/g/container/garray/garray_normal_string.go +++ b/g/container/garray/garray_normal_string.go @@ -440,8 +440,8 @@ func (a *StringArray) Unique() *StringArray { // // 使用自定义方法执行加锁修改操作。 func (a *StringArray) LockFunc(f func(array []string)) *StringArray { - a.mu.Lock(true) - defer a.mu.Unlock(true) + a.mu.Lock() + defer a.mu.Unlock() f(a.array) return a } @@ -450,8 +450,8 @@ func (a *StringArray) LockFunc(f func(array []string)) *StringArray { // // 使用自定义方法执行加锁读取操作。 func (a *StringArray) RLockFunc(f func(array []string)) *StringArray { - a.mu.RLock(true) - defer a.mu.RUnlock(true) + a.mu.RLock() + defer a.mu.RUnlock() f(a.array) return a } diff --git a/g/container/garray/garray_sorted_int.go b/g/container/garray/garray_sorted_int.go index c2a7cfab3..e0e7862a5 100644 --- a/g/container/garray/garray_sorted_int.go +++ b/g/container/garray/garray_sorted_int.go @@ -415,8 +415,8 @@ func (a *SortedIntArray) Clear() *SortedIntArray { // // 使用自定义方法执行加锁修改操作。 func (a *SortedIntArray) LockFunc(f func(array []int)) *SortedIntArray { - a.mu.Lock(true) - defer a.mu.Unlock(true) + a.mu.Lock() + defer a.mu.Unlock() f(a.array) return a } @@ -425,8 +425,8 @@ func (a *SortedIntArray) LockFunc(f func(array []int)) *SortedIntArray { // // 使用自定义方法执行加锁读取操作。 func (a *SortedIntArray) RLockFunc(f func(array []int)) *SortedIntArray { - a.mu.RLock(true) - defer a.mu.RUnlock(true) + a.mu.RLock() + defer a.mu.RUnlock() f(a.array) return a } diff --git a/g/container/garray/garray_sorted_interface.go b/g/container/garray/garray_sorted_interface.go index 48544e16b..71c3f8ef3 100644 --- a/g/container/garray/garray_sorted_interface.go +++ b/g/container/garray/garray_sorted_interface.go @@ -422,8 +422,8 @@ func (a *SortedArray) Clear() *SortedArray { // // 使用自定义方法执行加锁修改操作。 func (a *SortedArray) LockFunc(f func(array []interface{})) *SortedArray { - a.mu.Lock(true) - defer a.mu.Unlock(true) + a.mu.Lock() + defer a.mu.Unlock() f(a.array) return a } @@ -432,8 +432,8 @@ func (a *SortedArray) LockFunc(f func(array []interface{})) *SortedArray { // // 使用自定义方法执行加锁读取操作。 func (a *SortedArray) RLockFunc(f func(array []interface{})) *SortedArray { - a.mu.RLock(true) - defer a.mu.RUnlock(true) + a.mu.RLock() + defer a.mu.RUnlock() f(a.array) return a } diff --git a/g/container/garray/garray_sorted_string.go b/g/container/garray/garray_sorted_string.go index 6ead68b12..2eb009809 100644 --- a/g/container/garray/garray_sorted_string.go +++ b/g/container/garray/garray_sorted_string.go @@ -410,8 +410,8 @@ func (a *SortedStringArray) Clear() *SortedStringArray { // // 使用自定义方法执行加锁修改操作。 func (a *SortedStringArray) LockFunc(f func(array []string)) *SortedStringArray { - a.mu.Lock(true) - defer a.mu.Unlock(true) + a.mu.Lock() + defer a.mu.Unlock() f(a.array) return a } @@ -420,8 +420,8 @@ func (a *SortedStringArray) LockFunc(f func(array []string)) *SortedStringArray // // 使用自定义方法执行加锁读取操作。 func (a *SortedStringArray) RLockFunc(f func(array []string)) *SortedStringArray { - a.mu.RLock(true) - defer a.mu.RUnlock(true) + a.mu.RLock() + defer a.mu.RUnlock() f(a.array) return a } diff --git a/g/container/gmap/gmap.go b/g/container/gmap/gmap.go index 679d66007..c2a982aab 100644 --- a/g/container/gmap/gmap.go +++ b/g/container/gmap/gmap.go @@ -291,8 +291,8 @@ func (gm *Map) Clear() { // // 并发安全锁操作,使用自定义方法执行加锁修改操作 func (gm *Map) LockFunc(f func(m map[interface{}]interface{})) { - gm.mu.Lock(true) - defer gm.mu.Unlock(true) + gm.mu.Lock() + defer gm.mu.Unlock() f(gm.m) } @@ -300,8 +300,8 @@ func (gm *Map) LockFunc(f func(m map[interface{}]interface{})) { // // 并发安全锁操作,使用自定义方法执行加锁读取操作 func (gm *Map) RLockFunc(f func(m map[interface{}]interface{})) { - gm.mu.RLock(true) - defer gm.mu.RUnlock(true) + gm.mu.RLock() + defer gm.mu.RUnlock() f(gm.m) } diff --git a/g/container/gmap/gmap_int_bool_map.go b/g/container/gmap/gmap_int_bool_map.go index 71520e264..035bc3e4d 100644 --- a/g/container/gmap/gmap_int_bool_map.go +++ b/g/container/gmap/gmap_int_bool_map.go @@ -238,15 +238,15 @@ func (gm *IntBoolMap) Clear() { // 并发安全锁操作,使用自定义方法执行加锁修改操作 func (gm *IntBoolMap) LockFunc(f func(m map[int]bool)) { - gm.mu.Lock(true) - defer gm.mu.Unlock(true) + gm.mu.Lock() + defer gm.mu.Unlock() f(gm.m) } // 并发安全锁操作,使用自定义方法执行加锁读取操作 func (gm *IntBoolMap) RLockFunc(f func(m map[int]bool)) { - gm.mu.RLock(true) - defer gm.mu.RUnlock(true) + gm.mu.RLock() + defer gm.mu.RUnlock() f(gm.m) } diff --git a/g/container/gmap/gmap_int_int_map.go b/g/container/gmap/gmap_int_int_map.go index 67c912109..723365dc4 100644 --- a/g/container/gmap/gmap_int_int_map.go +++ b/g/container/gmap/gmap_int_int_map.go @@ -238,15 +238,15 @@ func (gm *IntIntMap) Clear() { // 并发安全锁操作,使用自定义方法执行加锁修改操作 func (gm *IntIntMap) LockFunc(f func(m map[int]int)) { - gm.mu.Lock(true) - defer gm.mu.Unlock(true) + gm.mu.Lock() + defer gm.mu.Unlock() f(gm.m) } // 并发安全锁操作,使用自定义方法执行加锁读取操作 func (gm *IntIntMap) RLockFunc(f func(m map[int]int)) { - gm.mu.RLock(true) - defer gm.mu.RUnlock(true) + gm.mu.RLock() + defer gm.mu.RUnlock() f(gm.m) } diff --git a/g/container/gmap/gmap_int_interface_map.go b/g/container/gmap/gmap_int_interface_map.go index 5f30013d2..c6b6a540f 100644 --- a/g/container/gmap/gmap_int_interface_map.go +++ b/g/container/gmap/gmap_int_interface_map.go @@ -231,8 +231,8 @@ func (gm *IntInterfaceMap) LockFunc(f func(m map[int]interface{})) { // 并发安全锁操作,使用自定义方法执行加锁读取操作 func (gm *IntInterfaceMap) RLockFunc(f func(m map[int]interface{})) { - gm.mu.RLock(true) - defer gm.mu.RUnlock(true) + gm.mu.RLock() + defer gm.mu.RUnlock() f(gm.m) } diff --git a/g/container/gmap/gmap_int_string_map.go b/g/container/gmap/gmap_int_string_map.go index 629b0d3e1..54c075a0f 100644 --- a/g/container/gmap/gmap_int_string_map.go +++ b/g/container/gmap/gmap_int_string_map.go @@ -239,15 +239,15 @@ func (gm *IntStringMap) Clear() { // 并发安全锁操作,使用自定义方法执行加锁修改操作 func (gm *IntStringMap) LockFunc(f func(m map[int]string)) { - gm.mu.Lock(true) - defer gm.mu.Unlock(true) + gm.mu.Lock() + defer gm.mu.Unlock() f(gm.m) } // 并发安全锁操作,使用自定义方法执行加锁读取操作 func (gm *IntStringMap) RLockFunc(f func(m map[int]string)) { - gm.mu.RLock(true) - defer gm.mu.RUnlock(true) + gm.mu.RLock() + defer gm.mu.RUnlock() f(gm.m) } diff --git a/g/container/gmap/gmap_string_bool_map.go b/g/container/gmap/gmap_string_bool_map.go index 3ccf8892e..e1edfacd2 100644 --- a/g/container/gmap/gmap_string_bool_map.go +++ b/g/container/gmap/gmap_string_bool_map.go @@ -238,15 +238,15 @@ func (gm *StringBoolMap) Clear() { // 并发安全锁操作,使用自定义方法执行加锁修改操作 func (gm *StringBoolMap) LockFunc(f func(m map[string]bool)) { - gm.mu.Lock(true) - defer gm.mu.Unlock(true) + gm.mu.Lock() + defer gm.mu.Unlock() f(gm.m) } // 并发安全锁操作,使用自定义方法执行加锁读取操作 func (gm *StringBoolMap) RLockFunc(f func(m map[string]bool)) { - gm.mu.RLock(true) - defer gm.mu.RUnlock(true) + gm.mu.RLock() + defer gm.mu.RUnlock() f(gm.m) } diff --git a/g/container/gmap/gmap_string_int_map.go b/g/container/gmap/gmap_string_int_map.go index 8cdc80066..63a16806d 100644 --- a/g/container/gmap/gmap_string_int_map.go +++ b/g/container/gmap/gmap_string_int_map.go @@ -239,15 +239,15 @@ func (gm *StringIntMap) Clear() { // 并发安全写锁操作,使用自定义方法执行加锁修改操作 func (gm *StringIntMap) LockFunc(f func(m map[string]int)) { - gm.mu.Lock(true) - defer gm.mu.Unlock(true) + gm.mu.Lock() + defer gm.mu.Unlock() f(gm.m) } // 并发安全读锁操作,使用自定义方法执行加锁读取操作 func (gm *StringIntMap) RLockFunc(f func(m map[string]int)) { - gm.mu.RLock(true) - defer gm.mu.RUnlock(true) + gm.mu.RLock() + defer gm.mu.RUnlock() f(gm.m) } diff --git a/g/container/gmap/gmap_string_interface_map.go b/g/container/gmap/gmap_string_interface_map.go index 875c7b684..39055a599 100644 --- a/g/container/gmap/gmap_string_interface_map.go +++ b/g/container/gmap/gmap_string_interface_map.go @@ -224,15 +224,15 @@ func (gm *StringInterfaceMap) Clear() { // 并发安全写锁操作,使用自定义方法执行加锁修改操作 func (gm *StringInterfaceMap) LockFunc(f func(m map[string]interface{})) { - gm.mu.Lock(true) - defer gm.mu.Unlock(true) + gm.mu.Lock() + defer gm.mu.Unlock() f(gm.m) } // 并发安全读锁操作,使用自定义方法执行加锁读取操作 func (gm *StringInterfaceMap) RLockFunc(f func(m map[string]interface{})) { - gm.mu.RLock(true) - defer gm.mu.RUnlock(true) + gm.mu.RLock() + defer gm.mu.RUnlock() f(gm.m) } diff --git a/g/container/gmap/gmap_string_string_map.go b/g/container/gmap/gmap_string_string_map.go index 35f8a4b47..5c61e742a 100644 --- a/g/container/gmap/gmap_string_string_map.go +++ b/g/container/gmap/gmap_string_string_map.go @@ -238,15 +238,15 @@ func (gm *StringStringMap) Clear() { // 并发安全写锁操作,使用自定义方法执行加锁修改操作 func (gm *StringStringMap) LockFunc(f func(m map[string]string)) { - gm.mu.Lock(true) - defer gm.mu.Unlock(true) + gm.mu.Lock() + defer gm.mu.Unlock() f(gm.m) } // 并发安全读锁操作,使用自定义方法执行加锁读取操作 func (gm *StringStringMap) RLockFunc(f func(m map[string]string)) { - gm.mu.RLock(true) - defer gm.mu.RUnlock(true) + gm.mu.RLock() + defer gm.mu.RUnlock() f(gm.m) } diff --git a/g/container/gring/gring.go b/g/container/gring/gring.go index 2590ac463..0d34b1424 100644 --- a/g/container/gring/gring.go +++ b/g/container/gring/gring.go @@ -149,8 +149,8 @@ func (r *Ring) Unlink(n int) *Ring { // 读锁遍历,往后只读遍历,回调函数返回true表示继续遍历,否则退出遍历 func (r *Ring) RLockIteratorNext(f func(value interface{}) bool) { - r.mu.RLock(true) - defer r.mu.RUnlock(true) + r.mu.RLock() + defer r.mu.RUnlock() if !f(r.ring.Value) { return } @@ -163,8 +163,8 @@ func (r *Ring) RLockIteratorNext(f func(value interface{}) bool) { // 读锁遍历,往前只读遍历,回调函数返回true表示继续遍历,否则退出遍历 func (r *Ring) RLockIteratorPrev(f func(value interface{}) bool) { - r.mu.RLock(true) - defer r.mu.RUnlock(true) + r.mu.RLock() + defer r.mu.RUnlock() if !f(r.ring.Value) { return } @@ -177,8 +177,8 @@ func (r *Ring) RLockIteratorPrev(f func(value interface{}) bool) { // 写锁遍历,往后写遍历,回调函数返回true表示继续遍历,否则退出遍历 func (r *Ring) LockIteratorNext(f func(item *ring.Ring) bool) { - r.mu.RLock(true) - defer r.mu.RUnlock(true) + r.mu.RLock() + defer r.mu.RUnlock() if !f(r.ring) { return } @@ -191,8 +191,8 @@ func (r *Ring) LockIteratorNext(f func(item *ring.Ring) bool) { // 写锁遍历,往前写遍历,回调函数返回true表示继续遍历,否则退出遍历 func (r *Ring) LockIteratorPrev(f func(item *ring.Ring) bool) { - r.mu.RLock(true) - defer r.mu.RUnlock(true) + r.mu.RLock() + defer r.mu.RUnlock() if !f(r.ring) { return } diff --git a/g/container/gset/gset.go b/g/container/gset/gset.go index 82995005e..3d56f541e 100644 --- a/g/container/gset/gset.go +++ b/g/container/gset/gset.go @@ -139,8 +139,8 @@ func (set *Set) String() string { // // 使用自定义方法执行加锁修改操作。 func (set *Set) LockFunc(f func(m map[interface{}]struct{})) *Set { - set.mu.Lock(true) - defer set.mu.Unlock(true) + set.mu.Lock() + defer set.mu.Unlock() f(set.m) return set } @@ -149,8 +149,8 @@ func (set *Set) LockFunc(f func(m map[interface{}]struct{})) *Set { // // 使用自定义方法执行加锁读取操作。 func (set *Set) RLockFunc(f func(m map[interface{}]struct{})) *Set { - set.mu.RLock(true) - defer set.mu.RUnlock(true) + set.mu.RLock() + defer set.mu.RUnlock() f(set.m) return set } diff --git a/g/container/gset/gset_int_set.go b/g/container/gset/gset_int_set.go index 3150736b9..a53a90692 100644 --- a/g/container/gset/gset_int_set.go +++ b/g/container/gset/gset_int_set.go @@ -130,8 +130,8 @@ func (set *IntSet) String() string { // // 使用自定义方法执行加锁修改操作。 func (set *IntSet) LockFunc(f func(m map[int]struct{})) *IntSet { - set.mu.Lock(true) - defer set.mu.Unlock(true) + set.mu.Lock() + defer set.mu.Unlock() f(set.m) return set } @@ -140,8 +140,8 @@ func (set *IntSet) LockFunc(f func(m map[int]struct{})) *IntSet { // // 使用自定义方法执行加锁读取操作。 func (set *IntSet) RLockFunc(f func(m map[int]struct{})) *IntSet { - set.mu.RLock(true) - defer set.mu.RUnlock(true) + set.mu.RLock() + defer set.mu.RUnlock() f(set.m) return set } diff --git a/g/container/gset/gset_string_set.go b/g/container/gset/gset_string_set.go index bd30ee58d..39faeb2fb 100644 --- a/g/container/gset/gset_string_set.go +++ b/g/container/gset/gset_string_set.go @@ -130,8 +130,8 @@ func (set *StringSet) String() string { // // 使用自定义方法执行加锁修改操作。 func (set *StringSet) LockFunc(f func(m map[string]struct{})) *StringSet { - set.mu.Lock(true) - defer set.mu.Unlock(true) + set.mu.Lock() + defer set.mu.Unlock() f(set.m) return set } @@ -140,8 +140,8 @@ func (set *StringSet) LockFunc(f func(m map[string]struct{})) *StringSet { // // 使用自定义方法执行加锁读取操作。 func (set *StringSet) RLockFunc(f func(m map[string]struct{})) *StringSet { - set.mu.RLock(true) - defer set.mu.RUnlock(true) + set.mu.RLock() + defer set.mu.RUnlock() f(set.m) return set } diff --git a/g/encoding/gjson/gjson.go b/g/encoding/gjson/gjson.go index 1dd4a9fc6..95bd233ee 100644 --- a/g/encoding/gjson/gjson.go +++ b/g/encoding/gjson/gjson.go @@ -8,21 +8,21 @@ package gjson import ( - "errors" - "github.com/gogf/gf/g/text/gregex" - "strings" - "strconv" - "io/ioutil" "encoding/json" - "github.com/gogf/gf/g/os/gfile" - "github.com/gogf/gf/g/util/gconv" + "errors" + "fmt" + "github.com/gogf/gf/g/encoding/gtoml" "github.com/gogf/gf/g/encoding/gxml" "github.com/gogf/gf/g/encoding/gyaml" - "github.com/gogf/gf/g/encoding/gtoml" - "github.com/gogf/gf/g/text/gstr" - "time" "github.com/gogf/gf/g/internal/rwmutex" - "fmt" + "github.com/gogf/gf/g/os/gfcache" + "github.com/gogf/gf/g/os/gfile" + "github.com/gogf/gf/g/text/gregex" + "github.com/gogf/gf/g/text/gstr" + "github.com/gogf/gf/g/util/gconv" + "strconv" + "strings" + "time" ) const ( @@ -110,11 +110,7 @@ func DecodeToJson (b []byte) (*Json, error) { // 支持多种配置文件类型转换为json格式内容并解析为gjson.Json对象 func Load (path string) (*Json, error) { - data, err := ioutil.ReadFile(path) - if err != nil { - return nil, err - } - return LoadContent(data, gfile.Ext(path)) + return LoadContent(gfcache.GetBinContents(path), gfile.Ext(path)) } // 支持的配置文件格式:xml, json, yaml/yml, toml, diff --git a/g/frame/gins/gins.go b/g/frame/gins/gins.go index b651b277c..4668d9fa3 100644 --- a/g/frame/gins/gins.go +++ b/g/frame/gins/gins.go @@ -73,7 +73,7 @@ func View(name...string) *gview.View { } key := fmt.Sprintf("%s.%s", gFRAME_CORE_COMPONENT_NAME_VIEW, group) return instances.GetOrSetFuncLock(key, func() interface{} { - path := cmdenv.Get("gf.gview.path", gfile.SelfDir()).String() + path := cmdenv.Get("gf.gview.path", gfile.Pwd()).String() view := gview.New(path) // 添加基于源码的搜索目录检索地址,常用于开发环境调试,只添加入口文件目录 if p := gfile.MainPkgPath(); p != "" && gfile.Exists(p) { @@ -94,7 +94,7 @@ func Config(file...string) *gcfg.Config { } return instances.GetOrSetFuncLock(fmt.Sprintf("%s.%s", gFRAME_CORE_COMPONENT_NAME_CONFIG, configFile), func() interface{} { - path := cmdenv.Get("gf.gcfg.path", gfile.SelfDir()).String() + path := cmdenv.Get("gf.gcfg.path", gfile.Pwd()).String() config := gcfg.New(path, configFile) // 添加基于源码的搜索目录检索地址,常用于开发环境调试,只添加入口文件目录 if p := gfile.MainPkgPath(); p != "" && gfile.Exists(p) { diff --git a/g/frame/gins/gins_test.go b/g/frame/gins/gins_test.go new file mode 100644 index 000000000..e0ff84e6f --- /dev/null +++ b/g/frame/gins/gins_test.go @@ -0,0 +1,142 @@ +// Copyright 2017 gf Author(https://github.com/gogf/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://github.com/gogf/gf. + +package gins_test + +import ( + "fmt" + "github.com/gogf/gf/g/frame/gins" + "github.com/gogf/gf/g/os/gfile" + "github.com/gogf/gf/g/os/gtime" + "github.com/gogf/gf/g/test/gtest" + "testing" +) + +func Test_SetGet(t *testing.T) { + gtest.Case(t, func() { + gins.Set("test-user", 1) + gtest.Assert(gins.Get("test-user"), 1) + gtest.Assert(gins.Get("none-exists"), nil) + }) + gtest.Case(t, func() { + gtest.Assert(gins.GetOrSet("test-1", 1), 1) + gtest.Assert(gins.Get("test-1"), 1) + }) + gtest.Case(t, func() { + gtest.Assert(gins.GetOrSetFunc("test-2", func() interface{} { + return 2 + }), 2) + gtest.Assert(gins.Get("test-2"), 2) + }) + gtest.Case(t, func() { + gtest.Assert(gins.GetOrSetFuncLock("test-3", func() interface{} { + return 3 + }), 3) + gtest.Assert(gins.Get("test-3"), 3) + }) + gtest.Case(t, func() { + gtest.Assert(gins.SetIfNotExist("test-4", 4), true) + gtest.Assert(gins.Get("test-4"), 4) + gtest.Assert(gins.SetIfNotExist("test-4", 5), false) + gtest.Assert(gins.Get("test-4"), 4) + }) +} + +func Test_View(t *testing.T) { + gtest.Case(t, func() { + gtest.AssertNE(gins.View(), nil) + b, e := gins.View().ParseContent(`{{"1540822968" | date "Y-m-d H:i:s"}}`, nil) + gtest.Assert(e, nil) + gtest.Assert(string(b), "2018-10-29 22:22:48") + }) + gtest.Case(t, func() { + tpl := "t.tpl" + err := gfile.PutContents(tpl, `{{"1540822968" | date "Y-m-d H:i:s"}}`) + gtest.Assert(err, nil) + defer gfile.Remove(tpl) + + b, e := gins.View().Parse("t.tpl", nil) + gtest.Assert(e, nil) + gtest.Assert(string(b), "2018-10-29 22:22:48") + }) + gtest.Case(t, func() { + path := fmt.Sprintf(`%s/%d`, gfile.TempDir(), gtime.Nanosecond()) + tpl := fmt.Sprintf(`%s/%s`, path, "t.tpl") + err := gfile.PutContents(tpl, `{{"1540822968" | date "Y-m-d H:i:s"}}`) + gtest.Assert(err, nil) + defer gfile.Remove(tpl) + err = gins.View().AddPath(path) + gtest.Assert(err, nil) + + b, e := gins.View().Parse("t.tpl", nil) + gtest.Assert(e, nil) + gtest.Assert(string(b), "2018-10-29 22:22:48") + }) +} + +func Test_Config(t *testing.T) { + config := ` +# 模板引擎目录 +viewpath = "/home/www/templates/" +test = "v=1" +# MySQL数据库配置 +[database] + [[database.default]] + host = "127.0.0.1" + port = "3306" + user = "root" + pass = "" + name = "test" + type = "mysql" + role = "master" + charset = "utf8" + priority = "1" + [[database.default]] + host = "127.0.0.1" + port = "3306" + user = "root" + pass = "8692651" + name = "test" + type = "mysql" + role = "master" + charset = "utf8" + priority = "1" +# Redis数据库配置 +[redis] + disk = "127.0.0.1:6379,0" + cache = "127.0.0.1:6379,1" +` + gtest.Case(t, func() { + gtest.AssertNE(gins.Config(), nil) + }) + gtest.Case(t, func() { + path := "config.toml" + err := gfile.PutContents(path, config) + gtest.Assert(err, nil) + defer gfile.Remove(path) + + //fmt.Println(os.Getwd()) + //fmt.Println(gfile.Pwd()) + //fmt.Println(gfile.ScanDir(".", "*")) + + gtest.Assert(gins.Config().Get("test"), "v=1") + gtest.Assert(gins.Config().Get("database.default.1.host"), "127.0.0.1") + gtest.Assert(gins.Config().Get("redis.disk"), "127.0.0.1:6379,0") + }) + gtest.Case(t, func() { + path := fmt.Sprintf(`%s/%d`, gfile.TempDir(), gtime.Nanosecond()) + file := fmt.Sprintf(`%s/%s`, path, "config.toml") + err := gfile.PutContents(file, config) + gtest.Assert(err, nil) + defer gfile.Remove(file) + err = gins.Config().AddPath(path) + gtest.Assert(err, nil) + + gtest.Assert(gins.Config().Get("test"), "v=1") + gtest.Assert(gins.Config().Get("database.default.1.host"), "127.0.0.1") + gtest.Assert(gins.Config().Get("redis.disk"), "127.0.0.1:6379,0") + }) +} \ No newline at end of file diff --git a/g/os/gfile/gfile.go b/g/os/gfile/gfile.go index 528120965..7b6f3dee2 100644 --- a/g/os/gfile/gfile.go +++ b/g/os/gfile/gfile.go @@ -122,11 +122,12 @@ func IsDir(path string) bool { return s.IsDir() } -// Get current working absolute directory path. +// Get current working directory absolute path. // -// 获取当前工作目录(SelfDir()方法的别名) +// 获取当前工作目录(注意与SelfDir的区别). func Pwd() string { - return SelfDir() + path, _ := os.Getwd() + return path } // Check whether given path a file(not a directory). @@ -140,11 +141,18 @@ func IsFile(path string) bool { return !s.IsDir() } -// Info returns a FileInfo describing the named file. +// See Stat. +// +// Stat 方法的别名。 +func Info(path string) (os.FileInfo, error) { + return Stat(path) +} + +// Stat returns a FileInfo describing the named file. // If there is an error, it will be of type *PathError. // // 获取文件或目录信息. -func Info(path string) (os.FileInfo, error) { +func Stat(path string) (os.FileInfo, error) { return os.Stat(path) } diff --git a/g/os/gspath/gspath.go b/g/os/gspath/gspath.go index b6133194e..8a014a045 100644 --- a/g/os/gspath/gspath.go +++ b/g/os/gspath/gspath.go @@ -7,7 +7,8 @@ // Package gspath implements file index and search for folders. // // 搜索目录管理, -// 可以添加搜索目录,按照添加的优先级进行文件检索,并在内部进行高效缓存处理。 +// 可以添加搜索目录,按照添加的优先级进行文件检索,并在内部进行高效缓存处理(可选)。 +// 注意:当开启缓存功能后,在新增/删除文件时,会存在检索延迟。 package gspath import ( @@ -16,9 +17,8 @@ import ( "github.com/gogf/gf/g/container/garray" "github.com/gogf/gf/g/container/gmap" "github.com/gogf/gf/g/os/gfile" - "github.com/gogf/gf/g/os/gfsnotify" "github.com/gogf/gf/g/text/gstr" - "runtime" + "os" "sort" "strings" ) @@ -26,7 +26,7 @@ import ( // 文件目录搜索管理对象 type SPath struct { paths *garray.StringArray // 搜索路径,按照优先级进行排序 - cache *gmap.StringStringMap // 搜索结果缓存map + cache *gmap.StringStringMap // 搜索结果缓存map(如果未nil表示未启用缓存功能) } // 文件搜索缓存项 @@ -37,17 +37,20 @@ type SPathCacheItem struct { var ( // 单个目录路径对应的SPath对象指针,用于路径检索对象复用 - pathsMap = gmap.NewStringInterfaceMap() + pathsMap = gmap.NewStringInterfaceMap() + pathsCacheMap = gmap.NewStringInterfaceMap() ) // 创建一个搜索对象 -func New(path...string) *SPath { +func New(path string, cache bool) *SPath { sp := &SPath { paths : garray.NewStringArray(), - cache : gmap.NewStringStringMap(), + } + if cache { + sp.cache = gmap.NewStringStringMap() } if len(path) > 0 { - if _, err := sp.Add(path[0]); err != nil { + if _, err := sp.Add(path); err != nil { //fmt.Errorf(err.Error()) } } @@ -55,15 +58,26 @@ func New(path...string) *SPath { } // 创建/获取一个单例的搜索对象, root必须为目录的绝对路径 -func Get(root string) *SPath { - return pathsMap.GetOrSetFuncLock(root, func() interface{} { - return New(root) - }).(*SPath) +func Get(root string, cache bool) *SPath { + if cache { + return pathsCacheMap.GetOrSetFuncLock(root, func() interface{} { + return New(root, true) + }).(*SPath) + } else { + return pathsMap.GetOrSetFuncLock(root, func() interface{} { + return New(root, false) + }).(*SPath) + } } // 检索root目录(必须为绝对路径)下面的name文件的绝对路径,indexFiles用于指定当检索到的结果为目录时,同时检索是否存在这些indexFiles文件 func Search(root string, name string, indexFiles...string) (filePath string, isDir bool) { - return Get(root).Search(name, indexFiles...) + return Get(root, false).Search(name, indexFiles...) +} + +// 检索root目录(必须为绝对路径)下面的name文件的绝对路径,indexFiles用于指定当检索到的结果为目录时,同时检索是否存在这些indexFiles文件 +func SearchWithCache(root string, name string, indexFiles...string) (filePath string, isDir bool) { + return Get(root, true).Search(name, indexFiles...) } @@ -88,8 +102,9 @@ func (sp *SPath) Set(path string) (realPath string, err error) { } } sp.paths.Clear() - sp.cache.Clear() - + if sp.cache != nil { + sp.cache.Clear() + } sp.paths.Append(realPath) sp.updateCacheByPath(realPath) sp.addMonitorByPath(realPath) @@ -128,9 +143,39 @@ func (sp *SPath) Add(path string) (realPath string, err error) { } // 给定的name只是相对文件路径,找不到该文件时,返回空字符串; -// 当给定indexFiles时,如果name时一个目录,那么会进一步检索其下对应的indexFiles文件是否存在,存在则返回indexFile绝对路径; +// 当给定indexFiles时,如果name是一个目录,那么会进一步检索其下对应的indexFiles文件是否存在,存在则返回indexFile绝对路径; // 否则返回name目录绝对路径。 func (sp *SPath) Search(name string, indexFiles...string) (filePath string, isDir bool) { + // 不使用缓存 + if sp.cache == nil { + sp.paths.LockFunc(func(array []string) { + path := "" + for _, v := range array { + path = v + gfile.Separator + name + if stat, err := os.Stat(path); !os.IsNotExist(err) { + filePath = path + isDir = stat.IsDir() + break + } + } + }) + if len(indexFiles) > 0 && isDir { + if name == "/" { + name = "" + } + path := "" + for _, file := range indexFiles { + path = filePath + gfile.Separator + file + if gfile.Exists(path) { + filePath = path + isDir = false + break + } + } + } + return + } + // 使用缓存功能 name = sp.formatCacheName(name) if v := sp.cache.Get(name); v != "" { filePath, isDir = sp.parseCacheValue(v) @@ -151,6 +196,9 @@ func (sp *SPath) Search(name string, indexFiles...string) (filePath string, isDi // 从搜索路径中移除指定的文件,这样该文件无法给搜索。 // path可以是绝对路径,也可以相对路径。 func (sp *SPath) Remove(path string) { + if sp.cache == nil { + return + } if gfile.Exists(path) { for _, v := range sp.paths.Slice() { name := gstr.Replace(path, v, "") @@ -170,6 +218,9 @@ func (sp *SPath) Paths() []string { // 返回当前对象缓存的所有路径列表 func (sp *SPath) AllPaths() []string { + if sp.cache == nil { + return nil + } paths := sp.cache.Keys() if len(paths) > 0 { sort.Strings(paths) @@ -181,82 +232,3 @@ func (sp *SPath) AllPaths() []string { func (sp *SPath) Size() int { return sp.paths.Len() } - -// 递归添加目录下的文件 -func (sp *SPath) updateCacheByPath(path string) { - sp.addToCache(path, path) -} - -// 格式化name返回符合规范的缓存名称,分隔符号统一为'/',且前缀必须以'/'开头(类似HTTP URI). -func (sp *SPath) formatCacheName(name string) string { - if runtime.GOOS != "linux" { - name = gstr.Replace(name, "\\", "/") - } - return "/" + strings.Trim(name, "./") -} - -// 根据path计算出对应的缓存name, dirPath为检索根目录路径 -func (sp *SPath) nameFromPath(filePath, rootPath string) string { - name := gstr.Replace(filePath, rootPath, "") - name = sp.formatCacheName(name) - return name -} - -// 按照一定数据结构生成缓存的数据项字符串 -func (sp *SPath) makeCacheValue(filePath string, isDir bool) string { - if isDir { - return filePath + "_D_" - } - return filePath + "_F_" -} - -// 按照一定数据结构解析数据项字符串 -func (sp *SPath) parseCacheValue(value string) (filePath string, isDir bool) { - if value[len(value) - 2 : len(value) - 1][0] == 'F' { - return value[: len(value) - 3], false - } - return value[: len(value) - 3], true -} - -// 添加path到缓存中(递归) -func (sp *SPath) addToCache(filePath, rootPath string) { - // 首先添加自身 - idDir := gfile.IsDir(filePath) - sp.cache.SetIfNotExist(sp.nameFromPath(filePath, rootPath), sp.makeCacheValue(filePath, idDir)) - // 如果添加的是目录,那么需要递归添加 - if idDir { - if files, err := gfile.ScanDir(filePath, "*", true); err == nil { - //fmt.Println("gspath add to cache:", filePath, files) - for _, path := range files { - sp.cache.SetIfNotExist(sp.nameFromPath(path, rootPath), sp.makeCacheValue(path, gfile.IsDir(path))) - } - } else { - //fmt.Errorf(err.Error()) - } - } -} - -// 添加文件目录监控(递归),当目录下的文件有更新时,会同时更新缓存。 -// 这里需要注意的点是,由于添加监听是递归添加的,那么假如删除一个目录,那么该目录下的文件(包括目录)也会产生一条删除事件,总共会产生N条事件。 -func (sp *SPath) addMonitorByPath(path string) { - gfsnotify.Add(path, func(event *gfsnotify.Event) { - //glog.Debug(event.String()) - switch { - case event.IsRemove(): - sp.cache.Remove(sp.nameFromPath(event.Path, path)) - - case event.IsRename(): - if !gfile.Exists(event.Path) { - sp.cache.Remove(sp.nameFromPath(event.Path, path)) - } - - case event.IsCreate(): - sp.addToCache(event.Path, path) - } - }, true) -} - -// 删除监听(递归) -func (sp *SPath) removeMonitorByPath(path string) { - gfsnotify.Remove(path) -} \ No newline at end of file diff --git a/g/os/gspath/gspath_cache.go b/g/os/gspath/gspath_cache.go new file mode 100644 index 000000000..048e283bf --- /dev/null +++ b/g/os/gspath/gspath_cache.go @@ -0,0 +1,109 @@ +// Copyright 2018 gf Author(https://github.com/gogf/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://github.com/gogf/gf. + +// Package gspath implements file index and search for folders. +// + +package gspath + +import ( + "github.com/gogf/gf/g/os/gfile" + "github.com/gogf/gf/g/os/gfsnotify" + "github.com/gogf/gf/g/text/gstr" + "runtime" + "strings" +) + +// 递归添加目录下的文件 +func (sp *SPath) updateCacheByPath(path string) { + if sp.cache == nil { + return + } + sp.addToCache(path, path) +} + +// 格式化name返回符合规范的缓存名称,分隔符号统一为'/',且前缀必须以'/'开头(类似HTTP URI). +func (sp *SPath) formatCacheName(name string) string { + if runtime.GOOS != "linux" { + name = gstr.Replace(name, "\\", "/") + } + return "/" + strings.Trim(name, "./") +} + +// 根据path计算出对应的缓存name, dirPath为检索根目录路径 +func (sp *SPath) nameFromPath(filePath, rootPath string) string { + name := gstr.Replace(filePath, rootPath, "") + name = sp.formatCacheName(name) + return name +} + +// 按照一定数据结构生成缓存的数据项字符串 +func (sp *SPath) makeCacheValue(filePath string, isDir bool) string { + if isDir { + return filePath + "_D_" + } + return filePath + "_F_" +} + +// 按照一定数据结构解析数据项字符串 +func (sp *SPath) parseCacheValue(value string) (filePath string, isDir bool) { + if value[len(value) - 2 : len(value) - 1][0] == 'F' { + return value[: len(value) - 3], false + } + return value[: len(value) - 3], true +} + +// 添加path到缓存中(递归) +func (sp *SPath) addToCache(filePath, rootPath string) { + if sp.cache == nil { + return + } + // 首先添加自身 + idDir := gfile.IsDir(filePath) + sp.cache.SetIfNotExist(sp.nameFromPath(filePath, rootPath), sp.makeCacheValue(filePath, idDir)) + // 如果添加的是目录,那么需要递归添加 + if idDir { + if files, err := gfile.ScanDir(filePath, "*", true); err == nil { + //fmt.Println("gspath add to cache:", filePath, files) + for _, path := range files { + sp.cache.SetIfNotExist(sp.nameFromPath(path, rootPath), sp.makeCacheValue(path, gfile.IsDir(path))) + } + } else { + //fmt.Errorf(err.Error()) + } + } +} + +// 添加文件目录监控(递归),当目录下的文件有更新时,会同时更新缓存。 +// 这里需要注意的点是,由于添加监听是递归添加的,那么假如删除一个目录,那么该目录下的文件(包括目录)也会产生一条删除事件,总共会产生N条事件。 +func (sp *SPath) addMonitorByPath(path string) { + if sp.cache == nil { + return + } + gfsnotify.Add(path, func(event *gfsnotify.Event) { + //glog.Debug(event.String()) + switch { + case event.IsRemove(): + sp.cache.Remove(sp.nameFromPath(event.Path, path)) + + case event.IsRename(): + if !gfile.Exists(event.Path) { + sp.cache.Remove(sp.nameFromPath(event.Path, path)) + } + + case event.IsCreate(): + sp.addToCache(event.Path, path) + } + }, true) +} + +// 删除监听(递归) +func (sp *SPath) removeMonitorByPath(path string) { + if sp.cache == nil { + return + } + gfsnotify.Remove(path) +} \ No newline at end of file diff --git a/g/os/gview/gview.go b/g/os/gview/gview.go index 9fa6a3271..2b136fd08 100644 --- a/g/os/gview/gview.go +++ b/g/os/gview/gview.go @@ -54,7 +54,7 @@ func checkAndInitDefaultView() { // gfile.MainPkgPath() 用以判断是否开发环境 mainPkgPath := gfile.MainPkgPath() if gfile.MainPkgPath() == "" { - viewObj = New(gfile.SelfDir()) + viewObj = New(gfile.Pwd()) } else { viewObj = New(mainPkgPath) }