mirror of
https://gitee.com/johng/gf
synced 2026-06-06 16:21:40 +08:00
gfile/genv/gcmd/gjson/gparser改进,待测试
This commit is contained in:
1
TODO
1
TODO
@ -26,6 +26,7 @@ gvalid校验支持当第一个规则失败后便不再校验后续的规则,
|
||||
gvalid增加支持对[]rune的长度校验(一个中文占3个字节);
|
||||
ghttp.Request增加对输入参数的自动HtmlEncode机制;
|
||||
常量命名风格根据golint进行修改;
|
||||
开放rwmutex包,并将gjson的互斥锁使用自定义的mutex替换;
|
||||
文档完善:
|
||||
gconv struct tag、
|
||||
控制器及执行对象注册的Init&Shut方法、
|
||||
|
||||
@ -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{}
|
||||
|
||||
44
g/encoding/gjson/internal/rwmutex/mutex.go
Normal file
44
g/encoding/gjson/internal/rwmutex/mutex.go
Normal 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()
|
||||
}
|
||||
}
|
||||
@ -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
8
g/g.go
@ -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() {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
// 将所给定的路径转换为绝对路径
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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))
|
||||
}
|
||||
@ -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
11
geg/other/test2.go
Normal 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))
|
||||
}
|
||||
Reference in New Issue
Block a user