gfile/genv/gcmd/gjson/gparser改进,待测试

This commit is contained in:
john
2018-09-13 18:40:04 +08:00
parent fc2b832b22
commit edc94e8c0f
13 changed files with 176 additions and 109 deletions

1
TODO
View File

@ -26,6 +26,7 @@ gvalid校验支持当第一个规则失败后便不再校验后续的规则
gvalid增加支持对[]rune的长度校验(一个中文占3个字节)
ghttp.Request增加对输入参数的自动HtmlEncode机制
常量命名风格根据golint进行修改
开放rwmutex包并将gjson的互斥锁使用自定义的mutex替换
文档完善:
gconv struct tag、
控制器及执行对象注册的Init&Shut方法、

View File

@ -9,7 +9,6 @@
package gjson
import (
"sync"
"strings"
"strconv"
"io/ioutil"
@ -21,6 +20,7 @@ import (
"gitee.com/johng/gf/g/encoding/gtoml"
"gitee.com/johng/gf/g/util/gstr"
"time"
"gitee.com/johng/gf/g/encoding/gjson/internal/rwmutex"
)
const (
@ -29,37 +29,48 @@ const (
// json解析结果存放数组
type Json struct {
mu sync.RWMutex
mu *rwmutex.RWMutex
p *interface{} // 注意这是一个指针
c byte // 层级分隔符,默认为"."
vc bool // 层级检索是否执行分隔符冲突检测(默认为false检测会比较影响检索效率)
}
// 将变量转换为Json对象进行处理该变量至少应当是一个map或者array否者转换没有意义
func New(value interface{}) *Json {
switch value.(type) {
case map[string]interface{}:
return &Json{
p : &value,
c : byte(gDEFAULT_SPLIT_CHAR),
vc : false ,
}
case []interface{}:
return &Json{
p : &value,
c : byte(gDEFAULT_SPLIT_CHAR),
vc : false ,
}
default:
// 这里效率会比较低
b, _ := Encode(value)
v, _ := Decode(b)
return &Json{
p : &v,
c : byte(gDEFAULT_SPLIT_CHAR),
vc : false,
}
func New(value interface{}, safe...bool) *Json {
j := (*Json)(nil)
if value != nil {
switch value.(type) {
case map[string]interface{}:
j = &Json{
p : &value,
c : byte(gDEFAULT_SPLIT_CHAR),
vc : false ,
}
case []interface{}:
j = &Json{
p : &value,
c : byte(gDEFAULT_SPLIT_CHAR),
vc : false ,
}
default:
// 这里效率会比较低
b, _ := Encode(value)
v, _ := Decode(b)
j = &Json{
p : &v,
c : byte(gDEFAULT_SPLIT_CHAR),
vc : false,
}
}
} else {
j = &Json{
p : nil,
c : byte(gDEFAULT_SPLIT_CHAR),
vc : false,
}
}
j.mu = rwmutex.New(safe...)
return j
}
// 编码go变量为json字符串并返回json字符串指针
@ -100,7 +111,7 @@ func Load (path string) (*Json, error) {
return LoadContent(data, gfile.Ext(path))
}
// 支持的配置文件格式xml, json, yaml/yml, toml
// 支持的配置文件格式xml, json, yaml/yml, toml默认为json
func LoadContent (data []byte, dataType...string) (*Json, error) {
var err error
var result interface{}

View File

@ -0,0 +1,44 @@
package rwmutex
import "sync"
// RWMutex的封装支持对并发安全开启/关闭的控制。
// 但是只能初始化时确定并发安全性,不能在运行时动态修改并发安全特性设置。
type RWMutex struct {
sync.RWMutex
safe bool
}
func New(safe...bool) *RWMutex {
mu := new(RWMutex)
if len(safe) > 0 {
mu.safe = safe[0]
} else {
mu.safe = true
}
return mu
}
func (mu *RWMutex) Lock(force...bool) {
if mu.safe || (len(force) > 0 && force[0]) {
mu.RWMutex.Lock()
}
}
func (mu *RWMutex) Unlock(force...bool) {
if mu.safe || (len(force) > 0 && force[0]) {
mu.RWMutex.Unlock()
}
}
func (mu *RWMutex) RLock(force...bool) {
if mu.safe || (len(force) > 0 && force[0]) {
mu.RWMutex.RLock()
}
}
func (mu *RWMutex) RUnlock(force...bool) {
if mu.safe || (len(force) > 0 && force[0]) {
mu.RWMutex.RUnlock()
}
}

View File

@ -17,12 +17,9 @@ type Parser struct {
}
// 将变量转换为Parser对象进行处理该变量至少应当是一个map或者array否者转换没有意义
// 该参数为非必需参数,默认为创建一个空的Parser对象
func New (values...interface{}) *Parser {
if len(values) > 0 {
return &Parser{gjson.New(values[0])}
}
return &Parser{gjson.New(nil)}
// value可以传递nil, 表示创建一个空的Parser对象
func New (value interface{}, safe...bool) *Parser {
return &Parser{gjson.New(value, safe...)}
}
func Load (path string) (*Parser, error) {

8
g/g.go
View File

@ -27,10 +27,14 @@ const (
)
// 常用map数据结构(使用别名)
type Map = map[string]interface{}
type Map = map[string]interface{}
// 常用list数据结构(使用别名)
type List = []Map
type List = []Map
// 常用slice数据结构(使用别名)
type Slice = []interface{}
type Array = Slice
// 阻塞等待HTTPServer执行完成(同一进程多HTTPServer情况下)
func Wait() {

View File

@ -10,10 +10,8 @@ package gcmd
import (
"os"
"regexp"
"errors"
"strconv"
"strings"
"regexp"
)
// 命令行参数列表
@ -34,8 +32,8 @@ var cmdFuncMap = make(map[string]func()) // 终端命令及函数地址对应表
// 检查并初始化console参数在包加载的时候触发
// 初始化时执行,不影响运行时性能
func init() {
reg := regexp.MustCompile(`\-\-{0,1}(.+?)=(.+)`)
Option.options = make(map[string]string)
reg := regexp.MustCompile(`\-\-{0,1}(.+?)=(.+)`)
for i := 0; i < len(os.Args); i++ {
result := reg.FindStringSubmatch(os.Args[i])
if len(result) > 1 {
@ -57,59 +55,25 @@ func (c *gCmdOption) GetAll() map[string]string {
}
// 获得一条指定索引位置的value参数
func (c *gCmdValue) Get(index uint8) string {
func (c *gCmdValue) Get(index uint8, def...string) string {
if index < uint8(len(c.values)) {
return c.values[index]
} else if len(def) > 0 {
return def[0]
}
return ""
}
// 类型转换
func (c *gCmdValue) GetInt(key uint8) int {
if v := c.Get(key); v != "" {
i, _ := strconv.Atoi(v)
return i
}
return 0
}
// 类型转换bool
func (c *gCmdValue) GetBool(key uint8) bool {
v := c.Get(key)
v = strings.ToLower(v)
if v != "" && v != "0" && v != "false" {
return true
}
return false
}
// 获得一条指定索引位置的option参数;
func (c *gCmdOption) Get(key string) string {
func (c *gCmdOption) Get(key string, def...string) string {
if option, ok := c.options[key]; ok {
return option
} else if len(def) > 0 {
return def[0]
}
return ""
}
// 类型转换int
func (c *gCmdOption) GetInt(key string) int {
if v := c.Get(key); v != "" {
i, _ := strconv.Atoi(v)
return i
}
return 0
}
// 类型转换bool
func (c *gCmdOption) GetBool(key string) bool {
v := c.Get(key)
v = strings.ToLower(v)
if v != "" && v != "0" && v != "false" {
return true
}
return false
}
// 绑定命令行参数及对应的命令函数,注意命令函数参数是函数的内存地址
// 如果操作失败返回错误信息
func BindHandle (cmd string, f func()) error {

View File

@ -13,8 +13,13 @@ func All() []string {
return os.Environ()
}
func Get(k string) string {
return os.Getenv(k)
// 获取环境变量,并可以指定当环境变量不存在时的默认值
func Get(k string, def...string) string {
v, ok := os.LookupEnv(k)
if !ok && len(def) > 0 {
return def[0]
}
return v
}
func Set(k, v string) error {

View File

@ -11,7 +11,6 @@ import (
"os"
"io"
"io/ioutil"
"sort"
"fmt"
"time"
"strings"
@ -24,6 +23,7 @@ import (
"gitee.com/johng/gf/g/util/gregex"
"gitee.com/johng/gf/g/container/gtype"
"gitee.com/johng/gf/g/os/gfilepool"
"sort"
)
// 封装了常用的文件操作方法如需更详细的文件控制请查看官方os包
@ -241,9 +241,20 @@ func Copy(src string, dst string) error {
return nil
}
// 文件名正则匹配查找
func Glob(pattern string) ([]string, error) {
return filepath.Glob(pattern)
// 文件名正则匹配查找,第二个可选参数指定返回的列表是否仅为文件名(非绝对路径),默认返回绝对路径
func Glob(pattern string, onlyNames...bool) ([]string, error) {
if list, err := filepath.Glob(pattern); err == nil {
if len(onlyNames) > 0 && onlyNames[0] && len(list) > 0 {
array := make([]string, len(list))
for k, v := range list {
array[k] = Basename(v)
}
return array, nil
}
return list, nil
} else {
return nil, err
}
}
// 文件/目录删除
@ -290,32 +301,49 @@ func Chmod(path string, mode os.FileMode) error {
return os.Chmod(path, mode)
}
// 打开目录,并返回其下一级子目录名称列表,按照文件名称大小写进行排序,支持目录递归遍历。
// 当递归遍历时,结果集返回的是子级文件/目录的绝对路径,而不仅仅是一个名字
func ScanDir(path string, recursive ... bool) []string {
f, err := os.Open(path)
// 打开目录,并返回其下一级文件列表(绝对路径),按照文件名称大小写进行排序,支持目录递归遍历。
func ScanDir(path string, pattern string, recursive ... bool) ([]string, error) {
list, err := doScanDir(path, pattern, recursive...)
if err != nil {
return nil
return nil, err
}
if len(list) > 0 {
sort.Strings(list)
}
return list, nil
}
list, err := f.Readdirnames(-1)
f.Close()
// 内部检索目录方法,支持递归,返回没有排序的文件绝对路径列表结果
func doScanDir(path string, pattern string, recursive ... bool) ([]string, error) {
var list []string
// 打开目录
dfile, err := os.Open(path)
if err != nil {
return nil
return nil, err
}
defer dfile.Close()
// 读取目录下的文件列表
names, err := dfile.Readdirnames(-1)
if err != nil {
return nil, err
}
// 是否递归遍历
if len(recursive) > 0 && recursive[0] && len(list) > 0 {
for k, v := range list {
p := fmt.Sprintf("%s%s%s", path, Separator, v)
list[k] = p
if IsDir(p) {
list = append(list, ScanDir(p, true)...)
if len(recursive) > 0 && recursive[0] && len(names) > 0 {
for _, name := range names {
path := fmt.Sprintf("%s%s%s", path, Separator, name)
if IsDir(path) {
array, _ := doScanDir(path, pattern, true)
if len(array) > 0 {
list = append(list, array...)
}
}
// 满足pattern才加入结果列表
if match, err := filepath.Match(pattern, name); err == nil && match {
list = append(list, path)
}
}
}
// 默认按照字符串大小排序
sort.Slice(list, func(i, j int) bool { return list[i] < list[j] })
return list
return list, nil
}
// 将所给定的路径转换为绝对路径

View File

@ -113,8 +113,9 @@ func (w *Watcher) addWatch(path string, callback func(event *Event)) error {
// 递归添加监控
func (w *Watcher) Add(path string, callback func(event *Event)) error {
if gfile.IsDir(path) {
list := []string{path}
list = append(list, gfile.ScanDir(path, true)...)
paths, _ := gfile.ScanDir(path, "*", true)
list := []string{path}
list = append(list, paths...)
for _, v := range list {
if err := w.addWatch(v, callback); err != nil {
return err
@ -136,8 +137,9 @@ func (w *Watcher) removeWatch(path string) error {
// 递归移除监听
func (w *Watcher) Remove(path string) error {
if gfile.IsDir(path) {
paths, _ := gfile.ScanDir(path, "*", true)
list := []string{path}
list = append(list, gfile.ScanDir(path, true)...)
list = append(list, paths...)
for _, v := range list {
if err := w.removeWatch(v); err != nil {
return err

View File

@ -4,6 +4,7 @@ package main
import (
"gitee.com/johng/gf/g/os/gfile"
"fmt"
"gitee.com/johng/gf/g/util/gutil"
)
var dirpath1 = "/home/john/Workspace/temp/"
@ -22,8 +23,7 @@ func info () {
}
func scanDir() {
files := gfile.ScanDir(dirpath1)
fmt.Println(files)
gutil.Dump(gfile.ScanDir(dirpath1, "*"))
}
func getContents() {

View File

@ -6,6 +6,6 @@ import (
)
func main() {
gutil.Dump(gfile.ScanDir("/home/john/Documents"))
gutil.Dump(gfile.ScanDir("/home/john/temp/newproject", true))
gutil.Dump(gfile.ScanDir("/home/john/Documents", "*"))
gutil.Dump(gfile.ScanDir("/home/john/temp/newproject", "*", true))
}

View File

@ -8,7 +8,7 @@ import (
)
func main() {
files := gfile.ScanDir("/home/john/Workspace/med3-svr", true)
files, _ := gfile.ScanDir("/home/john/Workspace/med3-svr", "*", true)
for _, file := range files {
if strings.Index(gfcache.GetContents(file), "ENV") != -1 {
fmt.Println(file)

11
geg/other/test2.go Normal file
View File

@ -0,0 +1,11 @@
package main
import (
"gitee.com/johng/gf/g/util/gutil"
"gitee.com/johng/gf/g/os/gfile"
)
func main() {
gutil.Dump(gfile.ScanDir("/tmp", "*test*"))
gutil.Dump(gfile.Glob("/tmp/*", true))
}