mirror of
https://gitee.com/johng/gf
synced 2026-06-10 19:31:44 +08:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 630d8fdb43 | |||
| c4c7e6caf4 | |||
| 8a8fea1257 | |||
| 0e0f297a3f | |||
| fd2c0f2b24 | |||
| ecc6e3888d | |||
| 47c073aaf3 | |||
| 07476a4349 | |||
| 817148f3a1 | |||
| bd4271cd8c | |||
| a05361011f | |||
| 6b34a77251 |
@ -14,6 +14,7 @@ import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/gmap"
|
||||
"github.com/gogf/gf/g/container/gring"
|
||||
"github.com/gogf/gf/g/container/gtype"
|
||||
"github.com/gogf/gf/g/container/gvar"
|
||||
@ -155,22 +156,26 @@ const (
|
||||
gDEFAULT_BATCH_NUM = 10
|
||||
// 默认的连接池连接存活时间(秒)
|
||||
gDEFAULT_CONN_MAX_LIFE_TIME = 30
|
||||
)
|
||||
|
||||
var (
|
||||
// 单例对象Map
|
||||
instances = gmap.NewStringInterfaceMap()
|
||||
)
|
||||
|
||||
// 使用默认/指定分组配置进行连接,数据库集群配置项:default
|
||||
func New(groupName ...string) (db DB, err error) {
|
||||
group := config.d
|
||||
if len(groupName) > 0 {
|
||||
group = groupName[0]
|
||||
func New(name...string) (db DB, err error) {
|
||||
group := configs.defaultGroup
|
||||
if len(name) > 0 {
|
||||
group = name[0]
|
||||
}
|
||||
config.RLock()
|
||||
defer config.RUnlock()
|
||||
configs.RLock()
|
||||
defer configs.RUnlock()
|
||||
|
||||
if len(config.c) < 1 {
|
||||
if len(configs.config) < 1 {
|
||||
return nil, errors.New("empty database configuration")
|
||||
}
|
||||
if _, ok := config.c[group]; ok {
|
||||
if _, ok := configs.config[group]; ok {
|
||||
if node, err := getConfigNodeByGroup(group, true); err == nil {
|
||||
base := &dbBase {
|
||||
group : group,
|
||||
@ -204,9 +209,25 @@ func New(groupName ...string) (db DB, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// 获得数据库操作对象单例
|
||||
func Instance(name...string) (db DB, err error) {
|
||||
group := configs.defaultGroup
|
||||
if len(name) > 0 {
|
||||
group = name[0]
|
||||
}
|
||||
v := instances.GetOrSetFuncLock(group, func() interface{} {
|
||||
db, err = New(group)
|
||||
return db
|
||||
})
|
||||
if v != nil {
|
||||
return v.(DB), nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 获取指定数据库角色的一个配置项,内部根据权重计算负载均衡
|
||||
func getConfigNodeByGroup(group string, master bool) (*ConfigNode, error) {
|
||||
if list, ok := config.c[group]; ok {
|
||||
if list, ok := configs.config[group]; ok {
|
||||
// 将master, slave集群列表拆分出来
|
||||
masterList := make(ConfigGroup, 0)
|
||||
slaveList := make(ConfigGroup, 0)
|
||||
@ -319,17 +340,17 @@ func (bs *dbBase) getSqlDb(master bool) (sqlDb *sql.DB, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// 切换操作的数据库(注意该切换是全局的)
|
||||
// 切换当前数据库对象操作的数据库。
|
||||
func (bs *dbBase) SetSchema(schema string) {
|
||||
bs.schema.Set(schema)
|
||||
}
|
||||
|
||||
// 创建底层数据库master链接对象
|
||||
// 创建底层数据库master链接对象。
|
||||
func (bs *dbBase) Master() (*sql.DB, error) {
|
||||
return bs.getSqlDb(true)
|
||||
}
|
||||
|
||||
// 创建底层数据库slave链接对象
|
||||
// 创建底层数据库slave链接对象。
|
||||
func (bs *dbBase) Slave() (*sql.DB, error) {
|
||||
return bs.getSqlDb(false)
|
||||
}
|
||||
|
||||
@ -17,14 +17,7 @@ const (
|
||||
DEFAULT_GROUP_NAME = "default" // 默认配置名称
|
||||
)
|
||||
|
||||
// 数据库配置包内对象
|
||||
var config struct {
|
||||
sync.RWMutex
|
||||
c Config // 数据库配置
|
||||
d string // 默认数据库分组名称
|
||||
}
|
||||
|
||||
// 数据库配置
|
||||
// 数据库分组配置
|
||||
type Config map[string]ConfigGroup
|
||||
|
||||
// 数据库集群配置
|
||||
@ -41,12 +34,19 @@ type ConfigNode struct {
|
||||
Role string // (可选,默认为master)数据库的角色,用于主从操作分离,至少需要有一个master,参数值:master, slave
|
||||
Charset string // (可选,默认为 utf8)编码,默认为 utf8
|
||||
Priority int // (可选)用于负载均衡的权重计算,当集群中只有一个节点时,权重没有任何意义
|
||||
Linkinfo string // (可选)自定义链接信息,当该字段被设置值时,以上链接字段(Host,Port,User,Pass,Name)将失效(该字段是一个扩展功能)
|
||||
LinkInfo string // (可选)自定义链接信息,当该字段被设置值时,以上链接字段(Host,Port,User,Pass,Name)将失效(该字段是一个扩展功能)
|
||||
MaxIdleConnCount int // (可选)连接池最大限制的连接数
|
||||
MaxOpenConnCount int // (可选)连接池最大打开的连接数
|
||||
MaxConnLifetime int // (可选,单位秒)连接对象可重复使用的时间长度
|
||||
}
|
||||
|
||||
// 数据库配置包内对象
|
||||
var configs struct {
|
||||
sync.RWMutex // 并发安全互斥锁
|
||||
config Config // 数据库分组配置
|
||||
defaultGroup string // 默认数据库分组名称
|
||||
}
|
||||
|
||||
// 数据库集群配置示例,支持主从处理,多数据库集群支持
|
||||
/*
|
||||
var DatabaseConfiguration = Config {
|
||||
@ -80,29 +80,32 @@ var DatabaseConfiguration = Config {
|
||||
|
||||
// 包初始化
|
||||
func init() {
|
||||
config.c = make(Config)
|
||||
config.d = DEFAULT_GROUP_NAME
|
||||
configs.config = make(Config)
|
||||
configs.defaultGroup = DEFAULT_GROUP_NAME
|
||||
}
|
||||
|
||||
// 设置当前应用的数据库配置信息,进行全局数据库配置覆盖操作
|
||||
func SetConfig (c Config) {
|
||||
config.Lock()
|
||||
defer config.Unlock()
|
||||
config.c = c
|
||||
func SetConfig (config Config) {
|
||||
defer instances.Clear()
|
||||
configs.Lock()
|
||||
defer configs.Unlock()
|
||||
configs.config = config
|
||||
}
|
||||
|
||||
// 添加数据库服务器集群配置
|
||||
func AddConfigGroup (group string, nodes ConfigGroup) {
|
||||
config.Lock()
|
||||
config.c[group] = nodes
|
||||
config.Unlock()
|
||||
defer instances.Clear()
|
||||
configs.Lock()
|
||||
defer configs.Unlock()
|
||||
configs.config[group] = nodes
|
||||
}
|
||||
|
||||
// 添加一台数据库服务器配置
|
||||
func AddConfigNode (group string, node ConfigNode) {
|
||||
config.Lock()
|
||||
config.c[group] = append(config.c[group], node)
|
||||
config.Unlock()
|
||||
defer instances.Clear()
|
||||
configs.Lock()
|
||||
defer configs.Unlock()
|
||||
configs.config[group] = append(configs.config[group], node)
|
||||
}
|
||||
|
||||
// 添加默认链接的一台数据库服务器配置
|
||||
@ -117,16 +120,25 @@ func AddDefaultConfigGroup (nodes ConfigGroup) {
|
||||
|
||||
// 添加一台数据库服务器配置
|
||||
func GetConfig (group string) ConfigGroup {
|
||||
config.RLock()
|
||||
defer config.RUnlock()
|
||||
return config.c[group]
|
||||
configs.RLock()
|
||||
defer configs.RUnlock()
|
||||
return configs.config[group]
|
||||
}
|
||||
|
||||
// 设置默认链接的数据库链接配置项(默认是 default)
|
||||
func SetDefaultGroup (groupName string) {
|
||||
config.Lock()
|
||||
config.d = groupName
|
||||
config.Unlock()
|
||||
func SetDefaultGroup (name string) {
|
||||
defer instances.Clear()
|
||||
configs.Lock()
|
||||
defer configs.Unlock()
|
||||
configs.defaultGroup = name
|
||||
}
|
||||
|
||||
// 获取默认链接的数据库链接配置项(默认是 default)
|
||||
func GetDefaultGroup() string {
|
||||
defer instances.Clear()
|
||||
configs.Lock()
|
||||
defer configs.Unlock()
|
||||
return configs.defaultGroup
|
||||
}
|
||||
|
||||
// 设置数据库连接池中空闲链接的大小
|
||||
@ -147,8 +159,8 @@ func (bs *dbBase) SetConnMaxLifetime(n int) {
|
||||
|
||||
// 节点配置转换为字符串
|
||||
func (node *ConfigNode) String() string {
|
||||
if node.Linkinfo != "" {
|
||||
return node.Linkinfo
|
||||
if node.LinkInfo != "" {
|
||||
return node.LinkInfo
|
||||
}
|
||||
return fmt.Sprintf(`%s@%s:%s,%s,%s,%s,%s,%d-%d-%d`, node.User, node.Host, node.Port,
|
||||
node.Name, node.Type, node.Role, node.Charset,
|
||||
|
||||
@ -30,8 +30,8 @@ type dbMssql struct {
|
||||
// 创建SQL操作对象
|
||||
func (db *dbMssql) Open(config *ConfigNode) (*sql.DB, error) {
|
||||
source := ""
|
||||
if config.Linkinfo != "" {
|
||||
source = config.Linkinfo
|
||||
if config.LinkInfo != "" {
|
||||
source = config.LinkInfo
|
||||
} else {
|
||||
source = fmt.Sprintf("user id=%s;password=%s;server=%s;port=%s;database=%s;encrypt=disable",
|
||||
config.User, config.Pass, config.Host, config.Port, config.Name)
|
||||
|
||||
@ -20,8 +20,8 @@ type dbMysql struct {
|
||||
// 创建SQL操作对象,内部采用了lazy link处理
|
||||
func (db *dbMysql) Open (config *ConfigNode) (*sql.DB, error) {
|
||||
var source string
|
||||
if config.Linkinfo != "" {
|
||||
source = config.Linkinfo
|
||||
if config.LinkInfo != "" {
|
||||
source = config.LinkInfo
|
||||
} else {
|
||||
source = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=%s&multiStatements=true",
|
||||
config.User, config.Pass, config.Host, config.Port, config.Name, config.Charset)
|
||||
|
||||
@ -30,8 +30,8 @@ type dbOracle struct {
|
||||
// 创建SQL操作对象
|
||||
func (db *dbOracle) Open(config *ConfigNode) (*sql.DB, error) {
|
||||
var source string
|
||||
if config.Linkinfo != "" {
|
||||
source = config.Linkinfo
|
||||
if config.LinkInfo != "" {
|
||||
source = config.LinkInfo
|
||||
} else {
|
||||
source = fmt.Sprintf("%s/%s@%s", config.User, config.Pass, config.Name)
|
||||
}
|
||||
|
||||
@ -26,8 +26,8 @@ type dbPgsql struct {
|
||||
// 创建SQL操作对象,内部采用了lazy link处理
|
||||
func (db *dbPgsql) Open (config *ConfigNode) (*sql.DB, error) {
|
||||
var source string
|
||||
if config.Linkinfo != "" {
|
||||
source = config.Linkinfo
|
||||
if config.LinkInfo != "" {
|
||||
source = config.LinkInfo
|
||||
} else {
|
||||
source = fmt.Sprintf("user=%s password=%s host=%s port=%s dbname=%s", config.User, config.Pass, config.Host, config.Port, config.Name)
|
||||
}
|
||||
|
||||
@ -24,8 +24,8 @@ type dbSqlite struct {
|
||||
|
||||
func (db *dbSqlite) Open(config *ConfigNode) (*sql.DB, error) {
|
||||
var source string
|
||||
if config.Linkinfo != "" {
|
||||
source = config.Linkinfo
|
||||
if config.LinkInfo != "" {
|
||||
source = config.LinkInfo
|
||||
} else {
|
||||
source = config.Name
|
||||
}
|
||||
|
||||
28
g/database/gdb/gdb_unit_basic_test.go
Normal file
28
g/database/gdb/gdb_unit_basic_test.go
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2019 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 gdb_test
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/database/gdb"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_Instance(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
_, err := gdb.Instance("none")
|
||||
gtest.AssertNE(err, nil)
|
||||
|
||||
db, err := gdb.Instance()
|
||||
gtest.Assert(err, nil)
|
||||
|
||||
err1 := db.PingMaster()
|
||||
err2 := db.PingSlave()
|
||||
gtest.Assert(err1, nil)
|
||||
gtest.Assert(err2, nil)
|
||||
})
|
||||
}
|
||||
@ -4,10 +4,11 @@
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
// Package gredis provides client for redis server.
|
||||
// Package gredis provides convenient client for redis server.
|
||||
//
|
||||
// Redis客户端.
|
||||
// Redis中文手册文档请参考:http://redisdoc.com/ , Redis官方命令请参考:https://redis.io/commands
|
||||
// Redis中文手册请参考:http://redisdoc.com/
|
||||
// Redis官方命令请参考:https://redis.io/commands
|
||||
package gredis
|
||||
|
||||
import (
|
||||
@ -24,8 +25,9 @@ const (
|
||||
|
||||
// Redis客户端(管理连接池)
|
||||
type Redis struct {
|
||||
pool *redis.Pool
|
||||
config Config
|
||||
pool *redis.Pool // 底层连接池
|
||||
group string // 配置分组
|
||||
config Config // 配置对象
|
||||
}
|
||||
|
||||
// Redis连接对象(连接池中的单个连接)
|
||||
@ -48,13 +50,17 @@ type PoolStats struct {
|
||||
redis.PoolStats
|
||||
}
|
||||
|
||||
// 连接池map
|
||||
var pools = gmap.NewStringInterfaceMap()
|
||||
var (
|
||||
// 单例对象Map
|
||||
instances = gmap.NewStringInterfaceMap()
|
||||
// 连接池Map
|
||||
pools = gmap.NewStringInterfaceMap()
|
||||
)
|
||||
|
||||
// New creates a redis client object with given configuration.
|
||||
// Redis client maintains a connection pool automatically.
|
||||
//
|
||||
// 创建redis操作对象.
|
||||
// 创建redis操作对象,底层根据配置信息公用的连接池(连接池单例)。
|
||||
func New(config Config) *Redis {
|
||||
if config.IdleTimeout == 0 {
|
||||
config.IdleTimeout = gDEFAULT_POOL_IDLE_TIMEOUT
|
||||
@ -96,11 +102,41 @@ func New(config Config) *Redis {
|
||||
}
|
||||
}
|
||||
|
||||
// Instance returns an instance of redis client with specified group.
|
||||
// The <group> param is unnecessary, if <group> is not passed,
|
||||
// return redis instance with default group.
|
||||
//
|
||||
// 获取指定分组名称的Redis单例对象,底层根据配置信息公用的连接池(连接池单例)。
|
||||
func Instance(name...string) *Redis {
|
||||
group := DEFAULT_GROUP_NAME
|
||||
if len(name) > 0 {
|
||||
group = name[0]
|
||||
}
|
||||
v := instances.GetOrSetFuncLock(group, func() interface{} {
|
||||
if config, ok := GetConfig(group); ok {
|
||||
r := New(config)
|
||||
r.group = group
|
||||
return r
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if v != nil {
|
||||
return v.(*Redis)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close closes the redis connection pool,
|
||||
// it will release all connections reserved by this pool.
|
||||
// It always not necessary to call Close manually.
|
||||
//
|
||||
// 关闭redis管理对象,将会关闭底层的连接池。
|
||||
// 往往没必要手动调用,跟随进程销毁即可。
|
||||
func (r *Redis) Close() error {
|
||||
if r.group != "" {
|
||||
// 如果是单例对象,那么需要从单例对象Map中删除
|
||||
instances.Remove(r.group)
|
||||
}
|
||||
pools.Remove(fmt.Sprintf("%v", r.config))
|
||||
return r.pool.Close()
|
||||
}
|
||||
|
||||
69
g/database/gredis/gredis_config.go
Normal file
69
g/database/gredis/gredis_config.go
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright 2019 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 gredis
|
||||
|
||||
import "github.com/gogf/gf/g/container/gmap"
|
||||
|
||||
const (
|
||||
// 默认分组名称
|
||||
DEFAULT_GROUP_NAME = "default"
|
||||
)
|
||||
var (
|
||||
// 分组配置
|
||||
configs = gmap.NewStringInterfaceMap()
|
||||
)
|
||||
|
||||
// SetConfig sets the global configuration for specified group.
|
||||
// If <name> is not passed, it sets configuration for the default group name.
|
||||
//
|
||||
// 设置全局分组配置,name为非必需参数,默认为默认分组名称。
|
||||
func SetConfig(config Config, name...string) {
|
||||
group := DEFAULT_GROUP_NAME
|
||||
if len(name) > 0 {
|
||||
group = name[0]
|
||||
}
|
||||
configs.Set(group, config)
|
||||
instances.Remove(group)
|
||||
}
|
||||
|
||||
// GetConfig returns the global configuration with specified group.
|
||||
// If <group> is not passed, it returns configuration of the default group name.
|
||||
//
|
||||
// 获取指定全局分组配置,group为非必需参数,默认为默认分组名称。
|
||||
func GetConfig(name...string) (config Config, ok bool) {
|
||||
group := DEFAULT_GROUP_NAME
|
||||
if len(name) > 0 {
|
||||
group = name[0]
|
||||
}
|
||||
if v := configs.Get(group); v != nil {
|
||||
return v.(Config), true
|
||||
}
|
||||
return Config{}, false
|
||||
}
|
||||
|
||||
// RemoveConfig removes the global configuration with specified group.
|
||||
// If <name> is not passed, it removes configuration of the default group name.
|
||||
//
|
||||
// 删除指定全局分组配置,name为非必需参数,默认为默认分组名称。
|
||||
func RemoveConfig(name...string) {
|
||||
group := DEFAULT_GROUP_NAME
|
||||
if len(name) > 0 {
|
||||
group = name[0]
|
||||
}
|
||||
configs.Remove(group)
|
||||
instances.Remove(group)
|
||||
}
|
||||
|
||||
// ClearConfig removes all configurations and instances of redis.
|
||||
//
|
||||
// 清除所有的配置内容。
|
||||
func ClearConfig() {
|
||||
configs.Clear()
|
||||
instances.Clear()
|
||||
}
|
||||
|
||||
|
||||
@ -99,6 +99,33 @@ func Test_Conn(t *testing.T) {
|
||||
conn := redis.Conn()
|
||||
defer conn.Close()
|
||||
|
||||
|
||||
r, err := conn.Do("GET", "k")
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(r, []byte("v"))
|
||||
|
||||
_, err = conn.Do("DEL", "k")
|
||||
gtest.Assert(err, nil)
|
||||
r, err = conn.Do("GET", "k")
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(r, nil)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Instance(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
group := "my-test"
|
||||
gredis.SetConfig(config, group)
|
||||
defer gredis.RemoveConfig(group)
|
||||
redis := gredis.Instance(group)
|
||||
defer redis.Close()
|
||||
|
||||
conn := redis.Conn()
|
||||
defer conn.Close()
|
||||
|
||||
_, err := conn.Do("SET", "k", "v")
|
||||
gtest.Assert(err, nil)
|
||||
|
||||
r, err := conn.Do("GET", "k")
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(r, []byte("v"))
|
||||
|
||||
@ -4,9 +4,7 @@
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
// Package gjson provides flexible and useful API for JSON/XML/YAML/TOML content handling.
|
||||
//
|
||||
// JSON/XML/YAML/TOML数据格式处理。
|
||||
// Package gjson provides convenient API for JSON/XML/YAML/TOML data handling.
|
||||
package gjson
|
||||
|
||||
import (
|
||||
@ -19,7 +17,6 @@ import (
|
||||
"github.com/gogf/gf/g/encoding/gyaml"
|
||||
"github.com/gogf/gf/g/internal/rwmutex"
|
||||
"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"
|
||||
@ -30,18 +27,24 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
gDEFAULT_SPLIT_CHAR = '.' // 默认层级分隔符号
|
||||
// Separator char for hierarchical data access.
|
||||
gDEFAULT_SPLIT_CHAR = '.'
|
||||
)
|
||||
|
||||
// json解析结果存放数组
|
||||
// The customized JSON struct.
|
||||
type Json struct {
|
||||
mu *rwmutex.RWMutex
|
||||
p *interface{} // 注意这是一个指针
|
||||
c byte // 层级分隔符,默认为"."
|
||||
vc bool // 层级检索是否执行分隔符冲突检测(默认为false,检测会比较影响检索效率)
|
||||
p *interface{} // Pointer for hierarchical data access, it's the root of data in default.
|
||||
c byte // Char separator('.' in default).
|
||||
vc bool // Violence Check(false in default), which is used to access data
|
||||
// when the hierarchical data key contains separator char.
|
||||
}
|
||||
|
||||
// 将变量转换为Json对象进行处理,该变量至少应当是一个map或者slice,否者转换没有意义
|
||||
// New creates a Json object with any variable type of <data>,
|
||||
// but <data> should be a map or slice for data access reason,
|
||||
// or it will make no sense.
|
||||
// The <unsafe> param specifies whether using this Json object
|
||||
// in un-concurrent-safe context, which is false in default.
|
||||
func New(data interface{}, unsafe...bool) *Json {
|
||||
j := (*Json)(nil)
|
||||
switch data.(type) {
|
||||
@ -75,7 +78,7 @@ func New(data interface{}, unsafe...bool) *Json {
|
||||
return j
|
||||
}
|
||||
|
||||
// 创建一个非并发安全的Json对象
|
||||
// NewUnsafe creates a un-concurrent-safe Json object.
|
||||
func NewUnsafe(data...interface{}) *Json {
|
||||
if len(data) > 0 {
|
||||
return New(data[0], true)
|
||||
@ -83,17 +86,17 @@ func NewUnsafe(data...interface{}) *Json {
|
||||
return New(nil, true)
|
||||
}
|
||||
|
||||
// 识别当前给定内容是否为JSON格式
|
||||
// Valid checks whether <data> is a valid JSON data type.
|
||||
func Valid(data interface{}) bool {
|
||||
return json.Valid(gconv.Bytes(data))
|
||||
}
|
||||
|
||||
// 编码go变量为json字符串,并返回json字符串指针
|
||||
// Encode encodes <value> to JSON data type of bytes.
|
||||
func Encode(value interface{}) ([]byte, error) {
|
||||
return json.Marshal(value)
|
||||
}
|
||||
|
||||
// 解码字符串/[]byte为interface{}变量
|
||||
// Decode decodes <data>(string/[]byte) to golang variable.
|
||||
func Decode(data interface{}) (interface{}, error) {
|
||||
var value interface{}
|
||||
if err := DecodeTo(gconv.Bytes(data), &value); err != nil {
|
||||
@ -103,58 +106,63 @@ func Decode(data interface{}) (interface{}, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// 解析json字符串/[]byte为go变量,注意第二个参数为指针(任意结构的变量)
|
||||
// Decode decodes <data>(string/[]byte) to specified golang variable <v>.
|
||||
// The <v> should be a pointer type.
|
||||
func DecodeTo(data interface{}, v interface{}) error {
|
||||
decoder := json.NewDecoder(bytes.NewReader(gconv.Bytes(data)))
|
||||
decoder.UseNumber()
|
||||
return decoder.Decode(v)
|
||||
}
|
||||
|
||||
// 解析json字符串为gjson.Json对象,并返回操作对象指针
|
||||
func DecodeToJson(data interface{}) (*Json, error) {
|
||||
// DecodeToJson codes <data>(string/[]byte) to a Json object.
|
||||
func DecodeToJson(data interface{}, unsafe...bool) (*Json, error) {
|
||||
if v, err := Decode(gconv.Bytes(data)); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return New(v), nil
|
||||
return New(v, unsafe...), nil
|
||||
}
|
||||
}
|
||||
|
||||
// 支持多种配置文件类型转换为json格式内容并解析为gjson.Json对象
|
||||
func Load(path string) (*Json, error) {
|
||||
return LoadContent(gfcache.GetBinContents(path), gfile.Ext(path))
|
||||
// Load loads content from specified file <path>,
|
||||
// and creates a Json object from its content.
|
||||
func Load(path string, unsafe...bool) (*Json, error) {
|
||||
return LoadContent(gfcache.GetBinContents(path), unsafe...)
|
||||
}
|
||||
|
||||
// 支持的配置文件格式:xml, json, yaml/yml, toml,
|
||||
// 默认为自动识别,当无法检测成功时使用json解析。
|
||||
func LoadContent(data interface{}, dataType...string) (*Json, error) {
|
||||
// LoadContent creates a Json object from given content,
|
||||
// it checks the data type of <content> automatically,
|
||||
// supporting JSON, XML, YAML and TOML types of data.
|
||||
func LoadContent(data interface{}, unsafe...bool) (*Json, error) {
|
||||
var err error
|
||||
var result interface{}
|
||||
b := gconv.Bytes(data)
|
||||
t := "json"
|
||||
if len(dataType) > 0 {
|
||||
t = dataType[0]
|
||||
// auto check data type
|
||||
if json.Valid(b) {
|
||||
t = "json"
|
||||
} else if gregex.IsMatch(`^<.+>.*</.+>$`, b) {
|
||||
t = "xml"
|
||||
} else if gregex.IsMatch(`^[\s\t]*\w+\s*:\s*.+`, b) || gregex.IsMatch(`\n[\s\t]*\w+\s*:\s*.+`, b) {
|
||||
t = "yml"
|
||||
} else if gregex.IsMatch(`^[\s\t]*\w+\s*=\s*.+`, b) || gregex.IsMatch(`\n[\s\t]*\w+\s*=\s*.+`, b) {
|
||||
t = "toml"
|
||||
} else {
|
||||
if json.Valid(b) {
|
||||
t = "json"
|
||||
} else if gregex.IsMatch(`<.+>.*</.+>`, b) {
|
||||
t = "xml"
|
||||
} else if gregex.IsMatch(`\w+\s*:\s*.+`, b) {
|
||||
t = "yml"
|
||||
} else if gregex.IsMatch(`\w+\s*=\s*.+`, b) {
|
||||
t = "toml"
|
||||
}
|
||||
return nil, errors.New("unsupported data type")
|
||||
}
|
||||
// 其他数据格式解析
|
||||
// convert to json type data
|
||||
switch t {
|
||||
case "json", ".json":
|
||||
// ok
|
||||
case "xml", ".xml":
|
||||
// TODO UseNumber
|
||||
b, err = gxml.ToJson(b)
|
||||
|
||||
case "yml", "yaml", ".yml", ".yaml":
|
||||
// TODO UseNumber
|
||||
b, err = gyaml.ToJson(b)
|
||||
|
||||
case "toml", ".toml":
|
||||
// TODO UseNumber
|
||||
b, err = gtoml.ToJson(b)
|
||||
|
||||
default:
|
||||
@ -169,27 +177,31 @@ func LoadContent(data interface{}, dataType...string) (*Json, error) {
|
||||
if err := decoder.Decode(&result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch result.(type) {
|
||||
case string, []byte:
|
||||
return nil, fmt.Errorf(`json decoding failed for content: %s`, string(b))
|
||||
}
|
||||
}
|
||||
return New(result), nil
|
||||
return New(result, unsafe...), nil
|
||||
}
|
||||
|
||||
// 设置自定义的层级分隔符号
|
||||
// SetSplitChar sets the separator char for hierarchical data access.
|
||||
func (j *Json) SetSplitChar(char byte) {
|
||||
j.mu.Lock()
|
||||
j.c = char
|
||||
j.mu.Unlock()
|
||||
}
|
||||
|
||||
// 设置是否执行层级冲突检查,当键名中存在层级符号时需要开启该特性,默认为关闭。
|
||||
// 开启比较耗性能,也不建议允许键名中存在分隔符,最好在应用端避免这种情况。
|
||||
func (j *Json) SetViolenceCheck(check bool) {
|
||||
// SetViolenceCheck enables/disables violence check for hierarchical data access.
|
||||
func (j *Json) SetViolenceCheck(enabled bool) {
|
||||
j.mu.Lock()
|
||||
j.vc = check
|
||||
j.vc = enabled
|
||||
j.mu.Unlock()
|
||||
}
|
||||
|
||||
// 将指定的json内容转换为指定结构返回,查找失败或者转换失败,目标对象转换为nil
|
||||
// 注意第二个参数需要给的是**变量地址**
|
||||
// GetToVar gets the value by specified <pattern>,
|
||||
// and converts it to specified golang variable <v>.
|
||||
// The <v> should be a pointer type.
|
||||
func (j *Json) GetToVar(pattern string, v interface{}) error {
|
||||
r := j.Get(pattern)
|
||||
if r != nil {
|
||||
@ -204,19 +216,18 @@ func (j *Json) GetToVar(pattern string, v interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获得一个键值对关联数组/哈希表,方便操作,不需要自己做类型转换
|
||||
// 注意,如果获取的值不存在,或者类型与json类型不匹配,那么将会返回nil
|
||||
// GetMap gets the value by specified <pattern>,
|
||||
// and converts it to map[string]interface{}.
|
||||
func (j *Json) GetMap(pattern string) map[string]interface{} {
|
||||
result := j.Get(pattern)
|
||||
if result != nil {
|
||||
if r, ok := result.(map[string]interface{}); ok {
|
||||
return r
|
||||
}
|
||||
return gconv.Map(result)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 将检索值转换为Json对象指针返回。
|
||||
// GetJson gets the value by specified <pattern>,
|
||||
// and converts it to a Json object.
|
||||
func (j *Json) GetJson(pattern string) *Json {
|
||||
result := j.Get(pattern)
|
||||
if result != nil {
|
||||
@ -225,7 +236,8 @@ func (j *Json) GetJson(pattern string) *Json {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 将检索值转换为Json对象指针数组返回。
|
||||
// GetJsons gets the value by specified <pattern>,
|
||||
// and converts it to a slice of Json object.
|
||||
func (j *Json) GetJsons(pattern string) []*Json {
|
||||
array := j.GetArray(pattern)
|
||||
if len(array) > 0 {
|
||||
@ -238,21 +250,25 @@ func (j *Json) GetJsons(pattern string) []*Json {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获得一个数组[]interface{},方便操作,不需要自己做类型转换。
|
||||
// GetArray gets the value by specified <pattern>,
|
||||
// and converts it to a slice of []interface{}.
|
||||
func (j *Json) GetArray(pattern string) []interface{} {
|
||||
return gconv.Interfaces(j.Get(pattern))
|
||||
}
|
||||
|
||||
// 返回指定json中的string
|
||||
// GetString gets the value by specified <pattern>,
|
||||
// and converts it to string.
|
||||
func (j *Json) GetString(pattern string) string {
|
||||
return gconv.String(j.Get(pattern))
|
||||
}
|
||||
|
||||
// 返回指定json中的strings(转换为[]string数组)
|
||||
// GetStrings gets the value by specified <pattern>,
|
||||
// and converts it to a slice of []string.
|
||||
func (j *Json) GetStrings(pattern string) []string {
|
||||
return gconv.Strings(j.Get(pattern))
|
||||
}
|
||||
|
||||
// See GetArray.
|
||||
func (j *Json) GetInterfaces(pattern string) []interface{} {
|
||||
return gconv.Interfaces(j.Get(pattern))
|
||||
}
|
||||
@ -265,7 +281,10 @@ func (j *Json) GetTimeDuration(pattern string) time.Duration {
|
||||
return gconv.TimeDuration(j.Get(pattern))
|
||||
}
|
||||
|
||||
// 返回指定json中的bool(false:"", 0, false, off)
|
||||
// GetBool gets the value by specified <pattern>,
|
||||
// and converts it to bool.
|
||||
// It returns false when value is: "", 0, false, off, nil;
|
||||
// or returns true instead.
|
||||
func (j *Json) GetBool(pattern string) bool {
|
||||
return gconv.Bool(j.Get(pattern))
|
||||
}
|
||||
@ -326,25 +345,29 @@ func (j *Json) GetFloats(pattern string) []float64 {
|
||||
return gconv.Floats(j.Get(pattern))
|
||||
}
|
||||
|
||||
// 将指定变量转换为struct对象(对象属性赋值)
|
||||
// GetToStruct gets the value by specified <pattern>,
|
||||
// and converts it to specified object <objPointer>.
|
||||
// The <objPointer> should be the pointer to an object.
|
||||
func (j *Json) GetToStruct(pattern string, objPointer interface{}) error {
|
||||
return gconv.Struct(j.Get(pattern), objPointer)
|
||||
}
|
||||
|
||||
// 动态设置层级变量
|
||||
// Set sets value with specified <pattern>.
|
||||
// It supports hierarchical data access by char separator, which is '.' in default.
|
||||
func (j *Json) Set(pattern string, value interface{}) error {
|
||||
return j.setValue(pattern, value, false)
|
||||
}
|
||||
|
||||
// 动态删除层级变量
|
||||
// Remove deletes value with specified <pattern>.
|
||||
// It supports hierarchical data access by char separator, which is '.' in default.
|
||||
func (j *Json) Remove(pattern string) error {
|
||||
return j.setValue(pattern, nil, true)
|
||||
}
|
||||
|
||||
// 根据pattern查找并设置数据
|
||||
// 注意:
|
||||
// 1、写入的value为nil且removed为true时,表示删除;
|
||||
// 2、里面的层级处理比较复杂,逻辑较复杂的地方在于层级检索及节点创建,叶子赋值;
|
||||
// Set <value> by <pattern>.
|
||||
// Notice:
|
||||
// 1. If value is nil and removed is true, means deleting this value;
|
||||
// 2. It's quite complicated in hierarchical data search, node creating and data assignment;
|
||||
func (j *Json) setValue(pattern string, value interface{}, removed bool) error {
|
||||
array := strings.Split(pattern, string(j.c))
|
||||
length := len(array)
|
||||
@ -363,144 +386,144 @@ func (j *Json) setValue(pattern string, value interface{}, removed bool) error {
|
||||
defer j.mu.Unlock()
|
||||
for i:= 0; i < length; i++ {
|
||||
switch (*pointer).(type) {
|
||||
case map[string]interface{}:
|
||||
if i == length - 1 {
|
||||
if removed && value == nil {
|
||||
// 删除map元素
|
||||
delete((*pointer).(map[string]interface{}), array[i])
|
||||
} else {
|
||||
(*pointer).(map[string]interface{})[array[i]] = value
|
||||
}
|
||||
} else {
|
||||
// 当键名不存在的情况这里会进行处理
|
||||
if v, ok := (*pointer).(map[string]interface{})[array[i]]; !ok {
|
||||
if removed && value == nil {
|
||||
goto done
|
||||
}
|
||||
// 创建新节点
|
||||
if gstr.IsNumeric(array[i + 1]) {
|
||||
// 创建array节点
|
||||
n, _ := strconv.Atoi(array[i + 1])
|
||||
var v interface{} = make([]interface{}, n + 1)
|
||||
pparent = j.setPointerWithValue(pointer, array[i], v)
|
||||
pointer = &v
|
||||
} else {
|
||||
// 创建map节点
|
||||
var v interface{} = make(map[string]interface{})
|
||||
pparent = j.setPointerWithValue(pointer, array[i], v)
|
||||
pointer = &v
|
||||
}
|
||||
} else {
|
||||
pparent = pointer
|
||||
pointer = &v
|
||||
}
|
||||
}
|
||||
|
||||
case []interface{}:
|
||||
// 键名与当前指针类型不符合,需要执行**覆盖操作**
|
||||
if !gstr.IsNumeric(array[i]) {
|
||||
case map[string]interface{}:
|
||||
if i == length - 1 {
|
||||
*pointer = map[string]interface{}{ array[i] : value }
|
||||
if removed && value == nil {
|
||||
// 删除map元素
|
||||
delete((*pointer).(map[string]interface{}), array[i])
|
||||
} else {
|
||||
(*pointer).(map[string]interface{})[array[i]] = value
|
||||
}
|
||||
} else {
|
||||
var v interface{} = make(map[string]interface{})
|
||||
*pointer = v
|
||||
pparent = pointer
|
||||
pointer = &v
|
||||
// 当键名不存在的情况这里会进行处理
|
||||
if v, ok := (*pointer).(map[string]interface{})[array[i]]; !ok {
|
||||
if removed && value == nil {
|
||||
goto done
|
||||
}
|
||||
// 创建新节点
|
||||
if gstr.IsNumeric(array[i + 1]) {
|
||||
// 创建array节点
|
||||
n, _ := strconv.Atoi(array[i + 1])
|
||||
var v interface{} = make([]interface{}, n + 1)
|
||||
pparent = j.setPointerWithValue(pointer, array[i], v)
|
||||
pointer = &v
|
||||
} else {
|
||||
// 创建map节点
|
||||
var v interface{} = make(map[string]interface{})
|
||||
pparent = j.setPointerWithValue(pointer, array[i], v)
|
||||
pointer = &v
|
||||
}
|
||||
} else {
|
||||
pparent = pointer
|
||||
pointer = &v
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
valn, err := strconv.Atoi(array[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 叶子节点
|
||||
if i == length - 1 {
|
||||
if len((*pointer).([]interface{})) > valn {
|
||||
if removed && value == nil {
|
||||
// 删除数据元素
|
||||
j.setPointerWithValue(pparent, array[i - 1], append((*pointer).([]interface{})[ : valn], (*pointer).([]interface{})[valn + 1 : ]...))
|
||||
case []interface{}:
|
||||
// 键名与当前指针类型不符合,需要执行**覆盖操作**
|
||||
if !gstr.IsNumeric(array[i]) {
|
||||
if i == length - 1 {
|
||||
*pointer = map[string]interface{}{ array[i] : value }
|
||||
} else {
|
||||
(*pointer).([]interface{})[valn] = value
|
||||
}
|
||||
} else {
|
||||
if removed && value == nil {
|
||||
goto done
|
||||
}
|
||||
if pparent == nil {
|
||||
// 表示根节点
|
||||
j.setPointerWithValue(pointer, array[i], value)
|
||||
} else {
|
||||
// 非根节点
|
||||
s := make([]interface{}, valn + 1)
|
||||
copy(s, (*pointer).([]interface{}))
|
||||
s[valn] = value
|
||||
j.setPointerWithValue(pparent, array[i - 1], s)
|
||||
var v interface{} = make(map[string]interface{})
|
||||
*pointer = v
|
||||
pparent = pointer
|
||||
pointer = &v
|
||||
}
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
if gstr.IsNumeric(array[i + 1]) {
|
||||
n, _ := strconv.Atoi(array[i + 1])
|
||||
|
||||
valn, err := strconv.Atoi(array[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 叶子节点
|
||||
if i == length - 1 {
|
||||
if len((*pointer).([]interface{})) > valn {
|
||||
(*pointer).([]interface{})[valn] = make([]interface{}, n + 1)
|
||||
pparent = pointer
|
||||
pointer = &(*pointer).([]interface{})[valn]
|
||||
if removed && value == nil {
|
||||
// 删除数据元素
|
||||
j.setPointerWithValue(pparent, array[i - 1], append((*pointer).([]interface{})[ : valn], (*pointer).([]interface{})[valn + 1 : ]...))
|
||||
} else {
|
||||
(*pointer).([]interface{})[valn] = value
|
||||
}
|
||||
} else {
|
||||
if removed && value == nil {
|
||||
goto done
|
||||
}
|
||||
var v interface{} = make([]interface{}, n + 1)
|
||||
if pparent == nil {
|
||||
// 表示根节点
|
||||
j.setPointerWithValue(pointer, array[i], value)
|
||||
} else {
|
||||
// 非根节点
|
||||
s := make([]interface{}, valn + 1)
|
||||
copy(s, (*pointer).([]interface{}))
|
||||
s[valn] = value
|
||||
j.setPointerWithValue(pparent, array[i - 1], s)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if gstr.IsNumeric(array[i + 1]) {
|
||||
n, _ := strconv.Atoi(array[i + 1])
|
||||
if len((*pointer).([]interface{})) > valn {
|
||||
(*pointer).([]interface{})[valn] = make([]interface{}, n + 1)
|
||||
pparent = pointer
|
||||
pointer = &(*pointer).([]interface{})[valn]
|
||||
} else {
|
||||
if removed && value == nil {
|
||||
goto done
|
||||
}
|
||||
var v interface{} = make([]interface{}, n + 1)
|
||||
pparent = j.setPointerWithValue(pointer, array[i], v)
|
||||
pointer = &v
|
||||
}
|
||||
} else {
|
||||
var v interface{} = make(map[string]interface{})
|
||||
pparent = j.setPointerWithValue(pointer, array[i], v)
|
||||
pointer = &v
|
||||
}
|
||||
} else {
|
||||
var v interface{} = make(map[string]interface{})
|
||||
pparent = j.setPointerWithValue(pointer, array[i], v)
|
||||
pointer = &v
|
||||
}
|
||||
}
|
||||
|
||||
// 如果当前指针指向的变量不是引用类型的,
|
||||
// 那么修改变量必须通过父级进行修改,即 pparent
|
||||
default:
|
||||
if removed && value == nil {
|
||||
goto done
|
||||
}
|
||||
if gstr.IsNumeric(array[i]) {
|
||||
n, _ := strconv.Atoi(array[i])
|
||||
s := make([]interface{}, n + 1)
|
||||
if i == length - 1 {
|
||||
s[n] = value
|
||||
default:
|
||||
if removed && value == nil {
|
||||
goto done
|
||||
}
|
||||
if pparent != nil {
|
||||
pparent = j.setPointerWithValue(pparent, array[i - 1], s)
|
||||
} else {
|
||||
*pointer = s
|
||||
pparent = pointer
|
||||
}
|
||||
} else {
|
||||
var v interface{} = make(map[string]interface{})
|
||||
if i == length - 1 {
|
||||
v = map[string]interface{}{
|
||||
array[i] : value,
|
||||
if gstr.IsNumeric(array[i]) {
|
||||
n, _ := strconv.Atoi(array[i])
|
||||
s := make([]interface{}, n + 1)
|
||||
if i == length - 1 {
|
||||
s[n] = value
|
||||
}
|
||||
if pparent != nil {
|
||||
pparent = j.setPointerWithValue(pparent, array[i - 1], s)
|
||||
} else {
|
||||
*pointer = s
|
||||
pparent = pointer
|
||||
}
|
||||
}
|
||||
if pparent != nil {
|
||||
pparent = j.setPointerWithValue(pparent, array[i - 1], v)
|
||||
} else {
|
||||
*pointer = v
|
||||
pparent = pointer
|
||||
var v interface{} = make(map[string]interface{})
|
||||
if i == length - 1 {
|
||||
v = map[string]interface{}{
|
||||
array[i] : value,
|
||||
}
|
||||
}
|
||||
if pparent != nil {
|
||||
pparent = j.setPointerWithValue(pparent, array[i - 1], v)
|
||||
} else {
|
||||
*pointer = v
|
||||
pparent = pointer
|
||||
}
|
||||
pointer = &v
|
||||
}
|
||||
pointer = &v
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
done:
|
||||
return nil
|
||||
}
|
||||
|
||||
// 数据结构转换,map参数必须转换为map[string]interface{},数组参数必须转换为[]interface{}
|
||||
// Convert <value> to map[string]interface{} or []interface{},
|
||||
// which can be supported for hierarchical data access.
|
||||
func (j *Json) convertValue(value interface{}) interface{} {
|
||||
switch value.(type) {
|
||||
case map[string]interface{}:
|
||||
@ -520,7 +543,7 @@ func (j *Json) convertValue(value interface{}) interface{} {
|
||||
case reflect.Map: return gconv.Map(value)
|
||||
case reflect.Struct: return gconv.Map(value)
|
||||
default:
|
||||
// 最后使用JSON编解码
|
||||
// Use json decode/encode at last.
|
||||
b, _ := Encode(value)
|
||||
v, _ := Decode(b)
|
||||
return v
|
||||
@ -528,8 +551,8 @@ func (j *Json) convertValue(value interface{}) interface{} {
|
||||
}
|
||||
}
|
||||
|
||||
// 用于Set方法中,对指针指向的内存地址进行赋值
|
||||
// 返回修改后的父级指针
|
||||
// Set <key>:<value> to <pointer>, the <key> may be a map key or slice index.
|
||||
// It returns the pointer to the new value set.
|
||||
func (j *Json) setPointerWithValue(pointer *interface{}, key string, value interface{}) *interface{} {
|
||||
switch (*pointer).(type) {
|
||||
case map[string]interface{}:
|
||||
@ -553,9 +576,12 @@ func (j *Json) setPointerWithValue(pointer *interface{}, key string, value inter
|
||||
return pointer
|
||||
}
|
||||
|
||||
// 根据约定字符串方式访问json解析数据,参数形如: "items.name.first", "list.0"; 当pattern为空时,表示获取所有数据;
|
||||
// 返回的结果类型的interface{},因此需要自己做类型转换;
|
||||
// 如果找不到对应节点的数据,返回nil;
|
||||
// Get returns value by specified <pattern>.
|
||||
// It returns all values of current Json object, if <pattern> is empty or not specified.
|
||||
// It returns nil if no value found by <pattern>.
|
||||
//
|
||||
// We can also access slice item by its index number in <pattern>,
|
||||
// eg: "items.name.first", "list.10".
|
||||
func (j *Json) Get(pattern...string) interface{} {
|
||||
j.mu.RLock()
|
||||
defer j.mu.RUnlock()
|
||||
@ -576,13 +602,14 @@ func (j *Json) Get(pattern...string) interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 判断锁给定pattern是否数据存在
|
||||
// Contains checks whether the value by specified <pattern> exist.
|
||||
func (j *Json) Contains(pattern...string) bool {
|
||||
return j.Get(pattern...) != nil
|
||||
}
|
||||
|
||||
// 计算指定pattern的元素长度(pattern对应数据类型为map/slice时有效)。
|
||||
// 当pattern对应的数据类型非map/slice时,返回-1。
|
||||
// Len returns the length/size of the value by specified <pattern>.
|
||||
// The target value by <pattern> should be type of slice or map.
|
||||
// It returns -1 if the target value is not found, or its type is invalid.
|
||||
func (j *Json) Len(pattern string) int {
|
||||
p := j.getPointerByPattern(pattern)
|
||||
if p != nil {
|
||||
@ -598,7 +625,8 @@ func (j *Json) Len(pattern string) int {
|
||||
return -1
|
||||
}
|
||||
|
||||
// 指定pattern追加元素
|
||||
// Append appends value to the value by specified <pattern>.
|
||||
// The target value by <pattern> should be type of slice.
|
||||
func (j *Json) Append(pattern string, value interface{}) error {
|
||||
p := j.getPointerByPattern(pattern)
|
||||
if p == nil {
|
||||
@ -611,7 +639,7 @@ func (j *Json) Append(pattern string, value interface{}) error {
|
||||
return fmt.Errorf("invalid variable type of %s", pattern)
|
||||
}
|
||||
|
||||
// 根据pattern获取对应元素项的指针
|
||||
// Get a pointer to the value by specified <pattern>.
|
||||
func (j *Json) getPointerByPattern(pattern string) *interface{} {
|
||||
if j.vc {
|
||||
return j.getPointerByPatternWithViolenceCheck(pattern)
|
||||
@ -620,18 +648,7 @@ func (j *Json) getPointerByPattern(pattern string) *interface{} {
|
||||
}
|
||||
}
|
||||
|
||||
// 根据pattern层级查找**变量指针**, 执行冲突检测。
|
||||
// 检索方式:例如检索 a.a.a ,值为1
|
||||
// 1. 检索 a.a.a.a 是否存在对应map的键名;
|
||||
// 2. 检索 a.a.a 是否存在对应map的键名;
|
||||
// 3. 检索 a.a 是否存在对应map的键名;
|
||||
// 4. 检索 a 是否存在对应map的键名,如果检索出这是一个map,假如为变量m1;
|
||||
// 5. 在m1中检索 a.a.a 否存在对应map的键名;
|
||||
// 6. 在m1中检索 a.a 否存在对应map的键名;
|
||||
// 7. 在m1中检索 a 否存在对应map的键名,如果检索出这是一个map,假如为变量m2;
|
||||
// 8. 在m2中检索 a.a 否存在对应map的键名;
|
||||
// 9. 在m2中检索 a 否存在对应map的键名,检索到有值,值为1;
|
||||
// 这样检索的复杂度很高,主要是为了避免键名中存在分隔符号(默认为".")的情况,避免歧义。
|
||||
// Get a pointer to the value of specified <pattern> with violence check.
|
||||
func (j *Json) getPointerByPatternWithViolenceCheck(pattern string) *interface{} {
|
||||
if !j.vc {
|
||||
return j.getPointerByPatternWithoutViolenceCheck(pattern)
|
||||
@ -657,7 +674,7 @@ func (j *Json) getPointerByPatternWithViolenceCheck(pattern string) *interface{}
|
||||
pointer = r
|
||||
}
|
||||
} else {
|
||||
// 查找下一个分割符号的索引位置
|
||||
// Get the position for next separator char.
|
||||
index = strings.LastIndexByte(pattern[start:index], j.c)
|
||||
if index != -1 && length > 0 {
|
||||
index += length + 1
|
||||
@ -670,7 +687,7 @@ func (j *Json) getPointerByPatternWithViolenceCheck(pattern string) *interface{}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 层级检索,内部不执行分隔符冲突检查,检索效率会有所提高,但是冲突需要开发者自己根据自定义的分隔符来进行解决
|
||||
// Get a pointer to the value of specified <pattern>, with no violence check.
|
||||
func (j *Json) getPointerByPatternWithoutViolenceCheck(pattern string) *interface{} {
|
||||
if j.vc {
|
||||
return j.getPointerByPatternWithViolenceCheck(pattern)
|
||||
@ -694,8 +711,8 @@ func (j *Json) getPointerByPatternWithoutViolenceCheck(pattern string) *interfac
|
||||
return nil
|
||||
}
|
||||
|
||||
// 判断给定的key在当前的pointer下是否有值,并返回对应的pointer,
|
||||
// 注意这里返回的指针都是临时变量的内存地址
|
||||
// Check whether there's value by <key> in specified <pointer>.
|
||||
// It returns a pointer to the value.
|
||||
func (j *Json) checkPatternByPointer(key string, pointer *interface{}) *interface{} {
|
||||
switch (*pointer).(type) {
|
||||
case map[string]interface{}:
|
||||
@ -713,7 +730,8 @@ func (j *Json) checkPatternByPointer(key string, pointer *interface{}) *interfac
|
||||
return nil
|
||||
}
|
||||
|
||||
// 转换为map[string]interface{}类型,如果转换失败,返回nil
|
||||
// ToMap converts current Json object to map[string]interface{}.
|
||||
// It returns nil if fails.
|
||||
func (j *Json) ToMap() map[string]interface{} {
|
||||
j.mu.RLock()
|
||||
defer j.mu.RUnlock()
|
||||
@ -725,15 +743,16 @@ func (j *Json) ToMap() map[string]interface{} {
|
||||
}
|
||||
}
|
||||
|
||||
// 转换为[]interface{}类型,如果转换失败,返回nil
|
||||
// ToArray converts current Json object to []interface{}.
|
||||
// It returns nil if fails.
|
||||
func (j *Json) ToArray() []interface{} {
|
||||
j.mu.RLock()
|
||||
defer j.mu.RUnlock()
|
||||
switch (*(j.p)).(type) {
|
||||
case []interface{}:
|
||||
return (*(j.p)).([]interface{})
|
||||
default:
|
||||
return nil
|
||||
case []interface{}:
|
||||
return (*(j.p)).([]interface{})
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -799,14 +818,15 @@ func (j *Json) ToTomlString() (string, error) {
|
||||
return string(b), e
|
||||
}
|
||||
|
||||
// 转换为指定的struct对象
|
||||
func (j *Json) ToStruct(o interface{}) error {
|
||||
// ToStruct converts current Json object to specified object.
|
||||
// The <objPointer> should be a pointer type.
|
||||
func (j *Json) ToStruct(objPointer interface{}) error {
|
||||
j.mu.RLock()
|
||||
defer j.mu.RUnlock()
|
||||
return gconv.Struct(*(j.p), o)
|
||||
return gconv.Struct(*(j.p), objPointer)
|
||||
}
|
||||
|
||||
// 打印Json对象
|
||||
// Dump prints current Json object with more manually readable.
|
||||
func (j *Json) Dump() error {
|
||||
j.mu.RLock()
|
||||
defer j.mu.RUnlock()
|
||||
|
||||
@ -69,7 +69,7 @@ func Test_Load_XML(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Load_YAML(t *testing.T) {
|
||||
func Test_Load_YAML1(t *testing.T) {
|
||||
data := []byte(`
|
||||
a:
|
||||
- 1
|
||||
@ -104,7 +104,16 @@ m:
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Load_TOML(t *testing.T) {
|
||||
func Test_Load_YAML2(t *testing.T) {
|
||||
data := []byte("i : 123456789")
|
||||
gtest.Case(t, func() {
|
||||
j, err := gjson.LoadContent(data)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(j.Get("i"), "123456789")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Load_TOML1(t *testing.T) {
|
||||
data := []byte(`
|
||||
a = ["1", "2", "3"]
|
||||
n = "123456789"
|
||||
@ -136,3 +145,12 @@ n = "123456789"
|
||||
gtest.Assert(j.Get("a.1"), 2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Load_TOML2(t *testing.T) {
|
||||
data := []byte("i=123456789")
|
||||
gtest.Case(t, func() {
|
||||
j, err := gjson.LoadContent(data)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(j.Get("i"), "123456789")
|
||||
})
|
||||
}
|
||||
|
||||
@ -172,7 +172,7 @@ func Test_Set10(t *testing.T) {
|
||||
|
||||
func Test_Set11(t *testing.T) {
|
||||
e := []byte(`{"a":{"b":{}}}`)
|
||||
p, _ := gjson.LoadContent([]byte(`{"a":{"b":{"c":1}}}`), "json")
|
||||
p, _ := gjson.LoadContent([]byte(`{"a":{"b":{"c":1}}}`))
|
||||
p.Remove("a.b.c")
|
||||
if c, err := p.ToJson(); err == nil {
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gp.
|
||||
|
||||
// Package gparser provides a flexible and easy way for accessing/converting variable and JSON/XML/YAML/TOML contents.
|
||||
// Package gparser provides convenient API for accessing/converting variable and JSON/XML/YAML/TOML.
|
||||
package gparser
|
||||
|
||||
import (
|
||||
@ -16,13 +16,16 @@ type Parser struct {
|
||||
json *gjson.Json
|
||||
}
|
||||
|
||||
// 将变量转换为Parser对象进行处理,该变量至少应当是一个map或者array,否者转换没有意义
|
||||
// value可以传递nil, 表示创建一个空的Parser对象
|
||||
func New (value interface{}, unsafe...bool) *Parser {
|
||||
// New creates a Parser object with any variable type of <data>,
|
||||
// but <data> should be a map or slice for data access reason,
|
||||
// or it will make no sense.
|
||||
// The <unsafe> param specifies whether using this Parser object
|
||||
// in un-concurrent-safe context, which is false in default.
|
||||
func New(value interface{}, unsafe...bool) *Parser {
|
||||
return &Parser{gjson.New(value, unsafe...)}
|
||||
}
|
||||
|
||||
// 非并发安全Parser对象
|
||||
// NewUnsafe creates a un-concurrent-safe Parser object.
|
||||
func NewUnsafe (value...interface{}) *Parser {
|
||||
if len(value) > 0 {
|
||||
return &Parser{gjson.New(value[0], false)}
|
||||
@ -30,57 +33,64 @@ func NewUnsafe (value...interface{}) *Parser {
|
||||
return &Parser{gjson.New(nil, false)}
|
||||
}
|
||||
|
||||
func Load (path string) (*Parser, error) {
|
||||
if j, e := gjson.Load(path); e == nil {
|
||||
// Load loads content from specified file <path>,
|
||||
// and creates a Parser object from its content.
|
||||
func Load (path string, unsafe...bool) (*Parser, error) {
|
||||
if j, e := gjson.Load(path, unsafe...); e == nil {
|
||||
return &Parser{j}, nil
|
||||
} else {
|
||||
return nil, e
|
||||
}
|
||||
}
|
||||
|
||||
// 支持的数据内容格式:json(默认), xml, yaml/yml, toml
|
||||
func LoadContent (data []byte, dataType...string) (*Parser, error) {
|
||||
if j, e := gjson.LoadContent(data, dataType...); e == nil {
|
||||
// LoadContent creates a Parser object from given content,
|
||||
// it checks the data type of <content> automatically,
|
||||
// supporting JSON, XML, YAML and TOML types of data.
|
||||
func LoadContent (data []byte, unsafe...bool) (*Parser, error) {
|
||||
if j, e := gjson.LoadContent(data, unsafe...); e == nil {
|
||||
return &Parser{j}, nil
|
||||
} else {
|
||||
return nil, e
|
||||
}
|
||||
}
|
||||
|
||||
// 设置自定义的层级分隔符号
|
||||
// SetSplitChar sets the separator char for hierarchical data access.
|
||||
func (p *Parser) SetSplitChar(char byte) {
|
||||
p.json.SetSplitChar(char)
|
||||
}
|
||||
|
||||
// 设置是否执行层级冲突检查,当键名中存在层级符号时需要开启该特性,默认为关闭。
|
||||
// 开启比较耗性能,也不建议允许键名中存在分隔符,最好在应用端避免这种情况。
|
||||
// SetViolenceCheck enables/disables violence check for hierarchical data access.
|
||||
func (p *Parser) SetViolenceCheck(check bool) {
|
||||
p.json.SetViolenceCheck(check)
|
||||
}
|
||||
|
||||
// 将指定的json内容转换为指定结构返回,查找失败或者转换失败,目标对象转换为nil
|
||||
// 注意第二个参数需要给的是变量地址
|
||||
// GetToVar gets the value by specified <pattern>,
|
||||
// and converts it to specified golang variable <v>.
|
||||
// The <v> should be a pointer type.
|
||||
func (p *Parser) GetToVar(pattern string, v interface{}) error {
|
||||
return p.json.GetToVar(pattern, v)
|
||||
}
|
||||
|
||||
// 获得一个键值对关联数组/哈希表,方便操作,不需要自己做类型转换
|
||||
// 注意,如果获取的值不存在,或者类型与json类型不匹配,那么将会返回nil
|
||||
// GetMap gets the value by specified <pattern>,
|
||||
// and converts it to map[string]interface{}.
|
||||
func (p *Parser) GetMap(pattern string) map[string]interface{} {
|
||||
return p.json.GetMap(pattern)
|
||||
}
|
||||
|
||||
// 获得一个数组[]interface{},方便操作,不需要自己做类型转换
|
||||
// 注意,如果获取的值不存在,或者类型与json类型不匹配,那么将会返回nil
|
||||
// GetArray gets the value by specified <pattern>,
|
||||
// and converts it to a slice of []interface{}.
|
||||
func (p *Parser) GetArray(pattern string) []interface{} {
|
||||
return p.json.GetArray(pattern)
|
||||
}
|
||||
|
||||
// 返回指定json中的string
|
||||
// GetString gets the value by specified <pattern>,
|
||||
// and converts it to string.
|
||||
func (p *Parser) GetString(pattern string) string {
|
||||
return p.json.GetString(pattern)
|
||||
}
|
||||
|
||||
// GetStrings gets the value by specified <pattern>,
|
||||
// and converts it to a slice of []string.
|
||||
func (p *Parser) GetStrings(pattern string) []string {
|
||||
return p.json.GetStrings(pattern)
|
||||
}
|
||||
@ -97,7 +107,10 @@ func (p *Parser) GetTimeDuration(pattern string) time.Duration {
|
||||
return p.json.GetTimeDuration(pattern)
|
||||
}
|
||||
|
||||
// 返回指定json中的bool(false:"", 0, false, off)
|
||||
// GetBool gets the value by specified <pattern>,
|
||||
// and converts it to bool.
|
||||
// It returns false when value is: "", 0, false, off, nil;
|
||||
// or returns true instead.
|
||||
func (p *Parser) GetBool(pattern string) bool {
|
||||
return p.json.GetBool(pattern)
|
||||
}
|
||||
@ -158,51 +171,60 @@ func (p *Parser) GetFloats(pattern string) []float64 {
|
||||
return p.json.GetFloats(pattern)
|
||||
}
|
||||
|
||||
// 将指定变量转换为struct对象(对象属性赋值)
|
||||
// GetToStruct gets the value by specified <pattern>,
|
||||
// and converts it to specified object <objPointer>.
|
||||
// The <objPointer> should be the pointer to an object.
|
||||
func (p *Parser) GetToStruct(pattern string, objPointer interface{}) error {
|
||||
return p.json.GetToStruct(pattern, objPointer)
|
||||
}
|
||||
|
||||
// 根据pattern查找并设置数据
|
||||
// 注意:写入的时候"."符号只能表示层级,不能使用带"."符号的键名
|
||||
// Set sets value with specified <pattern>.
|
||||
// It supports hierarchical data access by char separator, which is '.' in default.
|
||||
func (p *Parser) Set(pattern string, value interface{}) error {
|
||||
return p.json.Set(pattern, value)
|
||||
}
|
||||
|
||||
// 计算指定pattern的元素长度(pattern对应数据类型为map[string]interface{}/[]interface{}时有效)
|
||||
// Len returns the length/size of the value by specified <pattern>.
|
||||
// The target value by <pattern> should be type of slice or map.
|
||||
// It returns -1 if the target value is not found, or its type is invalid.
|
||||
func (p *Parser) Len(pattern string) int {
|
||||
return p.json.Len(pattern)
|
||||
}
|
||||
|
||||
// 指定pattern追加元素
|
||||
// Append appends value to the value by specified <pattern>.
|
||||
// The target value by <pattern> should be type of slice.
|
||||
func (p *Parser) Append(pattern string, value interface{}) error {
|
||||
return p.json.Append(pattern, value)
|
||||
}
|
||||
|
||||
// 动态删除变量节点
|
||||
// Remove deletes value with specified <pattern>.
|
||||
// It supports hierarchical data access by char separator, which is '.' in default.
|
||||
func (p *Parser) Remove(pattern string) error {
|
||||
return p.json.Remove(pattern)
|
||||
}
|
||||
|
||||
// 根据约定字符串方式访问json解析数据,参数形如: "items.name.first", "list.0"; 当pattern为空时,表示获取所有数据
|
||||
// 返回的结果类型的interface{},因此需要自己做类型转换;
|
||||
// 如果找不到对应节点的数据,返回nil;
|
||||
// Get returns value by specified <pattern>.
|
||||
// It returns all values of current Json object, if <pattern> is empty or not specified.
|
||||
// It returns nil if no value found by <pattern>.
|
||||
//
|
||||
// We can also access slice item by its index number in <pattern>,
|
||||
// eg: "items.name.first", "list.10".
|
||||
func (p *Parser) Get(pattern...string) interface{} {
|
||||
return p.json.Get(pattern...)
|
||||
}
|
||||
|
||||
// 转换为map[string]interface{}类型,如果转换失败,返回nil
|
||||
// ToMap converts current object values to map[string]interface{}.
|
||||
// It returns nil if fails.
|
||||
func (p *Parser) ToMap() map[string]interface{} {
|
||||
return p.json.ToMap()
|
||||
}
|
||||
|
||||
// 转换为[]interface{}类型,如果转换失败,返回nil
|
||||
// ToArray converts current object values to []interface{}.
|
||||
// It returns nil if fails.
|
||||
func (p *Parser) ToArray() []interface{} {
|
||||
return p.json.ToArray()
|
||||
}
|
||||
|
||||
/* 以下为数据文件格式转换,支持类型:xml, json, yaml/yml, toml */
|
||||
|
||||
func (p *Parser) ToXml(rootTag...string) ([]byte, error) {
|
||||
return p.json.ToXml(rootTag...)
|
||||
}
|
||||
@ -227,12 +249,13 @@ func (p *Parser) ToToml() ([]byte, error) {
|
||||
return p.json.ToToml()
|
||||
}
|
||||
|
||||
// 打印Json对象
|
||||
// Dump prints current Json object with more manually readable.
|
||||
func (p *Parser) Dump() error {
|
||||
return p.json.Dump()
|
||||
}
|
||||
|
||||
// 将变量解析为对应的struct对象,注意传递的参数为struct对象指针
|
||||
// ToStruct converts current Json object to specified object.
|
||||
// The <objPointer> should be a pointer type.
|
||||
func (p *Parser) ToStruct(o interface{}) error {
|
||||
return p.json.ToStruct(o)
|
||||
}
|
||||
@ -261,7 +284,6 @@ func VarToToml(value interface{}) ([]byte, error) {
|
||||
return New(value).ToToml()
|
||||
}
|
||||
|
||||
// 将变量解析为对应的struct对象,注意传递的参数为struct对象指针
|
||||
func VarToStruct(value interface{}, obj interface{}) error {
|
||||
return New(value).ToStruct(obj)
|
||||
}
|
||||
|
||||
208
g/encoding/gparser/gparser_unit_basic_test.go
Normal file
208
g/encoding/gparser/gparser_unit_basic_test.go
Normal file
@ -0,0 +1,208 @@
|
||||
// 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 gparser_test
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/encoding/gparser"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_New(t *testing.T) {
|
||||
data := []byte(`{"n":123456789, "m":{"k":"v"}, "a":[1,2,3]}`)
|
||||
gtest.Case(t, func() {
|
||||
j := gparser.New(data)
|
||||
gtest.Assert(j.Get("n"), "123456789")
|
||||
gtest.Assert(j.Get("m"), g.Map{"k" : "v"})
|
||||
gtest.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
})
|
||||
}
|
||||
|
||||
func Test_NewUnsafe(t *testing.T) {
|
||||
data := []byte(`{"n":123456789, "m":{"k":"v"}, "a":[1,2,3]}`)
|
||||
gtest.Case(t, func() {
|
||||
j := gparser.NewUnsafe(data)
|
||||
gtest.Assert(j.Get("n"), "123456789")
|
||||
gtest.Assert(j.Get("m"), g.Map{"k" : "v"})
|
||||
gtest.Assert(j.Get("m.k"), "v")
|
||||
gtest.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
gtest.Assert(j.Get("a.1"), 2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Encode(t *testing.T) {
|
||||
value := g.Slice{1, 2, 3}
|
||||
gtest.Case(t, func() {
|
||||
b, err := gparser.VarToJson(value)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(b, []byte(`[1,2,3]`))
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Decode(t *testing.T) {
|
||||
data := []byte(`{"n":123456789, "m":{"k":"v"}, "a":[1,2,3]}`)
|
||||
gtest.Case(t, func() {
|
||||
j := gparser.New(data)
|
||||
gtest.AssertNE(j, nil)
|
||||
gtest.Assert(j.Get("n"), "123456789")
|
||||
gtest.Assert(j.Get("m"), g.Map{"k" : "v"})
|
||||
gtest.Assert(j.Get("m.k"), "v")
|
||||
gtest.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
gtest.Assert(j.Get("a.1"), 2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_SplitChar(t *testing.T) {
|
||||
data := []byte(`{"n":123456789, "m":{"k":"v"}, "a":[1,2,3]}`)
|
||||
gtest.Case(t, func() {
|
||||
j := gparser.New(data)
|
||||
j.SetSplitChar(byte('#'))
|
||||
gtest.AssertNE(j, nil)
|
||||
gtest.Assert(j.Get("n"), "123456789")
|
||||
gtest.Assert(j.Get("m"), g.Map{"k" : "v"})
|
||||
gtest.Assert(j.Get("m#k"), "v")
|
||||
gtest.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
gtest.Assert(j.Get("a#1"), 2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_ViolenceCheck(t *testing.T) {
|
||||
data := []byte(`{"m":{"a":[1,2,3], "v1.v2":"4"}}`)
|
||||
gtest.Case(t, func() {
|
||||
j := gparser.New(data)
|
||||
gtest.AssertNE(j, nil)
|
||||
gtest.Assert(j.Get("m.a.2"), 3)
|
||||
gtest.Assert(j.Get("m.v1.v2"), nil)
|
||||
j.SetViolenceCheck(true)
|
||||
gtest.Assert(j.Get("m.v1.v2"), 4)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_GetToVar(t *testing.T) {
|
||||
data := []byte(`{"n":123456789, "m":{"k":"v"}, "a":[1,2,3]}`)
|
||||
gtest.Case(t, func() {
|
||||
var m map[string]string
|
||||
var n int
|
||||
var a []int
|
||||
j := gparser.New(data)
|
||||
gtest.AssertNE(j, nil)
|
||||
|
||||
j.GetToVar("n", &n)
|
||||
j.GetToVar("m", &m)
|
||||
j.GetToVar("a", &a)
|
||||
|
||||
gtest.Assert(n, "123456789")
|
||||
gtest.Assert(m, g.Map{"k" : "v"})
|
||||
gtest.Assert(a, g.Slice{1, 2, 3})
|
||||
})
|
||||
}
|
||||
|
||||
func Test_GetMap(t *testing.T) {
|
||||
data := []byte(`{"n":123456789, "m":{"k":"v"}, "a":[1,2,3]}`)
|
||||
gtest.Case(t, func() {
|
||||
j := gparser.New(data)
|
||||
gtest.AssertNE(j, nil)
|
||||
gtest.Assert(j.GetMap("n"), g.Map{})
|
||||
gtest.Assert(j.GetMap("m"), g.Map{"k" : "v"})
|
||||
gtest.Assert(j.GetMap("a"), g.Map{})
|
||||
})
|
||||
}
|
||||
|
||||
func Test_GetArray(t *testing.T) {
|
||||
data := []byte(`{"n":123456789, "m":{"k":"v"}, "a":[1,2,3]}`)
|
||||
gtest.Case(t, func() {
|
||||
j := gparser.New(data)
|
||||
gtest.AssertNE(j, nil)
|
||||
gtest.Assert(j.GetArray("n"), g.Array{123456789})
|
||||
gtest.Assert(j.GetArray("m"), g.Array{g.Map{"k":"v"}})
|
||||
gtest.Assert(j.GetArray("a"), g.Array{1,2,3})
|
||||
})
|
||||
}
|
||||
|
||||
func Test_GetString(t *testing.T) {
|
||||
data := []byte(`{"n":123456789, "m":{"k":"v"}, "a":[1,2,3]}`)
|
||||
gtest.Case(t, func() {
|
||||
j := gparser.New(data)
|
||||
gtest.AssertNE(j, nil)
|
||||
gtest.AssertEQ(j.GetString("n"), "123456789")
|
||||
gtest.AssertEQ(j.GetString("m"), `{"k":"v"}`)
|
||||
gtest.AssertEQ(j.GetString("a"), `[1,2,3]`)
|
||||
gtest.AssertEQ(j.GetString("i"), "")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_GetStrings(t *testing.T) {
|
||||
data := []byte(`{"n":123456789, "m":{"k":"v"}, "a":[1,2,3]}`)
|
||||
gtest.Case(t, func() {
|
||||
j := gparser.New(data)
|
||||
gtest.AssertNE(j, nil)
|
||||
gtest.AssertEQ(j.GetStrings("n"), g.SliceStr{"123456789"})
|
||||
gtest.AssertEQ(j.GetStrings("m"), g.SliceStr{`{"k":"v"}`})
|
||||
gtest.AssertEQ(j.GetStrings("a"), g.SliceStr{"1", "2", "3"})
|
||||
gtest.AssertEQ(j.GetStrings("i"), g.SliceStr{})
|
||||
})
|
||||
}
|
||||
|
||||
func Test_GetInterfaces(t *testing.T) {
|
||||
data := []byte(`{"n":123456789, "m":{"k":"v"}, "a":[1,2,3]}`)
|
||||
gtest.Case(t, func() {
|
||||
j := gparser.New(data)
|
||||
gtest.AssertNE(j, nil)
|
||||
gtest.AssertEQ(j.GetInterfaces("n"), g.Array{123456789})
|
||||
gtest.AssertEQ(j.GetInterfaces("m"), g.Array{g.Map{"k":"v"}})
|
||||
gtest.AssertEQ(j.GetInterfaces("a"), g.Array{1,2,3})
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Len(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
p := gparser.New(nil)
|
||||
p.Append("a", 1)
|
||||
p.Append("a", 2)
|
||||
gtest.Assert(p.Len("a"), 2)
|
||||
})
|
||||
gtest.Case(t, func() {
|
||||
p := gparser.New(nil)
|
||||
p.Append("a.b", 1)
|
||||
p.Append("a.c", 2)
|
||||
gtest.Assert(p.Len("a"), 2)
|
||||
})
|
||||
gtest.Case(t, func() {
|
||||
p := gparser.New(nil)
|
||||
p.Set("a", 1)
|
||||
gtest.Assert(p.Len("a"), -1)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Append(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
p := gparser.New(nil)
|
||||
p.Append("a", 1)
|
||||
p.Append("a", 2)
|
||||
gtest.Assert(p.Get("a"), g.Slice{1, 2})
|
||||
})
|
||||
gtest.Case(t, func() {
|
||||
p := gparser.New(nil)
|
||||
p.Append("a.b", 1)
|
||||
p.Append("a.c", 2)
|
||||
gtest.Assert(p.Get("a"), g.Map{
|
||||
"b" : g.Slice{1},
|
||||
"c" : g.Slice{2},
|
||||
})
|
||||
})
|
||||
gtest.Case(t, func() {
|
||||
p := gparser.New(nil)
|
||||
p.Set("a", 1)
|
||||
err := p.Append("a", 2)
|
||||
gtest.AssertNE(err, nil)
|
||||
gtest.Assert(p.Get("a"), 1)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
156
g/encoding/gparser/gparser_unit_load_test.go
Normal file
156
g/encoding/gparser/gparser_unit_load_test.go
Normal file
@ -0,0 +1,156 @@
|
||||
// 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 gparser_test
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/encoding/gparser"
|
||||
"github.com/gogf/gf/g/os/gfile"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
||||
func Test_Load_JSON(t *testing.T) {
|
||||
data := []byte(`{"n":123456789, "m":{"k":"v"}, "a":[1,2,3]}`)
|
||||
// JSON
|
||||
gtest.Case(t, func() {
|
||||
j, err := gparser.LoadContent(data)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(j.Get("n"), "123456789")
|
||||
gtest.Assert(j.Get("m"), g.Map{"k" : "v"})
|
||||
gtest.Assert(j.Get("m.k"), "v")
|
||||
gtest.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
gtest.Assert(j.Get("a.1"), 2)
|
||||
})
|
||||
// JSON
|
||||
gtest.Case(t, func() {
|
||||
path := "test.json"
|
||||
gfile.PutBinContents(path, data)
|
||||
defer gfile.Remove(path)
|
||||
j, err := gparser.Load(path)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(j.Get("n"), "123456789")
|
||||
gtest.Assert(j.Get("m"), g.Map{"k" : "v"})
|
||||
gtest.Assert(j.Get("m.k"), "v")
|
||||
gtest.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
gtest.Assert(j.Get("a.1"), 2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Load_XML(t *testing.T) {
|
||||
data := []byte(`<doc><a>1</a><a>2</a><a>3</a><m><k>v</k></m><n>123456789</n></doc>`)
|
||||
// XML
|
||||
gtest.Case(t, func() {
|
||||
j, err := gparser.LoadContent(data)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(j.Get("doc.n"), "123456789")
|
||||
gtest.Assert(j.Get("doc.m"), g.Map{"k" : "v"})
|
||||
gtest.Assert(j.Get("doc.m.k"), "v")
|
||||
gtest.Assert(j.Get("doc.a"), g.Slice{1, 2, 3})
|
||||
gtest.Assert(j.Get("doc.a.1"), 2)
|
||||
})
|
||||
// XML
|
||||
gtest.Case(t, func() {
|
||||
path := "test.xml"
|
||||
gfile.PutBinContents(path, data)
|
||||
defer gfile.Remove(path)
|
||||
j, err := gparser.Load(path)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(j.Get("doc.n"), "123456789")
|
||||
gtest.Assert(j.Get("doc.m"), g.Map{"k" : "v"})
|
||||
gtest.Assert(j.Get("doc.m.k"), "v")
|
||||
gtest.Assert(j.Get("doc.a"), g.Slice{1, 2, 3})
|
||||
gtest.Assert(j.Get("doc.a.1"), 2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Load_YAML1(t *testing.T) {
|
||||
data := []byte(`
|
||||
a:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
m:
|
||||
k: v
|
||||
"n": 123456789
|
||||
`)
|
||||
// YAML
|
||||
gtest.Case(t, func() {
|
||||
j, err := gparser.LoadContent(data)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(j.Get("n"), "123456789")
|
||||
gtest.Assert(j.Get("m"), g.Map{"k" : "v"})
|
||||
gtest.Assert(j.Get("m.k"), "v")
|
||||
gtest.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
gtest.Assert(j.Get("a.1"), 2)
|
||||
})
|
||||
// YAML
|
||||
gtest.Case(t, func() {
|
||||
path := "test.yaml"
|
||||
gfile.PutBinContents(path, data)
|
||||
defer gfile.Remove(path)
|
||||
j, err := gparser.Load(path)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(j.Get("n"), "123456789")
|
||||
gtest.Assert(j.Get("m"), g.Map{"k" : "v"})
|
||||
gtest.Assert(j.Get("m.k"), "v")
|
||||
gtest.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
gtest.Assert(j.Get("a.1"), 2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Load_YAML2(t *testing.T) {
|
||||
data := []byte("i : 123456789")
|
||||
gtest.Case(t, func() {
|
||||
j, err := gparser.LoadContent(data)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(j.Get("i"), "123456789")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Load_TOML1(t *testing.T) {
|
||||
data := []byte(`
|
||||
a = ["1", "2", "3"]
|
||||
n = "123456789"
|
||||
|
||||
[m]
|
||||
k = "v"
|
||||
`)
|
||||
// TOML
|
||||
gtest.Case(t, func() {
|
||||
j, err := gparser.LoadContent(data)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(j.Get("n"), "123456789")
|
||||
gtest.Assert(j.Get("m"), g.Map{"k" : "v"})
|
||||
gtest.Assert(j.Get("m.k"), "v")
|
||||
gtest.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
gtest.Assert(j.Get("a.1"), 2)
|
||||
})
|
||||
// TOML
|
||||
gtest.Case(t, func() {
|
||||
path := "test.toml"
|
||||
gfile.PutBinContents(path, data)
|
||||
defer gfile.Remove(path)
|
||||
j, err := gparser.Load(path)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(j.Get("n"), "123456789")
|
||||
gtest.Assert(j.Get("m"), g.Map{"k" : "v"})
|
||||
gtest.Assert(j.Get("m.k"), "v")
|
||||
gtest.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
gtest.Assert(j.Get("a.1"), 2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Load_TOML2(t *testing.T) {
|
||||
data := []byte("i=123456789")
|
||||
gtest.Case(t, func() {
|
||||
j, err := gparser.LoadContent(data)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(j.Get("i"), "123456789")
|
||||
})
|
||||
}
|
||||
@ -4,8 +4,6 @@
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
// 单元测试
|
||||
|
||||
package gparser_test
|
||||
|
||||
import (
|
||||
@ -22,7 +20,6 @@ func Test_Set1(t *testing.T) {
|
||||
})
|
||||
p.Set("k1.k11", []int{1,2,3})
|
||||
if c, err := p.ToJson(); err == nil {
|
||||
|
||||
if bytes.Compare(c, []byte(`{"k1":{"k11":[1,2,3]},"k2":"v2"}`)) != 0 {
|
||||
t.Error("expect:", string(e))
|
||||
}
|
||||
@ -36,7 +33,6 @@ func Test_Set2(t *testing.T) {
|
||||
p := gparser.New([]string{"a"})
|
||||
p.Set("0.1", 1)
|
||||
if c, err := p.ToJson(); err == nil {
|
||||
|
||||
if bytes.Compare(c, e) != 0 {
|
||||
t.Error("expect:", string(e))
|
||||
}
|
||||
@ -48,11 +44,10 @@ func Test_Set2(t *testing.T) {
|
||||
func Test_Set3(t *testing.T) {
|
||||
e := []byte(`{"kv":{"k1":"v1"}}`)
|
||||
p := gparser.New([]string{"a"})
|
||||
p.Set("kv", map[string]string{
|
||||
p.Set("kv", map[string]string {
|
||||
"k1" : "v1",
|
||||
})
|
||||
if c, err := p.ToJson(); err == nil {
|
||||
|
||||
if bytes.Compare(c, e) != 0 {
|
||||
t.Error("expect:", string(e))
|
||||
}
|
||||
@ -68,7 +63,6 @@ func Test_Set4(t *testing.T) {
|
||||
"k1" : "v1",
|
||||
})
|
||||
if c, err := p.ToJson(); err == nil {
|
||||
|
||||
if bytes.Compare(c, e) != 0 {
|
||||
t.Error("expect:", string(e))
|
||||
}
|
||||
@ -82,7 +76,6 @@ func Test_Set5(t *testing.T) {
|
||||
p := gparser.New([]string{"a"})
|
||||
p.Set("0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0", []int{1,2,3})
|
||||
if c, err := p.ToJson(); err == nil {
|
||||
|
||||
if bytes.Compare(c, e) != 0 {
|
||||
t.Error("expect:", string(e))
|
||||
}
|
||||
@ -96,7 +89,6 @@ func Test_Set6(t *testing.T) {
|
||||
p := gparser.New([]string{"a"})
|
||||
p.Set("1", []int{1,2,3})
|
||||
if c, err := p.ToJson(); err == nil {
|
||||
|
||||
if bytes.Compare(c, e) != 0 {
|
||||
t.Error("expect:", string(e))
|
||||
}
|
||||
@ -113,7 +105,6 @@ func Test_Set7(t *testing.T) {
|
||||
})
|
||||
p.Set("0.1", []int{1,2,3})
|
||||
if c, err := p.ToJson(); err == nil {
|
||||
|
||||
if bytes.Compare(c, e) != 0 {
|
||||
t.Error("expect:", string(e))
|
||||
}
|
||||
@ -130,7 +121,6 @@ func Test_Set8(t *testing.T) {
|
||||
})
|
||||
p.Set("0.0.0.0.0.0.1", []int{1,2,3})
|
||||
if c, err := p.ToJson(); err == nil {
|
||||
|
||||
if bytes.Compare(c, e) != 0 {
|
||||
t.Error("expect:", string(e))
|
||||
}
|
||||
@ -147,7 +137,6 @@ func Test_Set9(t *testing.T) {
|
||||
})
|
||||
p.Set("k1.1", []int{1,2,3})
|
||||
if c, err := p.ToJson(); err == nil {
|
||||
|
||||
if bytes.Compare(c, e) != 0 {
|
||||
t.Error("expect:", string(e))
|
||||
}
|
||||
@ -162,7 +151,6 @@ func Test_Set10(t *testing.T) {
|
||||
p := gparser.New(nil)
|
||||
p.Set("a.b.c", 1)
|
||||
if c, err := p.ToJson(); err == nil {
|
||||
|
||||
if bytes.Compare(c, e) != 0 {
|
||||
t.Error("expect:", string(e))
|
||||
}
|
||||
@ -174,10 +162,9 @@ func Test_Set10(t *testing.T) {
|
||||
|
||||
func Test_Set11(t *testing.T) {
|
||||
e := []byte(`{"a":{"b":{}}}`)
|
||||
p, _ := gparser.LoadContent([]byte(`{"a":{"b":{"c":1}}}`), "json")
|
||||
p, _ := gparser.LoadContent([]byte(`{"a":{"b":{"c":1}}}`))
|
||||
p.Remove("a.b.c")
|
||||
if c, err := p.ToJson(); err == nil {
|
||||
|
||||
if bytes.Compare(c, e) != 0 {
|
||||
t.Error("expect:", string(e))
|
||||
}
|
||||
@ -192,7 +179,6 @@ func Test_Set12(t *testing.T) {
|
||||
p.Set("0", 0)
|
||||
p.Set("1", 1)
|
||||
if c, err := p.ToJson(); err == nil {
|
||||
|
||||
if bytes.Compare(c, e) != 0 {
|
||||
t.Error("expect:", string(e))
|
||||
}
|
||||
@ -207,7 +193,6 @@ func Test_Set13(t *testing.T) {
|
||||
p.Set("array.0", 0)
|
||||
p.Set("array.1", 1)
|
||||
if c, err := p.ToJson(); err == nil {
|
||||
|
||||
if bytes.Compare(c, e) != 0 {
|
||||
t.Error("expect:", string(e))
|
||||
}
|
||||
@ -216,7 +201,16 @@ func Test_Set13(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
func Test_Set14(t *testing.T) {
|
||||
e := []byte(`{"f":{"a":1}}`)
|
||||
p := gparser.New(nil)
|
||||
p.Set("f", "m")
|
||||
p.Set("f.a", 1)
|
||||
if c, err := p.ToJson(); err == nil {
|
||||
if bytes.Compare(c, e) != 0 {
|
||||
t.Error("expect:", string(e))
|
||||
}
|
||||
} else {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@ -10,58 +10,55 @@
|
||||
package gxml
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/third/github.com/clbanning/mxj"
|
||||
"encoding/xml"
|
||||
"io"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/text/gregex"
|
||||
"github.com/gogf/gf/third/github.com/axgle/mahonia"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/third/github.com/clbanning/mxj"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 将XML内容解析为map变量
|
||||
func Decode(content []byte) (map[string]interface{}, error) {
|
||||
prepare(content)
|
||||
return mxj.NewMapXml(content)
|
||||
res, err := convert(content)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mxj.NewMapXml(res)
|
||||
}
|
||||
|
||||
// 将map变量解析为XML格式内容
|
||||
func Encode(v map[string]interface{}, rootTag...string) ([]byte, error) {
|
||||
return mxj.Map(v).Xml(rootTag...)
|
||||
func Encode(v map[string]interface{}, rootTag ...string) ([]byte, error) {
|
||||
return mxj.Map(v).Xml(rootTag...)
|
||||
}
|
||||
|
||||
func EncodeWithIndent(v map[string]interface{}, rootTag...string) ([]byte, error) {
|
||||
return mxj.Map(v).XmlIndent("", "\t", rootTag...)
|
||||
func EncodeWithIndent(v map[string]interface{}, rootTag ...string) ([]byte, error) {
|
||||
return mxj.Map(v).XmlIndent("", "\t", rootTag...)
|
||||
}
|
||||
|
||||
// XML格式内容直接转换为JSON格式内容
|
||||
func ToJson(content []byte) ([]byte, error) {
|
||||
prepare(content)
|
||||
mv, err := mxj.NewMapXml(content)
|
||||
res, err := convert(content)
|
||||
if err != nil {
|
||||
fmt.Println("convert error. ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mv, err := mxj.NewMapXml(res)
|
||||
if err == nil {
|
||||
return mv.Json()
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
return mv.Json()
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// XML字符集预处理
|
||||
// @author wenzi1
|
||||
// @date 20180604
|
||||
func prepare(xmlbyte []byte) error {
|
||||
// @date 20180604 修复并发安全问题,改为如果非UTF8字符集则先做字符集转换
|
||||
func convert(xmlbyte []byte) (res []byte, err error) {
|
||||
patten := `<\?xml.*encoding\s*=\s*['|"](.*?)['|"].*\?>`
|
||||
charsetReader := func(charset string, input io.Reader) (io.Reader, error) {
|
||||
reader := mahonia.GetCharset(charset)
|
||||
if reader == nil {
|
||||
return nil, errors.New(fmt.Sprintf("not support charset:%s", charset))
|
||||
}
|
||||
return reader.NewDecoder().NewReader(input), nil
|
||||
}
|
||||
|
||||
matchStr, err := gregex.MatchString(patten, string(xmlbyte))
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
xmlEncode := "UTF-8"
|
||||
@ -69,13 +66,19 @@ func prepare(xmlbyte []byte) error {
|
||||
xmlEncode = matchStr[1]
|
||||
}
|
||||
|
||||
charset := mahonia.GetCharset(xmlEncode)
|
||||
if charset == nil {
|
||||
return errors.New(fmt.Sprintf("not support charset:%s", xmlEncode))
|
||||
s := mahonia.GetCharset(xmlEncode)
|
||||
if s == nil {
|
||||
return nil, fmt.Errorf("not support charset:%s\n", xmlEncode)
|
||||
}
|
||||
|
||||
if !strings.EqualFold(charset.Name, "UTF-8") {
|
||||
mxj.CustomDecoder = &xml.Decoder{Strict : false, CharsetReader : charsetReader}
|
||||
res, err = gregex.Replace(patten, []byte(""), []byte(xmlbyte))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if !strings.EqualFold(s.Name, "UTF-8") {
|
||||
res = []byte(s.NewDecoder().ConvertString(string(res)))
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
140
g/encoding/gxml/gxml_test.go
Normal file
140
g/encoding/gxml/gxml_test.go
Normal file
@ -0,0 +1,140 @@
|
||||
// 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 gxml_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/gogf/gf/g/encoding/gcharset"
|
||||
"github.com/gogf/gf/g/encoding/gparser"
|
||||
"github.com/gogf/gf/g/encoding/gxml"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var testData = []struct {
|
||||
utf8, other, otherEncoding string
|
||||
}{
|
||||
{"Hello 常用國字標準字體表", "Hello \xb1`\xa5\u03b0\xea\xa6r\xbc\u0437\u01e6r\xc5\xe9\xaa\xed", "big5"},
|
||||
{"Hello 常用國字標準字體表", "Hello \xb3\xa3\xd3\xc3\x87\xf8\xd7\xd6\x98\xcb\x9c\xca\xd7\xd6\xf3\x77\xb1\xed", "gbk"},
|
||||
{"Hello 常用國字標準字體表", "Hello \xb3\xa3\xd3\xc3\x87\xf8\xd7\xd6\x98\xcb\x9c\xca\xd7\xd6\xf3\x77\xb1\xed", "gb18030"},
|
||||
}
|
||||
|
||||
func buildXml(charset string, str string) (string, string) {
|
||||
head := `<?xml version="1.0" encoding="UTF-8"?>`
|
||||
srcXml := strings.Replace(head, "UTF-8", charset, -1)
|
||||
|
||||
srcParser := gparser.New(nil)
|
||||
srcParser.Set("name", str)
|
||||
srcParser.Set("age", "12")
|
||||
|
||||
s, err := srcParser.ToXml()
|
||||
if err != nil {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
srcXml = srcXml + string(s)
|
||||
srcXml, err = gcharset.UTF8To(charset, srcXml)
|
||||
if err != nil {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
dstXml := head + string(s)
|
||||
|
||||
return srcXml, dstXml
|
||||
}
|
||||
|
||||
//测试XML中字符集的转换
|
||||
func Test_XmlToJson(t *testing.T) {
|
||||
for _, v := range testData {
|
||||
srcXml, dstXml := buildXml(v.otherEncoding, v.utf8)
|
||||
if len(srcXml) == 0 && len(dstXml) == 0 {
|
||||
t.Errorf("build xml string error. srcEncoding:%s, src:%s, utf8:%s", v.otherEncoding, v.other, v.utf8)
|
||||
}
|
||||
|
||||
srcJson, err := gxml.ToJson([]byte(srcXml))
|
||||
if err != nil {
|
||||
t.Errorf("gxml.ToJson error. %s", srcXml)
|
||||
}
|
||||
|
||||
dstJson, err := gxml.ToJson([]byte(dstXml))
|
||||
if err != nil {
|
||||
t.Errorf("dstXml to json error. %s", dstXml)
|
||||
}
|
||||
|
||||
if bytes.Compare(srcJson, dstJson) != 0 {
|
||||
t.Errorf("convert to json error. srcJson:%s, dstJson:%s", string(srcJson), string(dstJson))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Decode(t *testing.T) {
|
||||
for _, v := range testData {
|
||||
srcXml, dstXml := buildXml(v.otherEncoding, v.utf8)
|
||||
if len(srcXml) == 0 && len(dstXml) == 0 {
|
||||
t.Errorf("build xml string error. srcEncoding:%s, src:%s, utf8:%s", v.otherEncoding, v.other, v.utf8)
|
||||
}
|
||||
|
||||
srcMap, err := gxml.Decode([]byte(srcXml))
|
||||
if err != nil {
|
||||
t.Errorf("gxml.Decode error. %s", srcXml)
|
||||
}
|
||||
|
||||
dstMap, err := gxml.Decode([]byte(dstXml))
|
||||
if err != nil {
|
||||
t.Errorf("gxml decode error. %s", dstXml)
|
||||
}
|
||||
s := srcMap["doc"].(map[string]interface{})
|
||||
d := dstMap["doc"].(map[string]interface{})
|
||||
for kk, vv := range s {
|
||||
if vv.(string) != d[kk].(string) {
|
||||
t.Errorf("convert to map error. src:%v, dst:%v", vv, d[kk])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Encode(t *testing.T) {
|
||||
m := make(map[string]interface{})
|
||||
v := map[string]interface{}{
|
||||
"string": "hello world",
|
||||
"int": 123,
|
||||
"float": 100.92,
|
||||
"bool": true,
|
||||
}
|
||||
m["root"] = interface{}(v)
|
||||
|
||||
xmlStr, err := gxml.Encode(m)
|
||||
if err != nil {
|
||||
t.Errorf("encode error.")
|
||||
}
|
||||
t.Logf("%s\n", string(xmlStr))
|
||||
|
||||
res := `<root><bool>true</bool><float>100.92</float><int>123</int><string>hello world</string></root>`
|
||||
if string(xmlStr) != res {
|
||||
t.Errorf("encode error. result: [%s], expect:[%s]", string(xmlStr), res)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_EncodeIndent(t *testing.T) {
|
||||
m := make(map[string]interface{})
|
||||
v := map[string]interface{}{
|
||||
"string": "hello world",
|
||||
"int": 123,
|
||||
"float": 100.92,
|
||||
"bool": true,
|
||||
}
|
||||
m["root"] = interface{}(v)
|
||||
|
||||
xmlStr, err := gxml.EncodeWithIndent(m, "xml")
|
||||
if err != nil {
|
||||
t.Errorf("encodeWithIndent error.")
|
||||
}
|
||||
|
||||
t.Logf("%s\n", string(xmlStr))
|
||||
|
||||
}
|
||||
@ -4,10 +4,7 @@
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
// Package gins provides instances management and some core components.
|
||||
//
|
||||
// 单例对象管理.
|
||||
// 框架内置了一些核心对象获取方法,并且可以通过Set和Get方法实现IoC以及对内置核心对象的自定义替换
|
||||
// Package gins provides instances management and core components management.
|
||||
package gins
|
||||
|
||||
import (
|
||||
@ -21,9 +18,9 @@ import (
|
||||
"github.com/gogf/gf/g/os/gfsnotify"
|
||||
"github.com/gogf/gf/g/os/glog"
|
||||
"github.com/gogf/gf/g/os/gview"
|
||||
"github.com/gogf/gf/g/text/gregex"
|
||||
"github.com/gogf/gf/g/text/gstr"
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
"github.com/gogf/gf/g/text/gregex"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -101,23 +98,9 @@ func Config(file...string) *gcfg.Config {
|
||||
if len(file) > 0 {
|
||||
configFile = file[0]
|
||||
}
|
||||
return instances.GetOrSetFuncLock(fmt.Sprintf("%s.%s", gFRAME_CORE_COMPONENT_NAME_CONFIG, configFile),
|
||||
func() interface{} {
|
||||
// 默认当前工作目录
|
||||
config := gcfg.New(gfile.Pwd(), configFile)
|
||||
// 自定义的环境变量/启动参数路径,优先级最高,覆盖默认的工作目录
|
||||
if envPath := cmdenv.Get("gf.gcfg.path").String(); envPath != "" && gfile.Exists(envPath) {
|
||||
config.SetPath(envPath)
|
||||
}
|
||||
// 二进制文件执行目录
|
||||
if selfPath := gfile.SelfDir(); selfPath != "" && gfile.Exists(selfPath) {
|
||||
config.AddPath(selfPath)
|
||||
}
|
||||
// 开发环境源码main包目录
|
||||
if mainPath := gfile.MainPkgPath(); mainPath != "" && gfile.Exists(mainPath) {
|
||||
config.AddPath(mainPath)
|
||||
}
|
||||
return config
|
||||
key := fmt.Sprintf("%s.%s", gFRAME_CORE_COMPONENT_NAME_CONFIG, configFile)
|
||||
return instances.GetOrSetFuncLock(key, func() interface{} {
|
||||
return gcfg.New(configFile)
|
||||
}).(*gcfg.Config)
|
||||
}
|
||||
|
||||
@ -139,62 +122,66 @@ func Database(name...string) gdb.DB {
|
||||
for group, v := range m {
|
||||
cg := gdb.ConfigGroup{}
|
||||
if list, ok := v.([]interface{}); ok {
|
||||
for _, nodev := range list {
|
||||
node := gdb.ConfigNode{}
|
||||
nodem := nodev.(map[string]interface{})
|
||||
if value, ok := nodem["host"]; ok {
|
||||
for _, nodeValue := range list {
|
||||
node := gdb.ConfigNode{}
|
||||
nodeMap := nodeValue.(map[string]interface{})
|
||||
if value, ok := nodeMap["host"]; ok {
|
||||
node.Host = gconv.String(value)
|
||||
}
|
||||
if value, ok := nodem["port"]; ok {
|
||||
if value, ok := nodeMap["port"]; ok {
|
||||
node.Port = gconv.String(value)
|
||||
}
|
||||
if value, ok := nodem["user"]; ok {
|
||||
if value, ok := nodeMap["user"]; ok {
|
||||
node.User = gconv.String(value)
|
||||
}
|
||||
if value, ok := nodem["pass"]; ok {
|
||||
if value, ok := nodeMap["pass"]; ok {
|
||||
node.Pass = gconv.String(value)
|
||||
}
|
||||
if value, ok := nodem["name"]; ok {
|
||||
if value, ok := nodeMap["name"]; ok {
|
||||
node.Name = gconv.String(value)
|
||||
}
|
||||
if value, ok := nodem["type"]; ok {
|
||||
if value, ok := nodeMap["type"]; ok {
|
||||
node.Type = gconv.String(value)
|
||||
}
|
||||
if value, ok := nodem["role"]; ok {
|
||||
if value, ok := nodeMap["role"]; ok {
|
||||
node.Role = gconv.String(value)
|
||||
}
|
||||
if value, ok := nodem["charset"]; ok {
|
||||
if value, ok := nodeMap["charset"]; ok {
|
||||
node.Charset = gconv.String(value)
|
||||
}
|
||||
if value, ok := nodem["priority"]; ok {
|
||||
if value, ok := nodeMap["priority"]; ok {
|
||||
node.Priority = gconv.Int(value)
|
||||
}
|
||||
// Deprecated
|
||||
if value, ok := nodem["linkinfo"]; ok {
|
||||
node.Linkinfo = gconv.String(value)
|
||||
}
|
||||
if value, ok := nodem["linkInfo"]; ok {
|
||||
node.Linkinfo = gconv.String(value)
|
||||
if value, ok := nodeMap["linkinfo"]; ok {
|
||||
node.LinkInfo = gconv.String(value)
|
||||
}
|
||||
// Deprecated
|
||||
if value, ok := nodem["max-idle"]; ok {
|
||||
if value, ok := nodeMap["link-info"]; ok {
|
||||
node.LinkInfo = gconv.String(value)
|
||||
}
|
||||
if value, ok := nodeMap["linkInfo"]; ok {
|
||||
node.LinkInfo = gconv.String(value)
|
||||
}
|
||||
// Deprecated
|
||||
if value, ok := nodeMap["max-idle"]; ok {
|
||||
node.MaxIdleConnCount = gconv.Int(value)
|
||||
}
|
||||
if value, ok := nodem["maxIdle"]; ok {
|
||||
if value, ok := nodeMap["maxIdle"]; ok {
|
||||
node.MaxIdleConnCount = gconv.Int(value)
|
||||
}
|
||||
// Deprecated
|
||||
if value, ok := nodem["max-open"]; ok {
|
||||
if value, ok := nodeMap["max-open"]; ok {
|
||||
node.MaxOpenConnCount = gconv.Int(value)
|
||||
}
|
||||
if value, ok := nodem["maxOpen"]; ok {
|
||||
if value, ok := nodeMap["maxOpen"]; ok {
|
||||
node.MaxOpenConnCount = gconv.Int(value)
|
||||
}
|
||||
// Deprecated
|
||||
if value, ok := nodem["max-lifetime"]; ok {
|
||||
if value, ok := nodeMap["max-lifetime"]; ok {
|
||||
node.MaxConnLifetime = gconv.Int(value)
|
||||
}
|
||||
if value, ok := nodem["maxLifetime"]; ok {
|
||||
if value, ok := nodeMap["maxLifetime"]; ok {
|
||||
node.MaxConnLifetime = gconv.Int(value)
|
||||
}
|
||||
cg = append(cg, node)
|
||||
@ -202,10 +189,7 @@ func Database(name...string) gdb.DB {
|
||||
}
|
||||
gdb.AddConfigGroup(group, cg)
|
||||
}
|
||||
// 使用gfsnotify进行文件监控,当配置文件有任何变化时,清空数据库配置缓存
|
||||
gfsnotify.Add(config.GetFilePath(), func(event *gfsnotify.Event) {
|
||||
instances.Remove(key)
|
||||
})
|
||||
addConfigMonitor(key, config)
|
||||
}
|
||||
if db, err := gdb.New(name...); err == nil {
|
||||
return db
|
||||
@ -235,29 +219,31 @@ func Redis(name...string) *gredis.Redis {
|
||||
line := gconv.String(v)
|
||||
array, _ := gregex.MatchString(`(.+):(\d+),{0,1}(\d*),{0,1}(.*)\?(.+)`, line)
|
||||
if len(array) == 6 {
|
||||
parse, _ := gstr.Parse(array[5])
|
||||
config := gredis.Config{
|
||||
parse, _ := gstr.Parse(array[5])
|
||||
redisConfig := gredis.Config{
|
||||
Host : array[1],
|
||||
Port : gconv.Int(array[2]),
|
||||
Db : gconv.Int(array[3]),
|
||||
Pass : array[4],
|
||||
}
|
||||
if v, ok := parse["maxIdle"]; ok {
|
||||
config.MaxIdle = gconv.Int(v)
|
||||
redisConfig.MaxIdle = gconv.Int(v)
|
||||
}
|
||||
if v, ok := parse["maxActive"]; ok {
|
||||
config.MaxActive = gconv.Int(v)
|
||||
redisConfig.MaxActive = gconv.Int(v)
|
||||
}
|
||||
if v, ok := parse["idleTimeout"]; ok {
|
||||
config.IdleTimeout = gconv.TimeDuration(v)*time.Second
|
||||
redisConfig.IdleTimeout = gconv.TimeDuration(v)*time.Second
|
||||
}
|
||||
if v, ok := parse["maxConnLifetime"]; ok {
|
||||
config.MaxConnLifetime = gconv.TimeDuration(v)*time.Second
|
||||
redisConfig.MaxConnLifetime = gconv.TimeDuration(v)*time.Second
|
||||
}
|
||||
return gredis.New(config)
|
||||
addConfigMonitor(key, config)
|
||||
return gredis.New(redisConfig)
|
||||
}
|
||||
array, _ = gregex.MatchString(`(.+):(\d+),{0,1}(\d*),{0,1}(.*)`, line)
|
||||
if len(array) == 5 {
|
||||
addConfigMonitor(key, config)
|
||||
return gredis.New(gredis.Config{
|
||||
Host : array[1],
|
||||
Port : gconv.Int(array[2]),
|
||||
@ -281,6 +267,16 @@ func Redis(name...string) *gredis.Redis {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 添加对单例对象的配置文件inotify监控
|
||||
func addConfigMonitor(key string, config *gcfg.Config) {
|
||||
// 使用gfsnotify进行文件监控,当配置文件有任何变化时,清空对象单例缓存
|
||||
if path := config.GetFilePath(); path != "" {
|
||||
gfsnotify.Add(path, func(event *gfsnotify.Event) {
|
||||
instances.Remove(key)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 模板内置方法:config
|
||||
func funcConfig(pattern string, file...string) string {
|
||||
return Config().GetString(pattern, file...)
|
||||
|
||||
@ -57,7 +57,7 @@ test = "v=1"
|
||||
err := gfile.PutContents(path, config)
|
||||
gtest.Assert(err, nil)
|
||||
defer gfile.Remove(path)
|
||||
defer gins.Config().Reload()
|
||||
defer gins.Config().Clear()
|
||||
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")
|
||||
@ -71,7 +71,7 @@ test = "v=1"
|
||||
err := gfile.PutContents(path, config)
|
||||
gtest.Assert(err, nil)
|
||||
defer gfile.Remove(path)
|
||||
defer gins.Config().Reload()
|
||||
defer gins.Config().Clear()
|
||||
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")
|
||||
@ -84,7 +84,7 @@ test = "v=1"
|
||||
err := gfile.PutContents(path, config)
|
||||
gtest.Assert(err, nil)
|
||||
defer gfile.Remove(path)
|
||||
defer gins.Config().Reload()
|
||||
defer gins.Config().Clear()
|
||||
gtest.Assert(gins.Config("test.toml").Get("test"), "v=1")
|
||||
gtest.Assert(gins.Config("test.toml").Get("database.default.1.host"), "127.0.0.1")
|
||||
gtest.Assert(gins.Config("test.toml").Get("redis.disk"), "127.0.0.1:6379,0")
|
||||
@ -97,7 +97,7 @@ test = "v=1"
|
||||
err := gfile.PutContents(path, config)
|
||||
gtest.Assert(err, nil)
|
||||
defer gfile.Remove(path)
|
||||
defer gins.Config().Reload()
|
||||
defer gins.Config().Clear()
|
||||
gtest.Assert(gins.Config("test.toml").Get("test"), "v=1")
|
||||
gtest.Assert(gins.Config("test.toml").Get("database.default.1.host"), "127.0.0.1")
|
||||
gtest.Assert(gins.Config("test.toml").Get("redis.disk"), "127.0.0.1:6379,0")
|
||||
@ -113,7 +113,7 @@ test = "v=1"
|
||||
err := gfile.PutContents(file, config)
|
||||
gtest.Assert(err, nil)
|
||||
defer gfile.Remove(file)
|
||||
defer gins.Config().Reload()
|
||||
defer gins.Config().Clear()
|
||||
gtest.Assert(gins.Config().AddPath(path), nil)
|
||||
gtest.Assert(gins.Config().Get("test"), "v=1")
|
||||
gtest.Assert(gins.Config().Get("database.default.1.host"), "127.0.0.1")
|
||||
@ -127,7 +127,7 @@ test = "v=1"
|
||||
err := gfile.PutContents(file, config)
|
||||
gtest.Assert(err, nil)
|
||||
defer gfile.Remove(file)
|
||||
defer gins.Config().Reload()
|
||||
defer gins.Config().Clear()
|
||||
gtest.Assert(gins.Config().AddPath(path), nil)
|
||||
gtest.Assert(gins.Config().Get("test"), "v=1")
|
||||
gtest.Assert(gins.Config().Get("database.default.1.host"), "127.0.0.1")
|
||||
@ -141,7 +141,7 @@ test = "v=1"
|
||||
err := gfile.PutContents(file, config)
|
||||
gtest.Assert(err, nil)
|
||||
defer gfile.Remove(file)
|
||||
defer gins.Config("test.toml").Reload()
|
||||
defer gins.Config("test.toml").Clear()
|
||||
|
||||
gtest.Assert(gins.Config("test.toml").AddPath(path), nil)
|
||||
gtest.Assert(gins.Config("test.toml").Get("test"), "v=1")
|
||||
@ -156,7 +156,7 @@ test = "v=1"
|
||||
err := gfile.PutContents(file, config)
|
||||
gtest.Assert(err, nil)
|
||||
defer gfile.Remove(file)
|
||||
defer gins.Config("test.toml").Reload()
|
||||
defer gins.Config("test.toml").Clear()
|
||||
|
||||
gtest.Assert(gins.Config("test.toml").AddPath(path), nil)
|
||||
gtest.Assert(gins.Config("test.toml").Get("test"), "v=1")
|
||||
|
||||
@ -53,7 +53,7 @@ test = "v=2"
|
||||
err := gfile.PutContents(path, config)
|
||||
gtest.Assert(err, nil)
|
||||
defer gfile.Remove(path)
|
||||
defer gins.Config().Reload()
|
||||
defer gins.Config().Clear()
|
||||
|
||||
// for gfsnotify callbacks to refresh cache of config file
|
||||
time.Sleep(500*time.Millisecond)
|
||||
|
||||
@ -53,7 +53,7 @@ test = "v=3"
|
||||
err := gfile.PutContents(path, config)
|
||||
gtest.Assert(err, nil)
|
||||
defer gfile.Remove(path)
|
||||
defer gins.Config().Reload()
|
||||
defer gins.Config().Clear()
|
||||
|
||||
// for gfsnotify callbacks to refresh cache of config file
|
||||
time.Sleep(500*time.Millisecond)
|
||||
|
||||
@ -168,7 +168,7 @@ func getServerFdMap() map[string]listenerFdMap {
|
||||
func bufferToServerFdMap(buffer []byte) map[string]listenerFdMap {
|
||||
sfm := make(map[string]listenerFdMap)
|
||||
if len(buffer) > 0 {
|
||||
j, _ := gjson.LoadContent(buffer, "json")
|
||||
j, _ := gjson.LoadContent(buffer)
|
||||
for k, _ := range j.ToMap() {
|
||||
m := make(map[string]string)
|
||||
for k, v := range j.GetMap(k) {
|
||||
|
||||
@ -30,7 +30,7 @@ var serverMapping = gmap.NewStringInterfaceMap()
|
||||
|
||||
// 获取/创建一个空配置的TCP Server
|
||||
// 单例模式,请保证name的唯一性
|
||||
func GetServer(name...interface{}) (*Server) {
|
||||
func GetServer(name...interface{}) *Server {
|
||||
serverName := gDEFAULT_SERVER
|
||||
if len(name) > 0 {
|
||||
serverName = gconv.String(name[0])
|
||||
|
||||
@ -4,44 +4,41 @@
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
// Package gcfg provides reading, caching and managing for configuration files.
|
||||
//
|
||||
// 配置管理,
|
||||
// 配置文件格式支持:json, xml, toml, yaml/yml
|
||||
// Package gcfg provides reading, caching and managing for configuration files/contents.
|
||||
package gcfg
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/garray"
|
||||
"github.com/gogf/gf/g/container/gmap"
|
||||
"github.com/gogf/gf/g/container/gtype"
|
||||
"github.com/gogf/gf/g/container/gvar"
|
||||
"github.com/gogf/gf/g/encoding/gjson"
|
||||
"github.com/gogf/gf/g/os/gfile"
|
||||
"github.com/gogf/gf/g/os/gfsnotify"
|
||||
"github.com/gogf/gf/g/os/glog"
|
||||
"github.com/gogf/gf/g/os/gspath"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/garray"
|
||||
"github.com/gogf/gf/g/container/gmap"
|
||||
"github.com/gogf/gf/g/container/gtype"
|
||||
"github.com/gogf/gf/g/container/gvar"
|
||||
"github.com/gogf/gf/g/encoding/gjson"
|
||||
"github.com/gogf/gf/g/internal/cmdenv"
|
||||
"github.com/gogf/gf/g/os/gfile"
|
||||
"github.com/gogf/gf/g/os/gfsnotify"
|
||||
"github.com/gogf/gf/g/os/glog"
|
||||
"github.com/gogf/gf/g/os/gspath"
|
||||
)
|
||||
|
||||
const (
|
||||
// 默认的配置管理文件名称
|
||||
// Default configuration file name.
|
||||
DEFAULT_CONFIG_FILE = "config.toml"
|
||||
)
|
||||
|
||||
// 配置管理对象
|
||||
// Configuration struct.
|
||||
type Config struct {
|
||||
name *gtype.String // 默认配置文件名称
|
||||
paths *garray.StringArray // 搜索目录路径
|
||||
jsons *gmap.StringInterfaceMap // 配置文件对象
|
||||
vc *gtype.Bool // 层级检索是否执行分隔符冲突检测(默认为false,检测会比较影响检索效率)
|
||||
name *gtype.String // Default configuration file name.
|
||||
paths *garray.StringArray // Searching path array.
|
||||
jsons *gmap.StringInterfaceMap // The pared JSON objects for configuration files.
|
||||
vc *gtype.Bool // Whether do violence check in value index searching.
|
||||
// It affects the performance when set true(false in default).
|
||||
}
|
||||
|
||||
// New returns a new configuration management object.
|
||||
//
|
||||
// 生成一个配置管理对象
|
||||
func New(path string, file...string) *Config {
|
||||
func New(file...string) *Config {
|
||||
name := DEFAULT_CONFIG_FILE
|
||||
if len(file) > 0 {
|
||||
name = file[0]
|
||||
@ -52,15 +49,24 @@ func New(path string, file...string) *Config {
|
||||
jsons : gmap.NewStringInterfaceMap(),
|
||||
vc : gtype.NewBool(),
|
||||
}
|
||||
if len(path) > 0 {
|
||||
c.SetPath(path)
|
||||
}
|
||||
// Dir path of working dir.
|
||||
c.SetPath(gfile.Pwd())
|
||||
// Dir path from env/cmd, most high priority, will overwrite previous dir path setting.
|
||||
if envPath := cmdenv.Get("gf.gcfg.path").String(); envPath != "" && gfile.Exists(envPath) {
|
||||
c.SetPath(envPath)
|
||||
}
|
||||
// Dir path of binary.
|
||||
if selfPath := gfile.SelfDir(); selfPath != "" && gfile.Exists(selfPath) {
|
||||
c.AddPath(selfPath)
|
||||
}
|
||||
// Dir path of main package.
|
||||
if mainPath := gfile.MainPkgPath(); mainPath != "" && gfile.Exists(mainPath) {
|
||||
c.AddPath(mainPath)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// filePath returns the absolute configuration file path for the given filename by <file>.
|
||||
//
|
||||
// 判断从哪个配置文件中获取内容,返回配置文件的绝对路径
|
||||
func (c *Config) filePath(file...string) (path string) {
|
||||
name := c.name.Val()
|
||||
if len(file) > 0 {
|
||||
@ -137,7 +143,7 @@ func (c *Config) SetPath(path string) error {
|
||||
// 开启比较耗性能,也不建议允许键名中存在分隔符,最好在应用端避免这种情况。
|
||||
func (c *Config) SetViolenceCheck(check bool) {
|
||||
c.vc.Set(check)
|
||||
c.Reload()
|
||||
c.Clear()
|
||||
}
|
||||
|
||||
// 添加配置管理器的配置文件搜索路径
|
||||
@ -228,19 +234,30 @@ func (c *Config) getJson(file...string) *gjson.Json {
|
||||
name = file[0]
|
||||
}
|
||||
r := c.jsons.GetOrSetFuncLock(name, func() interface{} {
|
||||
filePath := c.filePath(file...)
|
||||
if filePath == "" {
|
||||
return nil
|
||||
content := ""
|
||||
filePath := ""
|
||||
if content = GetContent(name); content == "" {
|
||||
filePath = c.filePath(name)
|
||||
if filePath == "" {
|
||||
return nil
|
||||
}
|
||||
content = gfile.GetContents(filePath)
|
||||
}
|
||||
if j, err := gjson.Load(filePath); err == nil {
|
||||
if j, err := gjson.LoadContent(content); err == nil {
|
||||
j.SetViolenceCheck(c.vc.Val())
|
||||
// 添加配置文件监听,如果有任何变化,删除文件内容缓存,下一次查询会自动更新
|
||||
gfsnotify.Add(filePath, func(event *gfsnotify.Event) {
|
||||
c.jsons.Remove(name)
|
||||
})
|
||||
if filePath != "" {
|
||||
gfsnotify.Add(filePath, func(event *gfsnotify.Event) {
|
||||
c.jsons.Remove(name)
|
||||
})
|
||||
}
|
||||
return j
|
||||
} else {
|
||||
glog.Criticalfln(`[gcfg] Load config file "%s" failed: %s`, filePath, err.Error())
|
||||
if filePath != "" {
|
||||
glog.Criticalfln(`[gcfg] Load config file "%s" failed: %s`, filePath, err.Error())
|
||||
} else {
|
||||
glog.Criticalfln(`[gcfg] Load configuration failed: %s`, err.Error())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@ -432,8 +449,14 @@ func (c *Config) GetToStruct(pattern string, objPointer interface{}, file...stri
|
||||
return errors.New("config file not found")
|
||||
}
|
||||
|
||||
// 清空当前配置文件缓存,强制重新从磁盘文件读取配置文件内容
|
||||
// Deprecated. See Clear.
|
||||
func (c *Config) Reload() {
|
||||
c.jsons.Clear()
|
||||
}
|
||||
|
||||
// Clear removes all parsed configuration files content cache,
|
||||
// which will force reload configuration content from file.
|
||||
func (c *Config) Clear() {
|
||||
c.jsons.Clear()
|
||||
}
|
||||
|
||||
|
||||
39
g/os/gcfg/gcfg_config.go
Normal file
39
g/os/gcfg/gcfg_config.go
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright 2019 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 gcfg
|
||||
|
||||
import "github.com/gogf/gf/g/container/gmap"
|
||||
|
||||
var (
|
||||
// Customized configuration content.
|
||||
configs = gmap.NewStringStringMap()
|
||||
)
|
||||
|
||||
// SetContent sets customized configuration content for specified <file>.
|
||||
// The <file> is unnecessary param, default is DEFAULT_CONFIG_FILE.
|
||||
func SetContent(content string, file...string) {
|
||||
name := DEFAULT_CONFIG_FILE
|
||||
if len(file) > 0 {
|
||||
name = file[0]
|
||||
}
|
||||
configs.Set(name, content)
|
||||
}
|
||||
|
||||
// GetContent returns customized configuration content for specified <file>.
|
||||
// The <file> is unnecessary param, default is DEFAULT_CONFIG_FILE.
|
||||
func GetContent(file...string) string {
|
||||
name := DEFAULT_CONFIG_FILE
|
||||
if len(file) > 0 {
|
||||
name = file[0]
|
||||
}
|
||||
return configs.Get(name)
|
||||
}
|
||||
|
||||
// ClearContent removes all global configuration contents.
|
||||
func ClearContent() {
|
||||
configs.Clear()
|
||||
}
|
||||
27
g/os/gcfg/gcfg_instance.go
Normal file
27
g/os/gcfg/gcfg_instance.go
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2019 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 gcfg
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/container/gmap"
|
||||
)
|
||||
|
||||
var (
|
||||
// Instances map.
|
||||
instances = gmap.NewStringInterfaceMap()
|
||||
)
|
||||
|
||||
// Instance returns an instance of Config.
|
||||
func Instance(file...string) *Config {
|
||||
configFile := DEFAULT_CONFIG_FILE
|
||||
if len(file) > 0 {
|
||||
configFile = file[0]
|
||||
}
|
||||
return instances.GetOrSetFuncLock(configFile, func() interface{} {
|
||||
return New(configFile)
|
||||
}).(*Config)
|
||||
}
|
||||
@ -27,12 +27,12 @@ array = [1,2,3]
|
||||
cache = "127.0.0.1:6379,1"
|
||||
`
|
||||
gtest.Case(t, func() {
|
||||
path := "config.toml"
|
||||
path := gcfg.DEFAULT_CONFIG_FILE
|
||||
err := gfile.PutContents(path, config)
|
||||
gtest.Assert(err, nil)
|
||||
defer gfile.Remove(path)
|
||||
|
||||
c := gcfg.New(".")
|
||||
c := gcfg.New()
|
||||
gtest.Assert(c.Get("v1"), 1)
|
||||
gtest.AssertEQ(c.GetInt("v1"), 1)
|
||||
gtest.AssertEQ(c.GetInt8("v1"), int8(1))
|
||||
@ -71,7 +71,201 @@ array = [1,2,3]
|
||||
"disk" : "127.0.0.1:6379,0",
|
||||
"cache" : "127.0.0.1:6379,1",
|
||||
})
|
||||
gtest.AssertEQ(c.GetFilePath(), gfile.Pwd() + gfile.Separator + "config.toml")
|
||||
gtest.AssertEQ(c.GetFilePath(), gfile.Pwd() + gfile.Separator + path)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Content(t *testing.T) {
|
||||
content := `
|
||||
v1 = 1
|
||||
v2 = "true"
|
||||
v3 = "off"
|
||||
v4 = "1.23"
|
||||
array = [1,2,3]
|
||||
[redis]
|
||||
disk = "127.0.0.1:6379,0"
|
||||
cache = "127.0.0.1:6379,1"
|
||||
`
|
||||
gcfg.SetContent(content)
|
||||
defer gcfg.ClearContent()
|
||||
|
||||
gtest.Case(t, func() {
|
||||
c := gcfg.New()
|
||||
gtest.Assert(c.Get("v1"), 1)
|
||||
gtest.AssertEQ(c.GetInt("v1"), 1)
|
||||
gtest.AssertEQ(c.GetInt8("v1"), int8(1))
|
||||
gtest.AssertEQ(c.GetInt16("v1"), int16(1))
|
||||
gtest.AssertEQ(c.GetInt32("v1"), int32(1))
|
||||
gtest.AssertEQ(c.GetInt64("v1"), int64(1))
|
||||
gtest.AssertEQ(c.GetUint("v1"), uint(1))
|
||||
gtest.AssertEQ(c.GetUint8("v1"), uint8(1))
|
||||
gtest.AssertEQ(c.GetUint16("v1"), uint16(1))
|
||||
gtest.AssertEQ(c.GetUint32("v1"), uint32(1))
|
||||
gtest.AssertEQ(c.GetUint64("v1"), uint64(1))
|
||||
|
||||
gtest.AssertEQ(c.GetVar("v1").String(), "1")
|
||||
gtest.AssertEQ(c.GetVar("v1").Bool(), true)
|
||||
gtest.AssertEQ(c.GetVar("v2").String(), "true")
|
||||
gtest.AssertEQ(c.GetVar("v2").Bool(), true)
|
||||
|
||||
gtest.AssertEQ(c.GetString("v1"), "1")
|
||||
gtest.AssertEQ(c.GetFloat32("v4"), float32(1.23))
|
||||
gtest.AssertEQ(c.GetFloat64("v4"), float64(1.23))
|
||||
gtest.AssertEQ(c.GetString("v2"), "true")
|
||||
gtest.AssertEQ(c.GetBool("v2"), true)
|
||||
gtest.AssertEQ(c.GetBool("v3"), false)
|
||||
|
||||
gtest.AssertEQ(c.Contains("v1"), true)
|
||||
gtest.AssertEQ(c.Contains("v2"), true)
|
||||
gtest.AssertEQ(c.Contains("v3"), true)
|
||||
gtest.AssertEQ(c.Contains("v4"), true)
|
||||
gtest.AssertEQ(c.Contains("v5"), false)
|
||||
|
||||
gtest.AssertEQ(c.GetInts("array"), []int{1,2,3})
|
||||
gtest.AssertEQ(c.GetStrings("array"), []string{"1","2","3"})
|
||||
gtest.AssertEQ(c.GetArray("array"), []interface{}{"1","2","3"})
|
||||
gtest.AssertEQ(c.GetInterfaces("array"), []interface{}{"1","2","3"})
|
||||
gtest.AssertEQ(c.GetMap("redis"), map[string]interface{}{
|
||||
"disk" : "127.0.0.1:6379,0",
|
||||
"cache" : "127.0.0.1:6379,1",
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func Test_SetFileName(t *testing.T) {
|
||||
config := `
|
||||
{
|
||||
"array": [
|
||||
1,
|
||||
2,
|
||||
3
|
||||
],
|
||||
"redis": {
|
||||
"cache": "127.0.0.1:6379,1",
|
||||
"disk": "127.0.0.1:6379,0"
|
||||
},
|
||||
"v1": 1,
|
||||
"v2": "true",
|
||||
"v3": "off",
|
||||
"v4": "1.234"
|
||||
}
|
||||
`
|
||||
gtest.Case(t, func() {
|
||||
path := "config.json"
|
||||
err := gfile.PutContents(path, config)
|
||||
gtest.Assert(err, nil)
|
||||
defer gfile.Remove(path)
|
||||
|
||||
c := gcfg.New()
|
||||
c.SetFileName(path)
|
||||
gtest.Assert(c.Get("v1"), 1)
|
||||
gtest.AssertEQ(c.GetInt("v1"), 1)
|
||||
gtest.AssertEQ(c.GetInt8("v1"), int8(1))
|
||||
gtest.AssertEQ(c.GetInt16("v1"), int16(1))
|
||||
gtest.AssertEQ(c.GetInt32("v1"), int32(1))
|
||||
gtest.AssertEQ(c.GetInt64("v1"), int64(1))
|
||||
gtest.AssertEQ(c.GetUint("v1"), uint(1))
|
||||
gtest.AssertEQ(c.GetUint8("v1"), uint8(1))
|
||||
gtest.AssertEQ(c.GetUint16("v1"), uint16(1))
|
||||
gtest.AssertEQ(c.GetUint32("v1"), uint32(1))
|
||||
gtest.AssertEQ(c.GetUint64("v1"), uint64(1))
|
||||
|
||||
gtest.AssertEQ(c.GetVar("v1").String(), "1")
|
||||
gtest.AssertEQ(c.GetVar("v1").Bool(), true)
|
||||
gtest.AssertEQ(c.GetVar("v2").String(), "true")
|
||||
gtest.AssertEQ(c.GetVar("v2").Bool(), true)
|
||||
|
||||
gtest.AssertEQ(c.GetString("v1"), "1")
|
||||
gtest.AssertEQ(c.GetFloat32("v4"), float32(1.234))
|
||||
gtest.AssertEQ(c.GetFloat64("v4"), float64(1.234))
|
||||
gtest.AssertEQ(c.GetString("v2"), "true")
|
||||
gtest.AssertEQ(c.GetBool("v2"), true)
|
||||
gtest.AssertEQ(c.GetBool("v3"), false)
|
||||
|
||||
gtest.AssertEQ(c.Contains("v1"), true)
|
||||
gtest.AssertEQ(c.Contains("v2"), true)
|
||||
gtest.AssertEQ(c.Contains("v3"), true)
|
||||
gtest.AssertEQ(c.Contains("v4"), true)
|
||||
gtest.AssertEQ(c.Contains("v5"), false)
|
||||
|
||||
gtest.AssertEQ(c.GetInts("array"), []int{1,2,3})
|
||||
gtest.AssertEQ(c.GetStrings("array"), []string{"1","2","3"})
|
||||
gtest.AssertEQ(c.GetArray("array"), []interface{}{"1","2","3"})
|
||||
gtest.AssertEQ(c.GetInterfaces("array"), []interface{}{"1","2","3"})
|
||||
gtest.AssertEQ(c.GetMap("redis"), map[string]interface{}{
|
||||
"disk" : "127.0.0.1:6379,0",
|
||||
"cache" : "127.0.0.1:6379,1",
|
||||
})
|
||||
gtest.AssertEQ(c.GetFilePath(), gfile.Pwd() + gfile.Separator + path)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Instance(t *testing.T) {
|
||||
config := `
|
||||
{
|
||||
"array": [
|
||||
1,
|
||||
2,
|
||||
3
|
||||
],
|
||||
"redis": {
|
||||
"cache": "127.0.0.1:6379,1",
|
||||
"disk": "127.0.0.1:6379,0"
|
||||
},
|
||||
"v1": 1,
|
||||
"v2": "true",
|
||||
"v3": "off",
|
||||
"v4": "1.234"
|
||||
}
|
||||
`
|
||||
gtest.Case(t, func() {
|
||||
path := gcfg.DEFAULT_CONFIG_FILE
|
||||
err := gfile.PutContents(path, config)
|
||||
gtest.Assert(err, nil)
|
||||
defer gfile.Remove(path)
|
||||
|
||||
c := gcfg.Instance()
|
||||
gtest.Assert(c.Get("v1"), 1)
|
||||
gtest.AssertEQ(c.GetInt("v1"), 1)
|
||||
gtest.AssertEQ(c.GetInt8("v1"), int8(1))
|
||||
gtest.AssertEQ(c.GetInt16("v1"), int16(1))
|
||||
gtest.AssertEQ(c.GetInt32("v1"), int32(1))
|
||||
gtest.AssertEQ(c.GetInt64("v1"), int64(1))
|
||||
gtest.AssertEQ(c.GetUint("v1"), uint(1))
|
||||
gtest.AssertEQ(c.GetUint8("v1"), uint8(1))
|
||||
gtest.AssertEQ(c.GetUint16("v1"), uint16(1))
|
||||
gtest.AssertEQ(c.GetUint32("v1"), uint32(1))
|
||||
gtest.AssertEQ(c.GetUint64("v1"), uint64(1))
|
||||
|
||||
gtest.AssertEQ(c.GetVar("v1").String(), "1")
|
||||
gtest.AssertEQ(c.GetVar("v1").Bool(), true)
|
||||
gtest.AssertEQ(c.GetVar("v2").String(), "true")
|
||||
gtest.AssertEQ(c.GetVar("v2").Bool(), true)
|
||||
|
||||
gtest.AssertEQ(c.GetString("v1"), "1")
|
||||
gtest.AssertEQ(c.GetFloat32("v4"), float32(1.234))
|
||||
gtest.AssertEQ(c.GetFloat64("v4"), float64(1.234))
|
||||
gtest.AssertEQ(c.GetString("v2"), "true")
|
||||
gtest.AssertEQ(c.GetBool("v2"), true)
|
||||
gtest.AssertEQ(c.GetBool("v3"), false)
|
||||
|
||||
gtest.AssertEQ(c.Contains("v1"), true)
|
||||
gtest.AssertEQ(c.Contains("v2"), true)
|
||||
gtest.AssertEQ(c.Contains("v3"), true)
|
||||
gtest.AssertEQ(c.Contains("v4"), true)
|
||||
gtest.AssertEQ(c.Contains("v5"), false)
|
||||
|
||||
gtest.AssertEQ(c.GetInts("array"), []int{1,2,3})
|
||||
gtest.AssertEQ(c.GetStrings("array"), []string{"1","2","3"})
|
||||
gtest.AssertEQ(c.GetArray("array"), []interface{}{"1","2","3"})
|
||||
gtest.AssertEQ(c.GetInterfaces("array"), []interface{}{"1","2","3"})
|
||||
gtest.AssertEQ(c.GetMap("redis"), map[string]interface{}{
|
||||
"disk" : "127.0.0.1:6379,0",
|
||||
"cache" : "127.0.0.1:6379,1",
|
||||
})
|
||||
gtest.AssertEQ(c.GetFilePath(), gfile.Pwd() + gfile.Separator + path)
|
||||
|
||||
})
|
||||
}
|
||||
@ -141,11 +141,6 @@ func (c *Cron) Search(name string) *Entry {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 根据指定名称删除定时任务
|
||||
func (c *Cron) Remove(name string) {
|
||||
c.entries.Remove(name)
|
||||
}
|
||||
|
||||
// 开启定时任务执行(可以指定特定名称的一个或若干个定时任务)
|
||||
func (c *Cron) Start(name...string) {
|
||||
if len(name) > 0 {
|
||||
@ -172,6 +167,13 @@ func (c *Cron) Stop(name...string) {
|
||||
}
|
||||
}
|
||||
|
||||
// 根据指定名称删除定时任务。
|
||||
func (c *Cron) Remove(name string) {
|
||||
if v := c.entries.Get(name); v != nil {
|
||||
v.(*Entry).Close()
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭定时任务
|
||||
func (c *Cron) Close() {
|
||||
c.status.Set(STATUS_CLOSED)
|
||||
|
||||
@ -87,7 +87,7 @@ func (entry *Entry) Stop() {
|
||||
|
||||
// 关闭定时任务
|
||||
func (entry *Entry) Close() {
|
||||
entry.cron.Remove(entry.Name)
|
||||
entry.cron.entries.Remove(entry.Name)
|
||||
entry.entry.Close()
|
||||
}
|
||||
|
||||
@ -96,6 +96,7 @@ func (entry *Entry) check() {
|
||||
if entry.schedule.meet(time.Now()) {
|
||||
path := entry.cron.GetLogPath()
|
||||
level := entry.cron.GetLogLevel()
|
||||
// 检查定时任务对象状态(非任务状态)
|
||||
switch entry.cron.status.Val() {
|
||||
case STATUS_STOPPED:
|
||||
return
|
||||
|
||||
@ -71,6 +71,24 @@ func TestCron_Basic(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestCron_Remove(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
cron := gcron.New()
|
||||
array := garray.New()
|
||||
cron.Add("* * * * * *", func() {
|
||||
array.Append(1)
|
||||
}, "add")
|
||||
gtest.Assert(array.Len(), 0)
|
||||
time.Sleep(1200*time.Millisecond)
|
||||
gtest.Assert(array.Len(), 1)
|
||||
|
||||
cron.Remove("add")
|
||||
gtest.Assert(array.Len(), 1)
|
||||
time.Sleep(1200*time.Millisecond)
|
||||
gtest.Assert(array.Len(), 1)
|
||||
})
|
||||
}
|
||||
|
||||
func TestCron_AddSingleton(t *testing.T) {
|
||||
// un used, can be removed
|
||||
gtest.Case(t, func() {
|
||||
|
||||
@ -3,15 +3,14 @@ package main
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
array := []uint{1, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6}
|
||||
for i := 0; i < len(array) - 1; i++ {
|
||||
for j := i + 1; j < len(array); j++ {
|
||||
if array[i] == array[j] {
|
||||
array = append(array[ : j], array[j + 1 : ]...)
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Println(array)
|
||||
array := []uint{1, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6}
|
||||
for i := 0; i < len(array)-1; i++ {
|
||||
for j := i + 1; j < len(array); j++ {
|
||||
if array[i] == array[j] {
|
||||
array = append(array[:j], array[j+1:]...)
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Println(array)
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,59 +1,58 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/garray"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/garray"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 创建普通的int类型数组,并关闭默认的并发安全特性
|
||||
a := garray.NewIntArray(true)
|
||||
|
||||
func main () {
|
||||
// 创建普通的int类型数组,并关闭默认的并发安全特性
|
||||
a := garray.NewIntArray(true)
|
||||
// 添加数据项
|
||||
for i := 0; i < 10; i++ {
|
||||
a.Append(i)
|
||||
}
|
||||
|
||||
// 添加数据项
|
||||
for i := 0; i < 10; i++ {
|
||||
a.Append(i)
|
||||
}
|
||||
// 获取当前数组长度
|
||||
fmt.Println(a.Len())
|
||||
|
||||
// 获取当前数组长度
|
||||
fmt.Println(a.Len())
|
||||
// 获取当前数据项列表
|
||||
fmt.Println(a.Slice())
|
||||
|
||||
// 获取当前数据项列表
|
||||
fmt.Println(a.Slice())
|
||||
// 获取指定索引项
|
||||
fmt.Println(a.Get(6))
|
||||
|
||||
// 获取指定索引项
|
||||
fmt.Println(a.Get(6))
|
||||
// 在指定索引前插入数据项
|
||||
a.InsertAfter(9, 11)
|
||||
// 在指定索引后插入数据项
|
||||
a.InsertBefore(10, 10)
|
||||
fmt.Println(a.Slice())
|
||||
|
||||
// 在指定索引前插入数据项
|
||||
a.InsertAfter(9, 11)
|
||||
// 在指定索引后插入数据项
|
||||
a.InsertBefore(10, 10)
|
||||
fmt.Println(a.Slice())
|
||||
// 修改指定索引的数据项
|
||||
a.Set(0, 100)
|
||||
fmt.Println(a.Slice())
|
||||
|
||||
// 修改指定索引的数据项
|
||||
a.Set(0, 100)
|
||||
fmt.Println(a.Slice())
|
||||
// 搜索数据项,返回搜索到的索引位置
|
||||
fmt.Println(a.Search(5))
|
||||
|
||||
// 搜索数据项,返回搜索到的索引位置
|
||||
fmt.Println(a.Search(5))
|
||||
// 删除指定索引的数据项
|
||||
a.Remove(0)
|
||||
fmt.Println(a.Slice())
|
||||
|
||||
// 删除指定索引的数据项
|
||||
a.Remove(0)
|
||||
fmt.Println(a.Slice())
|
||||
// 并发安全,写锁操作
|
||||
a.LockFunc(func(array []int) {
|
||||
// 将末尾项改为100
|
||||
array[len(array)-1] = 100
|
||||
})
|
||||
|
||||
// 并发安全,写锁操作
|
||||
a.LockFunc(func(array []int) {
|
||||
// 将末尾项改为100
|
||||
array[len(array) - 1] = 100
|
||||
})
|
||||
// 并发安全,读锁操作
|
||||
a.RLockFunc(func(array []int) {
|
||||
fmt.Println(array[len(array)-1])
|
||||
})
|
||||
|
||||
// 并发安全,读锁操作
|
||||
a.RLockFunc(func(array []int) {
|
||||
fmt.Println(array[len(array) - 1])
|
||||
})
|
||||
|
||||
// 清空数组
|
||||
fmt.Println(a.Slice())
|
||||
a.Clear()
|
||||
fmt.Println(a.Slice())
|
||||
// 清空数组
|
||||
fmt.Println(a.Slice())
|
||||
a.Clear()
|
||||
fmt.Println(a.Slice())
|
||||
}
|
||||
|
||||
@ -1,40 +1,39 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/garray"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/garray"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 自定义排序数组,降序排序(SortedIntArray管理的数据是升序)
|
||||
a := garray.NewSortedArray(func(v1, v2 interface{}) int {
|
||||
if v1.(int) < v2.(int) {
|
||||
return 1
|
||||
}
|
||||
if v1.(int) > v2.(int) {
|
||||
return -1
|
||||
}
|
||||
return 0
|
||||
})
|
||||
|
||||
func main () {
|
||||
// 自定义排序数组,降序排序(SortedIntArray管理的数据是升序)
|
||||
a := garray.NewSortedArray(func(v1, v2 interface{}) int {
|
||||
if v1.(int) < v2.(int) {
|
||||
return 1
|
||||
}
|
||||
if v1.(int) > v2.(int) {
|
||||
return -1
|
||||
}
|
||||
return 0
|
||||
})
|
||||
// 添加数据
|
||||
a.Add(2)
|
||||
a.Add(3)
|
||||
a.Add(1)
|
||||
fmt.Println(a.Slice())
|
||||
|
||||
// 添加数据
|
||||
a.Add(2)
|
||||
a.Add(3)
|
||||
a.Add(1)
|
||||
fmt.Println(a.Slice())
|
||||
// 添加重复数据
|
||||
a.Add(3)
|
||||
fmt.Println(a.Slice())
|
||||
|
||||
// 添加重复数据
|
||||
a.Add(3)
|
||||
fmt.Println(a.Slice())
|
||||
// 检索数据,返回最后对比的索引位置,检索结果
|
||||
// 检索结果:0: 匹配; <0:参数小于对比值; >0:参数大于对比值
|
||||
fmt.Println(a.Search(1))
|
||||
|
||||
// 检索数据,返回最后对比的索引位置,检索结果
|
||||
// 检索结果:0: 匹配; <0:参数小于对比值; >0:参数大于对比值
|
||||
fmt.Println(a.Search(1))
|
||||
|
||||
// 设置不可重复
|
||||
a.SetUnique(true)
|
||||
fmt.Println(a.Slice())
|
||||
a.Add(1)
|
||||
fmt.Println(a.Slice())
|
||||
// 设置不可重复
|
||||
a.SetUnique(true)
|
||||
fmt.Println(a.Slice())
|
||||
a.Add(1)
|
||||
fmt.Println(a.Slice())
|
||||
}
|
||||
|
||||
@ -1,18 +1,17 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/container/garray"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/container/garray"
|
||||
)
|
||||
|
||||
func main() {
|
||||
a := garray.NewIntArray()
|
||||
a.Append(1, 2, 3)
|
||||
|
||||
func main () {
|
||||
a := garray.NewIntArray()
|
||||
a.Append(1, 2, 3)
|
||||
v := a.Slice()
|
||||
v[0] = 4
|
||||
|
||||
v := a.Slice()
|
||||
v[0] = 4
|
||||
|
||||
g.Dump(a.Slice())
|
||||
g.Dump(v)
|
||||
g.Dump(a.Slice())
|
||||
g.Dump(v)
|
||||
}
|
||||
|
||||
@ -1,20 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/container/garray"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/container/garray"
|
||||
)
|
||||
|
||||
func main() {
|
||||
array := garray.NewSortedStringArray()
|
||||
array.Add("1")
|
||||
array.Add("2")
|
||||
array.Add("3")
|
||||
array.Add("4")
|
||||
array.Add("5")
|
||||
array.Add("6")
|
||||
array.Add("7")
|
||||
array.Add("8")
|
||||
array.Add("9")
|
||||
g.Dump(array.Slice())
|
||||
}
|
||||
func main() {
|
||||
array := garray.NewSortedStringArray()
|
||||
array.Add("1")
|
||||
array.Add("2")
|
||||
array.Add("3")
|
||||
array.Add("4")
|
||||
array.Add("5")
|
||||
array.Add("6")
|
||||
array.Add("7")
|
||||
array.Add("8")
|
||||
array.Add("9")
|
||||
g.Dump(array.Slice())
|
||||
}
|
||||
|
||||
@ -1,26 +1,26 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/container/garray"
|
||||
"strings"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/container/garray"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
array := garray.NewSortedStringArray()
|
||||
array.Add("/api/ctl/show")
|
||||
array.Add("/api/ctl/post")
|
||||
array.Add("/api/obj/rest")
|
||||
array.Add("/api/handler")
|
||||
array.Add("/api/obj/delete")
|
||||
array.Add("/api/obj/show")
|
||||
array.Add("/api/obj/my-show")
|
||||
array.Add("/api/*")
|
||||
array.Add("/api/ctl/rest")
|
||||
array.Add("/api/ctl/my-show")
|
||||
g.Dump(array.Slice())
|
||||
func main() {
|
||||
array := garray.NewSortedStringArray()
|
||||
array.Add("/api/ctl/show")
|
||||
array.Add("/api/ctl/post")
|
||||
array.Add("/api/obj/rest")
|
||||
array.Add("/api/handler")
|
||||
array.Add("/api/obj/delete")
|
||||
array.Add("/api/obj/show")
|
||||
array.Add("/api/obj/my-show")
|
||||
array.Add("/api/*")
|
||||
array.Add("/api/ctl/rest")
|
||||
array.Add("/api/ctl/my-show")
|
||||
g.Dump(array.Slice())
|
||||
|
||||
fmt.Println(strings.Compare("/api/ctl/post", "/api/*"))
|
||||
fmt.Println(strings.Compare("/api/*", "/api/ctl/my-show"))
|
||||
}
|
||||
fmt.Println(strings.Compare("/api/ctl/post", "/api/*"))
|
||||
fmt.Println(strings.Compare("/api/*", "/api/ctl/my-show"))
|
||||
}
|
||||
|
||||
@ -1,73 +1,73 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/gmap"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/gmap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 创建一个默认的gmap对象,
|
||||
// 默认情况下该gmap对象支持并发安全特性,
|
||||
// 初始化时可以给定false参数关闭并发安全特性,当做一个普通的map使用。
|
||||
m := gmap.New()
|
||||
// 创建一个默认的gmap对象,
|
||||
// 默认情况下该gmap对象支持并发安全特性,
|
||||
// 初始化时可以给定false参数关闭并发安全特性,当做一个普通的map使用。
|
||||
m := gmap.New()
|
||||
|
||||
// 设置键值对
|
||||
for i := 0; i < 10; i++ {
|
||||
m.Set(i, i)
|
||||
}
|
||||
// 查询大小
|
||||
fmt.Println(m.Size())
|
||||
// 批量设置键值对(不同的数据类型对象参数不同)
|
||||
m.BatchSet(map[interface{}]interface{}{
|
||||
10 : 10,
|
||||
11 : 11,
|
||||
})
|
||||
fmt.Println(m.Size())
|
||||
// 设置键值对
|
||||
for i := 0; i < 10; i++ {
|
||||
m.Set(i, i)
|
||||
}
|
||||
// 查询大小
|
||||
fmt.Println(m.Size())
|
||||
// 批量设置键值对(不同的数据类型对象参数不同)
|
||||
m.BatchSet(map[interface{}]interface{}{
|
||||
10: 10,
|
||||
11: 11,
|
||||
})
|
||||
fmt.Println(m.Size())
|
||||
|
||||
// 查询是否存在
|
||||
fmt.Println(m.Contains(1))
|
||||
// 查询是否存在
|
||||
fmt.Println(m.Contains(1))
|
||||
|
||||
// 查询键值
|
||||
fmt.Println(m.Get(1))
|
||||
// 查询键值
|
||||
fmt.Println(m.Get(1))
|
||||
|
||||
// 删除数据项
|
||||
m.Remove(9)
|
||||
fmt.Println(m.Size())
|
||||
// 删除数据项
|
||||
m.Remove(9)
|
||||
fmt.Println(m.Size())
|
||||
|
||||
// 批量删除
|
||||
m.BatchRemove([]interface{}{10, 11})
|
||||
fmt.Println(m.Size())
|
||||
// 批量删除
|
||||
m.BatchRemove([]interface{}{10, 11})
|
||||
fmt.Println(m.Size())
|
||||
|
||||
// 当前键名列表(随机排序)
|
||||
fmt.Println(m.Keys())
|
||||
// 当前键值列表(随机排序)
|
||||
fmt.Println(m.Values())
|
||||
// 当前键名列表(随机排序)
|
||||
fmt.Println(m.Keys())
|
||||
// 当前键值列表(随机排序)
|
||||
fmt.Println(m.Values())
|
||||
|
||||
// 查询键名,当键值不存在时,写入给定的默认值
|
||||
fmt.Println(m.GetWithDefault(100, 100))
|
||||
// 查询键名,当键值不存在时,写入给定的默认值
|
||||
fmt.Println(m.GetWithDefault(100, 100))
|
||||
|
||||
// 删除键值对,并返回对应的键值
|
||||
fmt.Println(m.GetAndRemove(100))
|
||||
// 删除键值对,并返回对应的键值
|
||||
fmt.Println(m.GetAndRemove(100))
|
||||
|
||||
// 遍历map
|
||||
m.Iterator(func(k interface{}, v interface{}) bool {
|
||||
fmt.Printf("%v:%v ", k, v)
|
||||
return true
|
||||
})
|
||||
// 遍历map
|
||||
m.Iterator(func(k interface{}, v interface{}) bool {
|
||||
fmt.Printf("%v:%v ", k, v)
|
||||
return true
|
||||
})
|
||||
|
||||
// 自定义写锁操作
|
||||
m.LockFunc(func(m map[interface{}]interface{}) {
|
||||
m[99] = 99
|
||||
})
|
||||
// 自定义写锁操作
|
||||
m.LockFunc(func(m map[interface{}]interface{}) {
|
||||
m[99] = 99
|
||||
})
|
||||
|
||||
// 自定义读锁操作
|
||||
m.RLockFunc(func(m map[interface{}]interface{}) {
|
||||
fmt.Println(m[99])
|
||||
})
|
||||
// 自定义读锁操作
|
||||
m.RLockFunc(func(m map[interface{}]interface{}) {
|
||||
fmt.Println(m[99])
|
||||
})
|
||||
|
||||
// 清空map
|
||||
m.Clear()
|
||||
// 清空map
|
||||
m.Clear()
|
||||
|
||||
// 判断map是否为空
|
||||
fmt.Println(m.IsEmpty())
|
||||
// 判断map是否为空
|
||||
fmt.Println(m.IsEmpty())
|
||||
}
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/container/gmap"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/container/gmap"
|
||||
)
|
||||
|
||||
func main() {
|
||||
m := gmap.New()
|
||||
m.Set("1", "1")
|
||||
m := gmap.New()
|
||||
m.Set("1", "1")
|
||||
|
||||
m1 := m.Clone()
|
||||
m1["2"] = "2"
|
||||
m1 := m.Clone()
|
||||
m1["2"] = "2"
|
||||
|
||||
g.Dump(m.Clone())
|
||||
g.Dump(m1)
|
||||
g.Dump(m.Clone())
|
||||
g.Dump(m1)
|
||||
}
|
||||
|
||||
@ -1,39 +1,39 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
"fmt"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 验证 map 的delete方法是否并发安全
|
||||
func main() {
|
||||
// 创建一个初始化的map
|
||||
m := make(map[int]int)
|
||||
for i := 0; i < 10000; i++ {
|
||||
m[i] = i
|
||||
}
|
||||
// 创建一个初始化的map
|
||||
m := make(map[int]int)
|
||||
for i := 0; i < 10000; i++ {
|
||||
m[i] = i
|
||||
}
|
||||
|
||||
fmt.Println("map size:", len(m))
|
||||
fmt.Println("map size:", len(m))
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
ev := make(chan struct{}, 0)
|
||||
wg := sync.WaitGroup{}
|
||||
ev := make(chan struct{}, 0)
|
||||
|
||||
// 创建10个并发的goroutine,使用ev控制并发开始事件,更容易模拟data race
|
||||
for i := 0; i < 10; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
<- ev
|
||||
fmt.Println("start")
|
||||
for i := 0; i < 10000; i++ {
|
||||
delete(m, i)
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
// 创建10个并发的goroutine,使用ev控制并发开始事件,更容易模拟data race
|
||||
for i := 0; i < 10; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
<-ev
|
||||
fmt.Println("start")
|
||||
for i := 0; i < 10000; i++ {
|
||||
delete(m, i)
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
time.Sleep(time.Second)
|
||||
time.Sleep(time.Second)
|
||||
|
||||
close(ev)
|
||||
wg.Wait()
|
||||
close(ev)
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
@ -1,25 +1,25 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/container/gpool"
|
||||
"fmt"
|
||||
"time"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/gpool"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main () {
|
||||
// 创建一个对象池,过期时间为1000毫秒
|
||||
p := gpool.New(1000, nil)
|
||||
func main() {
|
||||
// 创建一个对象池,过期时间为1000毫秒
|
||||
p := gpool.New(1000, nil)
|
||||
|
||||
// 从池中取一个对象,返回nil及错误信息
|
||||
fmt.Println(p.Get())
|
||||
// 从池中取一个对象,返回nil及错误信息
|
||||
fmt.Println(p.Get())
|
||||
|
||||
// 丢一个对象到池中
|
||||
p.Put(1)
|
||||
// 丢一个对象到池中
|
||||
p.Put(1)
|
||||
|
||||
// 重新从池中取一个对象,返回1
|
||||
fmt.Println(p.Get())
|
||||
// 重新从池中取一个对象,返回1
|
||||
fmt.Println(p.Get())
|
||||
|
||||
// 等待1秒后重试,发现对象已过期,返回nil及错误信息
|
||||
time.Sleep(time.Second)
|
||||
fmt.Println(p.Get())
|
||||
// 等待1秒后重试,发现对象已过期,返回nil及错误信息
|
||||
time.Sleep(time.Second)
|
||||
fmt.Println(p.Get())
|
||||
}
|
||||
|
||||
@ -1,33 +1,33 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/os/gtimer"
|
||||
"time"
|
||||
"github.com/gogf/gf/g/os/gtime"
|
||||
"github.com/gogf/gf/g/container/gqueue"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/gqueue"
|
||||
"github.com/gogf/gf/g/os/gtime"
|
||||
"github.com/gogf/gf/g/os/gtimer"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
q := gqueue.New()
|
||||
// 数据生产者,每隔1秒往队列写数据
|
||||
gtimer.SetInterval(time.Second, func() {
|
||||
v := gtime.Now().String()
|
||||
q.Push(v)
|
||||
fmt.Println("Push:", v)
|
||||
})
|
||||
q := gqueue.New()
|
||||
// 数据生产者,每隔1秒往队列写数据
|
||||
gtimer.SetInterval(time.Second, func() {
|
||||
v := gtime.Now().String()
|
||||
q.Push(v)
|
||||
fmt.Println("Push:", v)
|
||||
})
|
||||
|
||||
// 3秒后关闭队列
|
||||
gtimer.SetTimeout(3*time.Second, func() {
|
||||
q.Close()
|
||||
})
|
||||
// 3秒后关闭队列
|
||||
gtimer.SetTimeout(3*time.Second, func() {
|
||||
q.Close()
|
||||
})
|
||||
|
||||
// 消费者,不停读取队列数据并输出到终端
|
||||
for {
|
||||
if v := q.Pop(); v != nil {
|
||||
fmt.Println(" Pop:", v)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
// 消费者,不停读取队列数据并输出到终端
|
||||
for {
|
||||
if v := q.Pop(); v != nil {
|
||||
fmt.Println(" Pop:", v)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,27 +1,27 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/gqueue"
|
||||
"github.com/gogf/gf/g/os/gtimer"
|
||||
"time"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/gqueue"
|
||||
"github.com/gogf/gf/g/os/gtimer"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
q := gqueue.New()
|
||||
// 数据生产者,每隔1秒往队列写数据
|
||||
gtimer.SetInterval(time.Second, func() {
|
||||
for i := 0; i < 10; i++ {
|
||||
q.Push(i)
|
||||
}
|
||||
})
|
||||
q := gqueue.New()
|
||||
// 数据生产者,每隔1秒往队列写数据
|
||||
gtimer.SetInterval(time.Second, func() {
|
||||
for i := 0; i < 10; i++ {
|
||||
q.Push(i)
|
||||
}
|
||||
})
|
||||
|
||||
// 消费者,不停读取队列数据并输出到终端
|
||||
for {
|
||||
if v := q.Pop(); v != nil {
|
||||
fmt.Println(" Pop:", v)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
// 消费者,不停读取队列数据并输出到终端
|
||||
for {
|
||||
if v := q.Pop(); v != nil {
|
||||
fmt.Println(" Pop:", v)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,29 +1,29 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/gqueue"
|
||||
"github.com/gogf/gf/g/os/gtime"
|
||||
"github.com/gogf/gf/g/os/gtimer"
|
||||
"time"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/gqueue"
|
||||
"github.com/gogf/gf/g/os/gtime"
|
||||
"github.com/gogf/gf/g/os/gtimer"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
queue := gqueue.New()
|
||||
// 数据生产者,每隔1秒往队列写数据
|
||||
gtimer.SetInterval(time.Second, func() {
|
||||
queue.Push(gtime.Now().String())
|
||||
})
|
||||
queue := gqueue.New()
|
||||
// 数据生产者,每隔1秒往队列写数据
|
||||
gtimer.SetInterval(time.Second, func() {
|
||||
queue.Push(gtime.Now().String())
|
||||
})
|
||||
|
||||
// 消费者,不停读取队列数据并输出到终端
|
||||
for {
|
||||
select {
|
||||
case v := <-queue.C:
|
||||
if v != nil {
|
||||
fmt.Println(v)
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
// 消费者,不停读取队列数据并输出到终端
|
||||
for {
|
||||
select {
|
||||
case v := <-queue.C:
|
||||
if v != nil {
|
||||
fmt.Println(v)
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,27 +1,27 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/container/gring"
|
||||
"fmt"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/gring"
|
||||
)
|
||||
|
||||
func main() {
|
||||
r1 := gring.New(10)
|
||||
for i := 0; i < 5; i ++ {
|
||||
r1.Set(i).Next()
|
||||
}
|
||||
fmt.Println("Len:", r1.Len())
|
||||
fmt.Println("Cap:", r1.Cap())
|
||||
fmt.Println(r1.SlicePrev())
|
||||
fmt.Println(r1.SliceNext())
|
||||
r1 := gring.New(10)
|
||||
for i := 0; i < 5; i++ {
|
||||
r1.Set(i).Next()
|
||||
}
|
||||
fmt.Println("Len:", r1.Len())
|
||||
fmt.Println("Cap:", r1.Cap())
|
||||
fmt.Println(r1.SlicePrev())
|
||||
fmt.Println(r1.SliceNext())
|
||||
|
||||
r2 := gring.New(10)
|
||||
for i := 0; i < 10; i ++ {
|
||||
r2.Set(i).Next()
|
||||
}
|
||||
fmt.Println("Len:", r2.Len())
|
||||
fmt.Println("Cap:", r2.Cap())
|
||||
fmt.Println(r2.SlicePrev())
|
||||
fmt.Println(r2.SliceNext())
|
||||
r2 := gring.New(10)
|
||||
for i := 0; i < 10; i++ {
|
||||
r2.Set(i).Next()
|
||||
}
|
||||
fmt.Println("Len:", r2.Len())
|
||||
fmt.Println("Cap:", r2.Cap())
|
||||
fmt.Println(r2.SlicePrev())
|
||||
fmt.Println(r2.SliceNext())
|
||||
|
||||
}
|
||||
|
||||
@ -1,57 +1,57 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/gring"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/gring"
|
||||
)
|
||||
|
||||
type Player struct {
|
||||
position int // 位置
|
||||
alive bool // 是否存活
|
||||
position int // 位置
|
||||
alive bool // 是否存活
|
||||
}
|
||||
|
||||
const (
|
||||
playerCount = 41 // 玩家人数
|
||||
startPos = 1 // 开始报数位置
|
||||
playerCount = 41 // 玩家人数
|
||||
startPos = 1 // 开始报数位置
|
||||
)
|
||||
|
||||
var (
|
||||
deadline = 3
|
||||
deadline = 3
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 关闭并发安全,当前场景没有必要
|
||||
r := gring.New(playerCount, false)
|
||||
// 关闭并发安全,当前场景没有必要
|
||||
r := gring.New(playerCount, false)
|
||||
|
||||
// 设置所有玩家初始值
|
||||
for i := 1; i <= playerCount; i++ {
|
||||
r.Put(&Player{i, true})
|
||||
}
|
||||
// 设置所有玩家初始值
|
||||
for i := 1; i <= playerCount; i++ {
|
||||
r.Put(&Player{i, true})
|
||||
}
|
||||
|
||||
// 如果开始报数的位置不为1,则设置开始位置
|
||||
if startPos > 1 {
|
||||
r.Move(startPos - 1)
|
||||
}
|
||||
// 如果开始报数的位置不为1,则设置开始位置
|
||||
if startPos > 1 {
|
||||
r.Move(startPos - 1)
|
||||
}
|
||||
|
||||
counter := 1 // 报数从1开始,因为下面的循环从第二个开始计算
|
||||
deadCount := 0 // 死亡人数,初始值为0
|
||||
counter := 1 // 报数从1开始,因为下面的循环从第二个开始计算
|
||||
deadCount := 0 // 死亡人数,初始值为0
|
||||
|
||||
// 直到所有人都死亡,否则循环一直执行
|
||||
for deadCount < playerCount {
|
||||
// 跳到下一个人
|
||||
r.Next()
|
||||
// 直到所有人都死亡,否则循环一直执行
|
||||
for deadCount < playerCount {
|
||||
// 跳到下一个人
|
||||
r.Next()
|
||||
|
||||
// 如果是活着的人,则报数
|
||||
if r.Val().(*Player).alive {
|
||||
counter++
|
||||
}
|
||||
// 如果是活着的人,则报数
|
||||
if r.Val().(*Player).alive {
|
||||
counter++
|
||||
}
|
||||
|
||||
// 如果报数为deadline,则此人淘汰出局
|
||||
if counter == deadline {
|
||||
r.Val().(*Player).alive = false
|
||||
fmt.Printf("Player %d died!\n", r.Val().(*Player).position)
|
||||
deadCount++
|
||||
counter = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
// 如果报数为deadline,则此人淘汰出局
|
||||
if counter == deadline {
|
||||
r.Val().(*Player).alive = false
|
||||
fmt.Printf("Player %d died!\n", r.Val().(*Player).position)
|
||||
deadCount++
|
||||
counter = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,52 +1,52 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/container/gset"
|
||||
"fmt"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/gset"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 创建一个非并发安全的集合对象
|
||||
s := gset.New(false)
|
||||
// 创建一个非并发安全的集合对象
|
||||
s := gset.New(false)
|
||||
|
||||
// 添加数据项
|
||||
s.Add(1)
|
||||
// 添加数据项
|
||||
s.Add(1)
|
||||
|
||||
// 批量添加数据项
|
||||
s.BatchAdd([]interface{}{1, 2, 3})
|
||||
// 批量添加数据项
|
||||
s.BatchAdd([]interface{}{1, 2, 3})
|
||||
|
||||
// 集合数据项大小
|
||||
fmt.Println(s.Size())
|
||||
// 集合数据项大小
|
||||
fmt.Println(s.Size())
|
||||
|
||||
// 集合中是否存在指定数据项
|
||||
fmt.Println(s.Contains(2))
|
||||
// 集合中是否存在指定数据项
|
||||
fmt.Println(s.Contains(2))
|
||||
|
||||
// 返回数据项slice
|
||||
fmt.Println(s.Slice())
|
||||
// 返回数据项slice
|
||||
fmt.Println(s.Slice())
|
||||
|
||||
// 删除数据项
|
||||
s.Remove(3)
|
||||
// 删除数据项
|
||||
s.Remove(3)
|
||||
|
||||
// 遍历数据项
|
||||
s.Iterator(func(v interface{}) bool {
|
||||
fmt.Println("Iterator:", v)
|
||||
return true
|
||||
})
|
||||
// 遍历数据项
|
||||
s.Iterator(func(v interface{}) bool {
|
||||
fmt.Println("Iterator:", v)
|
||||
return true
|
||||
})
|
||||
|
||||
// 将集合转换为字符串
|
||||
fmt.Println(s.String())
|
||||
// 将集合转换为字符串
|
||||
fmt.Println(s.String())
|
||||
|
||||
// 并发安全写锁操作
|
||||
s.LockFunc(func(m map[interface{}]struct{}) {
|
||||
m[4] = struct{}{}
|
||||
})
|
||||
// 并发安全写锁操作
|
||||
s.LockFunc(func(m map[interface{}]struct{}) {
|
||||
m[4] = struct{}{}
|
||||
})
|
||||
|
||||
// 并发安全读锁操作
|
||||
s.RLockFunc(func(m map[interface{}]struct{}) {
|
||||
fmt.Println(m)
|
||||
})
|
||||
// 并发安全读锁操作
|
||||
s.RLockFunc(func(m map[interface{}]struct{}) {
|
||||
fmt.Println(m)
|
||||
})
|
||||
|
||||
// 清空集合
|
||||
s.Clear()
|
||||
fmt.Println(s.Size())
|
||||
// 清空集合
|
||||
s.Clear()
|
||||
fmt.Println(s.Size())
|
||||
}
|
||||
|
||||
@ -1,20 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/container/gtype"
|
||||
"fmt"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/container/gtype"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 创建一个Int型的并发安全基本类型对象
|
||||
i := gtype.NewInt()
|
||||
// 创建一个Int型的并发安全基本类型对象
|
||||
i := gtype.NewInt()
|
||||
|
||||
// 设置值
|
||||
i.Set(10)
|
||||
// 设置值
|
||||
i.Set(10)
|
||||
|
||||
// 获取值
|
||||
fmt.Println(i.Val())
|
||||
// 获取值
|
||||
fmt.Println(i.Val())
|
||||
|
||||
// (整型/浮点型有效)数值 增加/删除 delta
|
||||
fmt.Println(i.Add(-1))
|
||||
// (整型/浮点型有效)数值 增加/删除 delta
|
||||
fmt.Println(i.Add(-1))
|
||||
}
|
||||
|
||||
@ -1,36 +1,36 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g"
|
||||
"fmt"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var v g.Var
|
||||
var v g.Var
|
||||
|
||||
v.Set("123")
|
||||
v.Set("123")
|
||||
|
||||
fmt.Println(v.Val())
|
||||
fmt.Println(v.Val())
|
||||
|
||||
// 基本类型转换
|
||||
fmt.Println(v.Int())
|
||||
fmt.Println(v.Uint())
|
||||
fmt.Println(v.Float64())
|
||||
// 基本类型转换
|
||||
fmt.Println(v.Int())
|
||||
fmt.Println(v.Uint())
|
||||
fmt.Println(v.Float64())
|
||||
|
||||
// slice转换
|
||||
fmt.Println(v.Ints())
|
||||
fmt.Println(v.Floats())
|
||||
fmt.Println(v.Strings())
|
||||
// slice转换
|
||||
fmt.Println(v.Ints())
|
||||
fmt.Println(v.Floats())
|
||||
fmt.Println(v.Strings())
|
||||
|
||||
// struct转换
|
||||
type Score struct {
|
||||
Value int
|
||||
}
|
||||
s := new(Score)
|
||||
v.Struct(s)
|
||||
fmt.Println(s)
|
||||
// struct转换
|
||||
type Score struct {
|
||||
Value int
|
||||
}
|
||||
s := new(Score)
|
||||
v.Struct(s)
|
||||
fmt.Println(s)
|
||||
|
||||
// 只读接口
|
||||
r := v.ReadOnly()
|
||||
fmt.Println(r.String())
|
||||
// 只读接口
|
||||
r := v.ReadOnly()
|
||||
fmt.Println(r.String())
|
||||
}
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"github.com/gogf/gf/g/database/gdb"
|
||||
"github.com/gogf/gf/g"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/database/gdb"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 本文件用于gf框架的mysql数据库操作示例,不作为单元测试使用
|
||||
@ -12,90 +12,88 @@ import (
|
||||
var db gdb.DB
|
||||
|
||||
// 初始化配置及创建数据库
|
||||
func init () {
|
||||
gdb.AddDefaultConfigNode(gdb.ConfigNode {
|
||||
Host : "127.0.0.1",
|
||||
Port : "3306",
|
||||
User : "root",
|
||||
Pass : "12345678",
|
||||
Name : "test",
|
||||
Type : "mysql",
|
||||
Role : "master",
|
||||
Charset : "utf8",
|
||||
})
|
||||
db, _ = gdb.New()
|
||||
func init() {
|
||||
gdb.AddDefaultConfigNode(gdb.ConfigNode{
|
||||
Host: "127.0.0.1",
|
||||
Port: "3306",
|
||||
User: "root",
|
||||
Pass: "12345678",
|
||||
Name: "test",
|
||||
Type: "mysql",
|
||||
Role: "master",
|
||||
Charset: "utf8",
|
||||
})
|
||||
db, _ = gdb.New()
|
||||
|
||||
//gins.Config().SetPath("/home/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/geg/frame")
|
||||
//db = g.Database()
|
||||
//gins.Config().SetPath("/home/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/geg/frame")
|
||||
//db = g.Database()
|
||||
|
||||
//gdb.SetConfig(gdb.ConfigNode {
|
||||
// Host : "127.0.0.1",
|
||||
// Port : 3306,
|
||||
// User : "root",
|
||||
// Pass : "123456",
|
||||
// Name : "test",
|
||||
// Type : "mysql",
|
||||
//})
|
||||
//db, _ = gdb.Instance()
|
||||
//gdb.SetConfig(gdb.ConfigNode {
|
||||
// Host : "127.0.0.1",
|
||||
// Port : 3306,
|
||||
// User : "root",
|
||||
// Pass : "123456",
|
||||
// Name : "test",
|
||||
// Type : "mysql",
|
||||
//})
|
||||
//db, _ = gdb.Instance()
|
||||
|
||||
//gdb.SetConfig(gdb.Config {
|
||||
// "default" : gdb.ConfigGroup {
|
||||
// gdb.ConfigNode {
|
||||
// Host : "127.0.0.1",
|
||||
// Port : "3306",
|
||||
// User : "root",
|
||||
// Pass : "123456",
|
||||
// Name : "test",
|
||||
// Type : "mysql",
|
||||
// Role : "master",
|
||||
// Priority : 100,
|
||||
// },
|
||||
// gdb.ConfigNode {
|
||||
// Host : "127.0.0.2",
|
||||
// Port : "3306",
|
||||
// User : "root",
|
||||
// Pass : "123456",
|
||||
// Name : "test",
|
||||
// Type : "mysql",
|
||||
// Role : "master",
|
||||
// Priority : 100,
|
||||
// },
|
||||
// gdb.ConfigNode {
|
||||
// Host : "127.0.0.3",
|
||||
// Port : "3306",
|
||||
// User : "root",
|
||||
// Pass : "123456",
|
||||
// Name : "test",
|
||||
// Type : "mysql",
|
||||
// Role : "master",
|
||||
// Priority : 100,
|
||||
// },
|
||||
// gdb.ConfigNode {
|
||||
// Host : "127.0.0.4",
|
||||
// Port : "3306",
|
||||
// User : "root",
|
||||
// Pass : "123456",
|
||||
// Name : "test",
|
||||
// Type : "mysql",
|
||||
// Role : "master",
|
||||
// Priority : 100,
|
||||
// },
|
||||
// },
|
||||
//})
|
||||
//db, _ = gdb.Instance()
|
||||
//gdb.SetConfig(gdb.Config {
|
||||
// "default" : gdb.ConfigGroup {
|
||||
// gdb.ConfigNode {
|
||||
// Host : "127.0.0.1",
|
||||
// Port : "3306",
|
||||
// User : "root",
|
||||
// Pass : "123456",
|
||||
// Name : "test",
|
||||
// Type : "mysql",
|
||||
// Role : "master",
|
||||
// Priority : 100,
|
||||
// },
|
||||
// gdb.ConfigNode {
|
||||
// Host : "127.0.0.2",
|
||||
// Port : "3306",
|
||||
// User : "root",
|
||||
// Pass : "123456",
|
||||
// Name : "test",
|
||||
// Type : "mysql",
|
||||
// Role : "master",
|
||||
// Priority : 100,
|
||||
// },
|
||||
// gdb.ConfigNode {
|
||||
// Host : "127.0.0.3",
|
||||
// Port : "3306",
|
||||
// User : "root",
|
||||
// Pass : "123456",
|
||||
// Name : "test",
|
||||
// Type : "mysql",
|
||||
// Role : "master",
|
||||
// Priority : 100,
|
||||
// },
|
||||
// gdb.ConfigNode {
|
||||
// Host : "127.0.0.4",
|
||||
// Port : "3306",
|
||||
// User : "root",
|
||||
// Pass : "123456",
|
||||
// Name : "test",
|
||||
// Type : "mysql",
|
||||
// Role : "master",
|
||||
// Priority : 100,
|
||||
// },
|
||||
// },
|
||||
//})
|
||||
//db, _ = gdb.Instance()
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 创建测试数据库
|
||||
func create() {
|
||||
fmt.Println("create:")
|
||||
_, err := db.Exec("CREATE DATABASE IF NOT EXISTS test")
|
||||
if (err != nil) {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println("create:")
|
||||
_, err := db.Exec("CREATE DATABASE IF NOT EXISTS test")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
s := `
|
||||
s := `
|
||||
CREATE TABLE IF NOT EXISTS user (
|
||||
uid INT(10) UNSIGNED AUTO_INCREMENT,
|
||||
name VARCHAR(45),
|
||||
@ -104,12 +102,12 @@ func create() {
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = utf8
|
||||
`
|
||||
_, err = db.Exec(s)
|
||||
if (err != nil) {
|
||||
fmt.Println(err)
|
||||
}
|
||||
_, err = db.Exec(s)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
s = `
|
||||
s = `
|
||||
CREATE TABLE IF NOT EXISTS user_detail (
|
||||
uid INT(10) UNSIGNED AUTO_INCREMENT,
|
||||
site VARCHAR(255),
|
||||
@ -119,419 +117,416 @@ func create() {
|
||||
DEFAULT CHARACTER SET = utf8
|
||||
`
|
||||
|
||||
_, err = db.Exec(s)
|
||||
if (err != nil) {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
_, err = db.Exec(s)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// 数据写入
|
||||
func insert() {
|
||||
fmt.Println("insert:")
|
||||
r, err := db.Insert("user", gdb.Map {
|
||||
"name": "john",
|
||||
})
|
||||
if err == nil {
|
||||
uid, err2 := r.LastInsertId()
|
||||
if err2 == nil {
|
||||
r, err = db.Insert("user_detail", gdb.Map {
|
||||
"uid" : uid,
|
||||
"site" : "http://johng.cn",
|
||||
})
|
||||
if err == nil {
|
||||
fmt.Printf("uid: %d\n", uid)
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
} else {
|
||||
fmt.Println(err2)
|
||||
}
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Println("insert:")
|
||||
r, err := db.Insert("user", gdb.Map{
|
||||
"name": "john",
|
||||
})
|
||||
if err == nil {
|
||||
uid, err2 := r.LastInsertId()
|
||||
if err2 == nil {
|
||||
r, err = db.Insert("user_detail", gdb.Map{
|
||||
"uid": uid,
|
||||
"site": "http://johng.cn",
|
||||
})
|
||||
if err == nil {
|
||||
fmt.Printf("uid: %d\n", uid)
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
} else {
|
||||
fmt.Println(err2)
|
||||
}
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
|
||||
// 基本sql查询
|
||||
func query() {
|
||||
fmt.Println("query:")
|
||||
list, err := db.GetAll("select * from user limit 2")
|
||||
if err == nil {
|
||||
fmt.Println(list)
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Println("query:")
|
||||
list, err := db.GetAll("select * from user limit 2")
|
||||
if err == nil {
|
||||
fmt.Println(list)
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// replace into
|
||||
func replace() {
|
||||
fmt.Println("replace:")
|
||||
r, err := db.Save("user", gdb.Map {
|
||||
"uid" : 1,
|
||||
"name" : "john",
|
||||
})
|
||||
if err == nil {
|
||||
fmt.Println(r.LastInsertId())
|
||||
fmt.Println(r.RowsAffected())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Println("replace:")
|
||||
r, err := db.Save("user", gdb.Map{
|
||||
"uid": 1,
|
||||
"name": "john",
|
||||
})
|
||||
if err == nil {
|
||||
fmt.Println(r.LastInsertId())
|
||||
fmt.Println(r.RowsAffected())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// 数据保存
|
||||
func save() {
|
||||
fmt.Println("save:")
|
||||
r, err := db.Save("user", gdb.Map {
|
||||
"uid" : 1,
|
||||
"name" : "john",
|
||||
})
|
||||
if err == nil {
|
||||
fmt.Println(r.LastInsertId())
|
||||
fmt.Println(r.RowsAffected())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Println("save:")
|
||||
r, err := db.Save("user", gdb.Map{
|
||||
"uid": 1,
|
||||
"name": "john",
|
||||
})
|
||||
if err == nil {
|
||||
fmt.Println(r.LastInsertId())
|
||||
fmt.Println(r.RowsAffected())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// 批量写入
|
||||
func batchInsert() {
|
||||
fmt.Println("batchInsert:")
|
||||
_, err := db.BatchInsert("user", gdb.List {
|
||||
{"name": "john_1"},
|
||||
{"name": "john_2"},
|
||||
{"name": "john_3"},
|
||||
{"name": "john_4"},
|
||||
}, 10)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Println("batchInsert:")
|
||||
_, err := db.BatchInsert("user", gdb.List{
|
||||
{"name": "john_1"},
|
||||
{"name": "john_2"},
|
||||
{"name": "john_3"},
|
||||
{"name": "john_4"},
|
||||
}, 10)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// 数据更新
|
||||
func update1() {
|
||||
fmt.Println("update1:")
|
||||
r, err := db.Update("user", gdb.Map {"name": "john1"}, "uid=?", 1)
|
||||
if err == nil {
|
||||
fmt.Println(r.LastInsertId())
|
||||
fmt.Println(r.RowsAffected())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Println("update1:")
|
||||
r, err := db.Update("user", gdb.Map{"name": "john1"}, "uid=?", 1)
|
||||
if err == nil {
|
||||
fmt.Println(r.LastInsertId())
|
||||
fmt.Println(r.RowsAffected())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// 数据更新
|
||||
func update2() {
|
||||
fmt.Println("update2:")
|
||||
r, err := db.Update("user", gdb.Map{"name" : "john6"}, "uid=?", 1)
|
||||
if err == nil {
|
||||
fmt.Println(r.LastInsertId())
|
||||
fmt.Println(r.RowsAffected())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Println("update2:")
|
||||
r, err := db.Update("user", gdb.Map{"name": "john6"}, "uid=?", 1)
|
||||
if err == nil {
|
||||
fmt.Println(r.LastInsertId())
|
||||
fmt.Println(r.RowsAffected())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// 数据更新
|
||||
func update3() {
|
||||
fmt.Println("update3:")
|
||||
r, err := db.Update("user", "name=?", "uid=?", "john2", 1)
|
||||
if err == nil {
|
||||
fmt.Println(r.LastInsertId())
|
||||
fmt.Println(r.RowsAffected())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Println("update3:")
|
||||
r, err := db.Update("user", "name=?", "uid=?", "john2", 1)
|
||||
if err == nil {
|
||||
fmt.Println(r.LastInsertId())
|
||||
fmt.Println(r.RowsAffected())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// 链式查询操作1
|
||||
func linkopSelect1() {
|
||||
fmt.Println("linkopSelect1:")
|
||||
r, err := db.Table("user u").LeftJoin("user_detail ud", "u.uid=ud.uid").Fields("u.*, ud.site").Where("u.uid > ?", 1).Limit(0, 2).Select()
|
||||
if err == nil {
|
||||
fmt.Println(r)
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Println("linkopSelect1:")
|
||||
r, err := db.Table("user u").LeftJoin("user_detail ud", "u.uid=ud.uid").Fields("u.*, ud.site").Where("u.uid > ?", 1).Limit(0, 2).Select()
|
||||
if err == nil {
|
||||
fmt.Println(r)
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// 链式查询操作2
|
||||
func linkopSelect2() {
|
||||
fmt.Println("linkopSelect2:")
|
||||
r, err := db.Table("user u").LeftJoin("user_detail ud", "u.uid=ud.uid").Fields("u.*,ud.site").Where("u.uid=?", 1).One()
|
||||
if err == nil {
|
||||
fmt.Println(r)
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Println("linkopSelect2:")
|
||||
r, err := db.Table("user u").LeftJoin("user_detail ud", "u.uid=ud.uid").Fields("u.*,ud.site").Where("u.uid=?", 1).One()
|
||||
if err == nil {
|
||||
fmt.Println(r)
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// 链式查询操作3
|
||||
func linkopSelect3() {
|
||||
fmt.Println("linkopSelect3:")
|
||||
r, err := db.Table("user u").LeftJoin("user_detail ud", "u.uid=ud.uid").Fields("ud.site").Where("u.uid=?", 1).Value()
|
||||
if err == nil {
|
||||
fmt.Println(r.String())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Println("linkopSelect3:")
|
||||
r, err := db.Table("user u").LeftJoin("user_detail ud", "u.uid=ud.uid").Fields("ud.site").Where("u.uid=?", 1).Value()
|
||||
if err == nil {
|
||||
fmt.Println(r.String())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// 链式查询数量1
|
||||
func linkopCount1() {
|
||||
fmt.Println("linkopCount1:")
|
||||
r, err := db.Table("user u").Fields("uid").LeftJoin("user_detail ud", "u.uid=ud.uid").Where("u.uid=?", 1).Count()
|
||||
if err == nil {
|
||||
fmt.Println(r)
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Println("linkopCount1:")
|
||||
r, err := db.Table("user u").Fields("uid").LeftJoin("user_detail ud", "u.uid=ud.uid").Where("u.uid=?", 1).Count()
|
||||
if err == nil {
|
||||
fmt.Println(r)
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
|
||||
// 错误操作
|
||||
func linkopUpdate1() {
|
||||
fmt.Println("linkopUpdate1:")
|
||||
r, err := db.Table("henghe_setting").Update()
|
||||
if err == nil {
|
||||
fmt.Println(r.RowsAffected())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Println("linkopUpdate1:")
|
||||
r, err := db.Table("henghe_setting").Update()
|
||||
if err == nil {
|
||||
fmt.Println(r.RowsAffected())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// 通过Map指针方式传参方式
|
||||
func linkopUpdate2() {
|
||||
fmt.Println("linkopUpdate2:")
|
||||
r, err := db.Table("user").Data(gdb.Map{"name" : "john2"}).Where("name=?", "john_1").Update()
|
||||
if err == nil {
|
||||
fmt.Println(r.RowsAffected())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Println("linkopUpdate2:")
|
||||
r, err := db.Table("user").Data(gdb.Map{"name": "john2"}).Where("name=?", "john_1").Update()
|
||||
if err == nil {
|
||||
fmt.Println(r.RowsAffected())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// 通过字符串方式传参
|
||||
func linkopUpdate3() {
|
||||
fmt.Println("linkopUpdate3:")
|
||||
r, err := db.Table("user").Data("name='john3'").Where("name=?", "john2").Update()
|
||||
if err == nil {
|
||||
fmt.Println(r.RowsAffected())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Println("linkopUpdate3:")
|
||||
r, err := db.Table("user").Data("name='john3'").Where("name=?", "john2").Update()
|
||||
if err == nil {
|
||||
fmt.Println(r.RowsAffected())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// Where条件使用Map
|
||||
func linkopUpdate4() {
|
||||
fmt.Println("linkopUpdate4:")
|
||||
r, err := db.Table("user").Data(gdb.Map{"name" : "john11111"}).Where(g.Map{"uid" : 1}).Update()
|
||||
if err == nil {
|
||||
fmt.Println(r.RowsAffected())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Println("linkopUpdate4:")
|
||||
r, err := db.Table("user").Data(gdb.Map{"name": "john11111"}).Where(g.Map{"uid": 1}).Update()
|
||||
if err == nil {
|
||||
fmt.Println(r.RowsAffected())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// 链式批量写入
|
||||
func linkopBatchInsert1() {
|
||||
fmt.Println("linkopBatchInsert1:")
|
||||
r, err := db.Table("user").Data(gdb.List{
|
||||
{"name": "john_1"},
|
||||
{"name": "john_2"},
|
||||
{"name": "john_3"},
|
||||
{"name": "john_4"},
|
||||
}).Insert()
|
||||
if err == nil {
|
||||
fmt.Println(r.RowsAffected())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Println("linkopBatchInsert1:")
|
||||
r, err := db.Table("user").Data(gdb.List{
|
||||
{"name": "john_1"},
|
||||
{"name": "john_2"},
|
||||
{"name": "john_3"},
|
||||
{"name": "john_4"},
|
||||
}).Insert()
|
||||
if err == nil {
|
||||
fmt.Println(r.RowsAffected())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// 链式批量写入,指定每批次写入的条数
|
||||
func linkopBatchInsert2() {
|
||||
fmt.Println("linkopBatchInsert2:")
|
||||
r, err := db.Table("user").Data(gdb.List{
|
||||
{"name": "john_1"},
|
||||
{"name": "john_2"},
|
||||
{"name": "john_3"},
|
||||
{"name": "john_4"},
|
||||
}).Batch(2).Insert()
|
||||
if err == nil {
|
||||
fmt.Println(r.RowsAffected())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Println("linkopBatchInsert2:")
|
||||
r, err := db.Table("user").Data(gdb.List{
|
||||
{"name": "john_1"},
|
||||
{"name": "john_2"},
|
||||
{"name": "john_3"},
|
||||
{"name": "john_4"},
|
||||
}).Batch(2).Insert()
|
||||
if err == nil {
|
||||
fmt.Println(r.RowsAffected())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// 链式批量保存
|
||||
func linkopBatchSave() {
|
||||
fmt.Println("linkopBatchSave:")
|
||||
r, err := db.Table("user").Data(gdb.List{
|
||||
{"uid":1, "name": "john_1"},
|
||||
{"uid":2, "name": "john_2"},
|
||||
{"uid":3, "name": "john_3"},
|
||||
{"uid":4, "name": "john_4"},
|
||||
}).Save()
|
||||
if err == nil {
|
||||
fmt.Println(r.RowsAffected())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Println("linkopBatchSave:")
|
||||
r, err := db.Table("user").Data(gdb.List{
|
||||
{"uid": 1, "name": "john_1"},
|
||||
{"uid": 2, "name": "john_2"},
|
||||
{"uid": 3, "name": "john_3"},
|
||||
{"uid": 4, "name": "john_4"},
|
||||
}).Save()
|
||||
if err == nil {
|
||||
fmt.Println(r.RowsAffected())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// 事务操作示例1
|
||||
func transaction1() {
|
||||
fmt.Println("transaction1:")
|
||||
if tx, err := db.Begin(); err == nil {
|
||||
r, err := tx.Save("user", gdb.Map{
|
||||
"uid" : 1,
|
||||
"name" : "john",
|
||||
})
|
||||
tx.Rollback()
|
||||
fmt.Println(r, err)
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Println("transaction1:")
|
||||
if tx, err := db.Begin(); err == nil {
|
||||
r, err := tx.Save("user", gdb.Map{
|
||||
"uid": 1,
|
||||
"name": "john",
|
||||
})
|
||||
tx.Rollback()
|
||||
fmt.Println(r, err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// 事务操作示例2
|
||||
func transaction2() {
|
||||
fmt.Println("transaction2:")
|
||||
if tx, err := db.Begin(); err == nil {
|
||||
r, err := tx.Table("user").Data(gdb.Map{"uid":1, "name": "john_1"}).Save()
|
||||
tx.Commit()
|
||||
fmt.Println(r, err)
|
||||
}
|
||||
fmt.Println()
|
||||
fmt.Println("transaction2:")
|
||||
if tx, err := db.Begin(); err == nil {
|
||||
r, err := tx.Table("user").Data(gdb.Map{"uid": 1, "name": "john_1"}).Save()
|
||||
tx.Commit()
|
||||
fmt.Println(r, err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// 主从io复用测试,在mysql中使用 show full processlist 查看链接信息
|
||||
func keepPing() {
|
||||
fmt.Println("keepPing:")
|
||||
for {
|
||||
fmt.Println("ping...")
|
||||
err := db.PingMaster()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
err = db.PingSlave()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
time.Sleep(1*time.Second)
|
||||
}
|
||||
fmt.Println("keepPing:")
|
||||
for {
|
||||
fmt.Println("ping...")
|
||||
err := db.PingMaster()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
err = db.PingSlave()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
// like语句查询
|
||||
func likeQuery() {
|
||||
fmt.Println("likeQuery:")
|
||||
if r, err := db.Table("user").Where("name like ?", "%john%").Select(); err == nil {
|
||||
fmt.Println(r)
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println("likeQuery:")
|
||||
if r, err := db.Table("user").Where("name like ?", "%john%").Select(); err == nil {
|
||||
fmt.Println(r)
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// mapToStruct
|
||||
func mapToStruct() {
|
||||
type User struct {
|
||||
Uid int
|
||||
Name string
|
||||
}
|
||||
fmt.Println("mapToStruct:")
|
||||
if r, err := db.Table("user").Where("uid=?", 1).One(); err == nil {
|
||||
u := User{}
|
||||
if err := r.ToStruct(&u); err == nil {
|
||||
fmt.Println(r)
|
||||
fmt.Println(u)
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
type User struct {
|
||||
Uid int
|
||||
Name string
|
||||
}
|
||||
fmt.Println("mapToStruct:")
|
||||
if r, err := db.Table("user").Where("uid=?", 1).One(); err == nil {
|
||||
u := User{}
|
||||
if err := r.ToStruct(&u); err == nil {
|
||||
fmt.Println(r)
|
||||
fmt.Println(u)
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
// getQueriedSqls
|
||||
func getQueriedSqls() {
|
||||
for k, v := range db.GetQueriedSqls() {
|
||||
fmt.Println(k, ":")
|
||||
fmt.Println("Sql :", v.Sql)
|
||||
fmt.Println("Args :", v.Args)
|
||||
fmt.Println("Error:", v.Error)
|
||||
fmt.Println("Func :", v.Func)
|
||||
}
|
||||
for k, v := range db.GetQueriedSqls() {
|
||||
fmt.Println(k, ":")
|
||||
fmt.Println("Sql :", v.Sql)
|
||||
fmt.Println("Args :", v.Args)
|
||||
fmt.Println("Error:", v.Error)
|
||||
fmt.Println("Func :", v.Func)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
//data := g.Map{
|
||||
// "nickname" : "john",
|
||||
//}
|
||||
//db.SetDebug(true)
|
||||
//r, err := db.Table("user").Where("id=1").Data(data).Update()
|
||||
//fmt.Println(err)
|
||||
//fmt.Println(r.RowsAffected())
|
||||
//data := g.Map{
|
||||
// "nickname" : "john",
|
||||
//}
|
||||
//db.SetDebug(true)
|
||||
//r, err := db.Table("user").Where("id=1").Data(data).Update()
|
||||
//fmt.Println(err)
|
||||
//fmt.Println(r.RowsAffected())
|
||||
|
||||
//data2 := g.Map{
|
||||
// "adsys1" : "ss",
|
||||
//}
|
||||
//db.SetDebug(true)
|
||||
//r, err := db.Table("cd_adsys").Where("adsys0=1").Data(data2).Update()
|
||||
//fmt.Println(err)
|
||||
//fmt.Println(r.RowsAffected())
|
||||
//return
|
||||
//db.SetDebug(true)
|
||||
//r, err := db.Table("test").Where("id=1").One()
|
||||
//fmt.Println(r["datetime"])
|
||||
//fmt.Println(r["datetime"].Time().Date())
|
||||
//fmt.Println(err)
|
||||
//create()
|
||||
//create()
|
||||
//insert()
|
||||
//query()
|
||||
//replace()
|
||||
//save()
|
||||
//batchInsert()
|
||||
//update1()
|
||||
//update2()
|
||||
//update3()
|
||||
linkopSelect1()
|
||||
//linkopSelect2()
|
||||
//linkopSelect3()
|
||||
//linkopCount1()
|
||||
//linkopUpdate1()
|
||||
//linkopUpdate2()
|
||||
//linkopUpdate3()
|
||||
//linkopUpdate4()
|
||||
//
|
||||
//transaction1()
|
||||
//transaction2()
|
||||
//
|
||||
//keepPing()
|
||||
//likeQuery()
|
||||
//mapToStruct()
|
||||
//getQueriedSqls()
|
||||
}
|
||||
//data2 := g.Map{
|
||||
// "adsys1" : "ss",
|
||||
//}
|
||||
//db.SetDebug(true)
|
||||
//r, err := db.Table("cd_adsys").Where("adsys0=1").Data(data2).Update()
|
||||
//fmt.Println(err)
|
||||
//fmt.Println(r.RowsAffected())
|
||||
//return
|
||||
//db.SetDebug(true)
|
||||
//r, err := db.Table("test").Where("id=1").One()
|
||||
//fmt.Println(r["datetime"])
|
||||
//fmt.Println(r["datetime"].Time().Date())
|
||||
//fmt.Println(err)
|
||||
//create()
|
||||
//create()
|
||||
//insert()
|
||||
//query()
|
||||
//replace()
|
||||
//save()
|
||||
//batchInsert()
|
||||
//update1()
|
||||
//update2()
|
||||
//update3()
|
||||
linkopSelect1()
|
||||
//linkopSelect2()
|
||||
//linkopSelect3()
|
||||
//linkopCount1()
|
||||
//linkopUpdate1()
|
||||
//linkopUpdate2()
|
||||
//linkopUpdate3()
|
||||
//linkopUpdate4()
|
||||
//
|
||||
//transaction1()
|
||||
//transaction2()
|
||||
//
|
||||
//keepPing()
|
||||
//likeQuery()
|
||||
//mapToStruct()
|
||||
//getQueriedSqls()
|
||||
}
|
||||
|
||||
@ -1,51 +1,50 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/database/gdb"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/crypto/gaes"
|
||||
"github.com/gogf/gf/g"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/crypto/gaes"
|
||||
"github.com/gogf/gf/g/database/gdb"
|
||||
)
|
||||
|
||||
func main() {
|
||||
gdb.AddDefaultConfigNode(gdb.ConfigNode {
|
||||
Host : "127.0.0.1",
|
||||
Port : "3306",
|
||||
User : "root",
|
||||
Pass : "123456",
|
||||
Name : "test",
|
||||
Type : "mysql",
|
||||
Role : "master",
|
||||
Charset : "utf8",
|
||||
})
|
||||
db, err := gdb.New()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
gdb.AddDefaultConfigNode(gdb.ConfigNode{
|
||||
Host: "127.0.0.1",
|
||||
Port: "3306",
|
||||
User: "root",
|
||||
Pass: "123456",
|
||||
Name: "test",
|
||||
Type: "mysql",
|
||||
Role: "master",
|
||||
Charset: "utf8",
|
||||
})
|
||||
db, err := gdb.New()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
key := "0123456789123456"
|
||||
key := "0123456789123456"
|
||||
|
||||
name := "john"
|
||||
encryptedName, err := gaes.Encrypt([]byte(name), []byte(key))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
name := "john"
|
||||
encryptedName, err := gaes.Encrypt([]byte(name), []byte(key))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
// 写入
|
||||
r, err := db.Table("user").Data(g.Map{
|
||||
"uid": 1,
|
||||
"name": encryptedName,
|
||||
}).Save()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(r.RowsAffected())
|
||||
|
||||
// 写入
|
||||
r, err := db.Table("user").Data(g.Map{
|
||||
"uid" : 1,
|
||||
"name" : encryptedName,
|
||||
}).Save()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(r.RowsAffected())
|
||||
|
||||
// 查询
|
||||
one, err := db.Table("user").Where("name=?", encryptedName).One()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(one.ToMap())
|
||||
}
|
||||
// 查询
|
||||
one, err := db.Table("user").Where("name=?", encryptedName).One()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Println(one.ToMap())
|
||||
}
|
||||
|
||||
@ -1,38 +1,38 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/database/gdb"
|
||||
"github.com/gogf/gf/g/util/gutil"
|
||||
"github.com/gogf/gf/g/database/gdb"
|
||||
"github.com/gogf/gf/g/util/gutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
gdb.AddDefaultConfigNode(gdb.ConfigNode {
|
||||
Host : "127.0.0.1",
|
||||
Port : "3306",
|
||||
User : "root",
|
||||
Pass : "123456",
|
||||
Name : "test",
|
||||
Type : "mysql",
|
||||
Role : "master",
|
||||
Charset : "utf8",
|
||||
})
|
||||
db, err := gdb.New()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// 开启调试模式,以便于记录所有执行的SQL
|
||||
db.SetDebug(true)
|
||||
gdb.AddDefaultConfigNode(gdb.ConfigNode{
|
||||
Host: "127.0.0.1",
|
||||
Port: "3306",
|
||||
User: "root",
|
||||
Pass: "123456",
|
||||
Name: "test",
|
||||
Type: "mysql",
|
||||
Role: "master",
|
||||
Charset: "utf8",
|
||||
})
|
||||
db, err := gdb.New()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// 开启调试模式,以便于记录所有执行的SQL
|
||||
db.SetDebug(true)
|
||||
|
||||
// 执行2次查询并将查询结果缓存3秒,并可执行缓存名称(可选)
|
||||
for i := 0; i < 2; i++ {
|
||||
r, _ := db.Table("user").Cache(3, "vip-user").Where("uid=?", 1).One()
|
||||
gutil.Dump(r.ToMap())
|
||||
}
|
||||
// 执行2次查询并将查询结果缓存3秒,并可执行缓存名称(可选)
|
||||
for i := 0; i < 2; i++ {
|
||||
r, _ := db.Table("user").Cache(3, "vip-user").Where("uid=?", 1).One()
|
||||
gutil.Dump(r.ToMap())
|
||||
}
|
||||
|
||||
// 执行更新操作,并清理指定名称的查询缓存
|
||||
db.Table("user").Cache(-1, "vip-user").Data(gdb.Map{"name" : "smith"}).Where("uid=?", 1).Update()
|
||||
// 执行更新操作,并清理指定名称的查询缓存
|
||||
db.Table("user").Cache(-1, "vip-user").Data(gdb.Map{"name": "smith"}).Where("uid=?", 1).Update()
|
||||
|
||||
// 再次执行查询,启用查询缓存特性
|
||||
r, _ := db.Table("user").Cache(3, "vip-user").Where("uid=?", 1).One()
|
||||
gutil.Dump(r.ToMap())
|
||||
}
|
||||
// 再次执行查询,启用查询缓存特性
|
||||
r, _ := db.Table("user").Cache(3, "vip-user").Where("uid=?", 1).One()
|
||||
gutil.Dump(r.ToMap())
|
||||
}
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
)
|
||||
|
||||
func main() {
|
||||
g.Config().AddPath("/home/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/geg/frame")
|
||||
if r, err := g.DB().Table("user").Where("uid=?", 1).One(); err == nil {
|
||||
fmt.Println(r["uid"].Int())
|
||||
fmt.Println(r["name"].String())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
g.Config().AddPath("/home/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/geg/frame")
|
||||
if r, err := g.DB().Table("user").Where("uid=?", 1).One(); err == nil {
|
||||
fmt.Println(r["uid"].Int())
|
||||
fmt.Println(r["name"].String())
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,29 +1,29 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/os/gtime"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/os/gtime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
db := g.Database()
|
||||
db.SetDebug(true)
|
||||
db := g.Database()
|
||||
db.SetDebug(true)
|
||||
|
||||
//r, err := db.Table("user").Data("create_time", gtime.Now().String()).Insert()
|
||||
//if err == nil {
|
||||
// fmt.Println(r.LastInsertId())
|
||||
//} else {
|
||||
// panic(err)
|
||||
//}
|
||||
//r, err := db.Table("user").Data("create_time", gtime.Now().String()).Insert()
|
||||
//if err == nil {
|
||||
// fmt.Println(r.LastInsertId())
|
||||
//} else {
|
||||
// panic(err)
|
||||
//}
|
||||
|
||||
r, err := db.Table("user").Data(g.Map{
|
||||
"name" : "john",
|
||||
"create_time" : gtime.Now().String(),
|
||||
}).Insert()
|
||||
if err == nil {
|
||||
fmt.Println(r.LastInsertId())
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
r, err := db.Table("user").Data(g.Map{
|
||||
"name": "john",
|
||||
"create_time": gtime.Now().String(),
|
||||
}).Insert()
|
||||
if err == nil {
|
||||
fmt.Println(r.LastInsertId())
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,36 +1,36 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/database/gdb"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/os/glog"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/database/gdb"
|
||||
"github.com/gogf/gf/g/os/glog"
|
||||
)
|
||||
|
||||
func main() {
|
||||
gdb.AddDefaultConfigNode(gdb.ConfigNode{
|
||||
Host: "127.0.0.1",
|
||||
Port: "3306",
|
||||
User: "root",
|
||||
Pass: "12345678",
|
||||
Name: "test",
|
||||
Type: "mysql",
|
||||
Role: "master",
|
||||
Charset: "utf8",
|
||||
})
|
||||
db, err := gdb.New()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
glog.SetPath("/tmp")
|
||||
db.SetDebug(true)
|
||||
// 执行3条SQL查询
|
||||
for i := 1; i <= 3; i++ {
|
||||
db.Table("user").Where("uid=?", i).One()
|
||||
}
|
||||
// 构造一条错误查询
|
||||
db.Table("user").Where("no_such_field=?", "just_test").One()
|
||||
gdb.AddDefaultConfigNode(gdb.ConfigNode{
|
||||
Host: "127.0.0.1",
|
||||
Port: "3306",
|
||||
User: "root",
|
||||
Pass: "12345678",
|
||||
Name: "test",
|
||||
Type: "mysql",
|
||||
Role: "master",
|
||||
Charset: "utf8",
|
||||
})
|
||||
db, err := gdb.New()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
glog.SetPath("/tmp")
|
||||
db.SetDebug(true)
|
||||
// 执行3条SQL查询
|
||||
for i := 1; i <= 3; i++ {
|
||||
db.Table("user").Where("uid=?", i).One()
|
||||
}
|
||||
// 构造一条错误查询
|
||||
db.Table("user").Where("no_such_field=?", "just_test").One()
|
||||
|
||||
db.Table("user").Data(g.Map{"name":"smith"}).Where("uid=?", 1).Save()
|
||||
db.Table("user").Data(g.Map{"name": "smith"}).Where("uid=?", 1).Save()
|
||||
|
||||
//db.PrintQueriedSqls()
|
||||
}
|
||||
//db.PrintQueriedSqls()
|
||||
}
|
||||
|
||||
@ -1,36 +1,36 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/database/gdb"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/encoding/gparser"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/database/gdb"
|
||||
"github.com/gogf/gf/g/encoding/gparser"
|
||||
)
|
||||
|
||||
func main() {
|
||||
gdb.AddDefaultConfigNode(gdb.ConfigNode {
|
||||
Host : "127.0.0.1",
|
||||
Port : "3306",
|
||||
User : "root",
|
||||
Pass : "12345678",
|
||||
Name : "test",
|
||||
Type : "mysql",
|
||||
Role : "master",
|
||||
Charset : "utf8",
|
||||
})
|
||||
db := g.DB()
|
||||
one, err := db.Table("user").Where("id=?", 1).One()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
gdb.AddDefaultConfigNode(gdb.ConfigNode{
|
||||
Host: "127.0.0.1",
|
||||
Port: "3306",
|
||||
User: "root",
|
||||
Pass: "12345678",
|
||||
Name: "test",
|
||||
Type: "mysql",
|
||||
Role: "master",
|
||||
Charset: "utf8",
|
||||
})
|
||||
db := g.DB()
|
||||
one, err := db.Table("user").Where("id=?", 1).One()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// 使用内置方法转换为json/xml
|
||||
fmt.Println(one.ToJson())
|
||||
fmt.Println(one.ToXml())
|
||||
// 使用内置方法转换为json/xml
|
||||
fmt.Println(one.ToJson())
|
||||
fmt.Println(one.ToXml())
|
||||
|
||||
// 自定义方法方法转换为json/xml
|
||||
jsonContent, _ := gparser.VarToJson(one.ToMap())
|
||||
fmt.Println(string(jsonContent))
|
||||
xmlContent, _ := gparser.VarToXml(one.ToMap())
|
||||
fmt.Println(string(xmlContent))
|
||||
}
|
||||
// 自定义方法方法转换为json/xml
|
||||
jsonContent, _ := gparser.VarToJson(one.ToMap())
|
||||
fmt.Println(string(jsonContent))
|
||||
xmlContent, _ := gparser.VarToXml(one.ToMap())
|
||||
fmt.Println(string(xmlContent))
|
||||
}
|
||||
|
||||
@ -1,24 +1,24 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g"
|
||||
"time"
|
||||
"github.com/gogf/gf/g"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
db := g.DB()
|
||||
db.SetMaxIdleConns(10)
|
||||
db.SetMaxOpenConns(10)
|
||||
db.SetConnMaxLifetime(10)
|
||||
db := g.DB()
|
||||
db.SetMaxIdleConns(10)
|
||||
db.SetMaxOpenConns(10)
|
||||
db.SetConnMaxLifetime(10)
|
||||
|
||||
// 开启调试模式,以便于记录所有执行的SQL
|
||||
db.SetDebug(true)
|
||||
// 开启调试模式,以便于记录所有执行的SQL
|
||||
db.SetDebug(true)
|
||||
|
||||
for {
|
||||
for i := 0; i < 10; i++ {
|
||||
go db.Table("user").All()
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
for {
|
||||
for i := 0; i < 10; i++ {
|
||||
go db.Table("user").All()
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
)
|
||||
|
||||
func main() {
|
||||
db := g.DB()
|
||||
// 开启调试模式,以便于记录所有执行的SQL
|
||||
db.SetDebug(true)
|
||||
db := g.DB()
|
||||
// 开启调试模式,以便于记录所有执行的SQL
|
||||
db.SetDebug(true)
|
||||
|
||||
r, _ := db.Table("test").Where("id IN (?)", []interface{}{1, 2}).All()
|
||||
if r != nil {
|
||||
fmt.Println(r.ToList())
|
||||
}
|
||||
}
|
||||
r, _ := db.Table("test").Where("id IN (?)", []interface{}{1, 2}).All()
|
||||
if r != nil {
|
||||
fmt.Println(r.ToList())
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,4 +44,4 @@ package main
|
||||
// if _, err := db.Exec(sql); err != nil {
|
||||
// fmt.Println(err)
|
||||
// }
|
||||
//}
|
||||
//}
|
||||
|
||||
@ -1,20 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
"github.com/gogf/gf/g/database/gredis"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/database/gredis"
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
)
|
||||
|
||||
// 使用原生gredis.New操作redis,但是注意需要自己调用Close方法关闭redis链接池
|
||||
func main() {
|
||||
redis := gredis.New(gredis.Config{
|
||||
Host : "127.0.0.1",
|
||||
Port : 6379,
|
||||
})
|
||||
defer redis.Close()
|
||||
redis.Do("SET", "k", "v")
|
||||
v, _ := redis.Do("GET", "k")
|
||||
fmt.Println(gconv.String(v))
|
||||
redis := gredis.New(gredis.Config{
|
||||
Host: "127.0.0.1",
|
||||
Port: 6379,
|
||||
})
|
||||
defer redis.Close()
|
||||
redis.Do("SET", "k", "v")
|
||||
v, _ := redis.Do("GET", "k")
|
||||
fmt.Println(gconv.String(v))
|
||||
}
|
||||
|
||||
|
||||
@ -1,15 +1,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
)
|
||||
|
||||
// 使用框架封装的g.Redis()方法获得redis操作对象单例,不需要开发者显示调用Close方法
|
||||
func main() {
|
||||
g.Redis().Do("SET", "k", "v")
|
||||
v, _ := g.Redis().Do("GET", "k")
|
||||
fmt.Println(gconv.String(v))
|
||||
g.Redis().Do("SET", "k", "v")
|
||||
v, _ := g.Redis().Do("GET", "k")
|
||||
fmt.Println(gconv.String(v))
|
||||
}
|
||||
|
||||
|
||||
@ -1,16 +1,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
)
|
||||
|
||||
func main() {
|
||||
conn := g.Redis().Conn()
|
||||
defer conn.Close()
|
||||
conn.Do("SET", "k", "v")
|
||||
v, _ := conn.Do("GET", "k")
|
||||
fmt.Println(gconv.String(v))
|
||||
conn := g.Redis().Conn()
|
||||
defer conn.Close()
|
||||
conn.Do("SET", "k", "v")
|
||||
v, _ := conn.Do("GET", "k")
|
||||
fmt.Println(gconv.String(v))
|
||||
}
|
||||
|
||||
|
||||
@ -1,21 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
)
|
||||
|
||||
func main() {
|
||||
conn := g.Redis().Conn()
|
||||
defer conn.Close()
|
||||
conn.Send("SET", "foo", "bar")
|
||||
conn.Send("GET", "foo")
|
||||
conn.Flush()
|
||||
// reply from SET
|
||||
conn.Receive()
|
||||
// reply from GET
|
||||
v, _ := conn.Receive()
|
||||
fmt.Println(gconv.String(v))
|
||||
conn := g.Redis().Conn()
|
||||
defer conn.Close()
|
||||
conn.Send("SET", "foo", "bar")
|
||||
conn.Send("GET", "foo")
|
||||
conn.Flush()
|
||||
// reply from SET
|
||||
conn.Receive()
|
||||
// reply from GET
|
||||
v, _ := conn.Receive()
|
||||
fmt.Println(gconv.String(v))
|
||||
}
|
||||
|
||||
|
||||
@ -1,24 +1,23 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
)
|
||||
|
||||
func main() {
|
||||
conn := g.Redis().Conn()
|
||||
defer conn.Close()
|
||||
_, err := conn.Do("SUBSCRIBE", "channel")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for {
|
||||
reply, err := conn.Receive()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(gconv.Strings(reply))
|
||||
}
|
||||
conn := g.Redis().Conn()
|
||||
defer conn.Close()
|
||||
_, err := conn.Do("SUBSCRIBE", "channel")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for {
|
||||
reply, err := conn.Receive()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(gconv.Strings(reply))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,18 +1,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/encoding/gbase64"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/encoding/gbase64"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := "john"
|
||||
b := gbase64.Encode(s)
|
||||
c, e := gbase64.Decode(b)
|
||||
fmt.Println(b)
|
||||
fmt.Println(c)
|
||||
fmt.Println(e)
|
||||
s := "john"
|
||||
b := gbase64.Encode(s)
|
||||
c, e := gbase64.Decode(b)
|
||||
fmt.Println(b)
|
||||
fmt.Println(c)
|
||||
fmt.Println(e)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,61 +1,61 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/os/glog"
|
||||
"github.com/gogf/gf/g/encoding/gbinary"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/encoding/gbinary"
|
||||
"github.com/gogf/gf/g/os/glog"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 使用gbinary.Encoded对基本数据类型进行二进制打包
|
||||
if buffer, err := gbinary.Encode(18, 300, 1.01); err != nil {
|
||||
glog.Error(err)
|
||||
} else {
|
||||
fmt.Println(buffer)
|
||||
}
|
||||
// 使用gbinary.Encoded对基本数据类型进行二进制打包
|
||||
if buffer, err := gbinary.Encode(18, 300, 1.01); err != nil {
|
||||
glog.Error(err)
|
||||
} else {
|
||||
fmt.Println(buffer)
|
||||
}
|
||||
|
||||
// 使用gbinary.Decode对整形二进制解包,注意第二个及其后参数为字长确定的整形变量的指针地址,字长确定的类型,
|
||||
// 例如:int8/16/32/64、uint8/16/32/64、float32/64
|
||||
// 这里的1.01默认为float64类型(64位系统下)
|
||||
if buffer, err := gbinary.Encode(18, 300, 1.01); err != nil {
|
||||
glog.Error(err)
|
||||
} else {
|
||||
var i1 int8
|
||||
var i2 int16
|
||||
var f3 float64
|
||||
if err := gbinary.Decode(buffer, &i1, &i2, &f3); err != nil {
|
||||
glog.Error(err)
|
||||
} else {
|
||||
fmt.Println(i1, i2, f3)
|
||||
}
|
||||
}
|
||||
// 使用gbinary.Decode对整形二进制解包,注意第二个及其后参数为字长确定的整形变量的指针地址,字长确定的类型,
|
||||
// 例如:int8/16/32/64、uint8/16/32/64、float32/64
|
||||
// 这里的1.01默认为float64类型(64位系统下)
|
||||
if buffer, err := gbinary.Encode(18, 300, 1.01); err != nil {
|
||||
glog.Error(err)
|
||||
} else {
|
||||
var i1 int8
|
||||
var i2 int16
|
||||
var f3 float64
|
||||
if err := gbinary.Decode(buffer, &i1, &i2, &f3); err != nil {
|
||||
glog.Error(err)
|
||||
} else {
|
||||
fmt.Println(i1, i2, f3)
|
||||
}
|
||||
}
|
||||
|
||||
// 编码/解析 int,自动识别变量长度
|
||||
fmt.Println(gbinary.DecodeToInt(gbinary.EncodeInt(1)))
|
||||
fmt.Println(gbinary.DecodeToInt(gbinary.EncodeInt(300)))
|
||||
fmt.Println(gbinary.DecodeToInt(gbinary.EncodeInt(70000)))
|
||||
fmt.Println(gbinary.DecodeToInt(gbinary.EncodeInt(2000000000)))
|
||||
fmt.Println(gbinary.DecodeToInt(gbinary.EncodeInt(500000000000)))
|
||||
// 编码/解析 int,自动识别变量长度
|
||||
fmt.Println(gbinary.DecodeToInt(gbinary.EncodeInt(1)))
|
||||
fmt.Println(gbinary.DecodeToInt(gbinary.EncodeInt(300)))
|
||||
fmt.Println(gbinary.DecodeToInt(gbinary.EncodeInt(70000)))
|
||||
fmt.Println(gbinary.DecodeToInt(gbinary.EncodeInt(2000000000)))
|
||||
fmt.Println(gbinary.DecodeToInt(gbinary.EncodeInt(500000000000)))
|
||||
|
||||
// 编码/解析 uint,自动识别变量长度
|
||||
fmt.Println(gbinary.DecodeToUint(gbinary.EncodeUint(1)))
|
||||
fmt.Println(gbinary.DecodeToUint(gbinary.EncodeUint(300)))
|
||||
fmt.Println(gbinary.DecodeToUint(gbinary.EncodeUint(70000)))
|
||||
fmt.Println(gbinary.DecodeToUint(gbinary.EncodeUint(2000000000)))
|
||||
fmt.Println(gbinary.DecodeToUint(gbinary.EncodeUint(500000000000)))
|
||||
// 编码/解析 uint,自动识别变量长度
|
||||
fmt.Println(gbinary.DecodeToUint(gbinary.EncodeUint(1)))
|
||||
fmt.Println(gbinary.DecodeToUint(gbinary.EncodeUint(300)))
|
||||
fmt.Println(gbinary.DecodeToUint(gbinary.EncodeUint(70000)))
|
||||
fmt.Println(gbinary.DecodeToUint(gbinary.EncodeUint(2000000000)))
|
||||
fmt.Println(gbinary.DecodeToUint(gbinary.EncodeUint(500000000000)))
|
||||
|
||||
// 编码/解析 int8/16/32/64
|
||||
fmt.Println(gbinary.DecodeToInt8(gbinary.EncodeInt8(int8(100))))
|
||||
fmt.Println(gbinary.DecodeToInt16(gbinary.EncodeInt16(int16(100))))
|
||||
fmt.Println(gbinary.DecodeToInt32(gbinary.EncodeInt32(int32(100))))
|
||||
fmt.Println(gbinary.DecodeToInt64(gbinary.EncodeInt64(int64(100))))
|
||||
// 编码/解析 int8/16/32/64
|
||||
fmt.Println(gbinary.DecodeToInt8(gbinary.EncodeInt8(int8(100))))
|
||||
fmt.Println(gbinary.DecodeToInt16(gbinary.EncodeInt16(int16(100))))
|
||||
fmt.Println(gbinary.DecodeToInt32(gbinary.EncodeInt32(int32(100))))
|
||||
fmt.Println(gbinary.DecodeToInt64(gbinary.EncodeInt64(int64(100))))
|
||||
|
||||
// 编码/解析 uint8/16/32/64
|
||||
fmt.Println(gbinary.DecodeToUint8(gbinary.EncodeUint8(uint8(100))))
|
||||
fmt.Println(gbinary.DecodeToUint16(gbinary.EncodeUint16(uint16(100))))
|
||||
fmt.Println(gbinary.DecodeToUint32(gbinary.EncodeUint32(uint32(100))))
|
||||
fmt.Println(gbinary.DecodeToUint64(gbinary.EncodeUint64(uint64(100))))
|
||||
// 编码/解析 uint8/16/32/64
|
||||
fmt.Println(gbinary.DecodeToUint8(gbinary.EncodeUint8(uint8(100))))
|
||||
fmt.Println(gbinary.DecodeToUint16(gbinary.EncodeUint16(uint16(100))))
|
||||
fmt.Println(gbinary.DecodeToUint32(gbinary.EncodeUint32(uint32(100))))
|
||||
fmt.Println(gbinary.DecodeToUint64(gbinary.EncodeUint64(uint64(100))))
|
||||
|
||||
// 编码/解析 string
|
||||
fmt.Println(gbinary.DecodeToString(gbinary.EncodeString("I'm string!")))
|
||||
// 编码/解析 string
|
||||
fmt.Println(gbinary.DecodeToString(gbinary.EncodeString("I'm string!")))
|
||||
}
|
||||
|
||||
@ -1,32 +1,32 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/encoding/gbinary"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/encoding/gbinary"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 传感器状态,0:已下线, 1:开启, 2:关闭, 3:待机
|
||||
count := 100
|
||||
status := 1
|
||||
// 传感器状态,0:已下线, 1:开启, 2:关闭, 3:待机
|
||||
count := 100
|
||||
status := 1
|
||||
|
||||
// 网关编码
|
||||
bits := make([]gbinary.Bit, 0)
|
||||
for i := 0; i < count; i++ {
|
||||
bits = gbinary.EncodeBits(bits, status, 2)
|
||||
}
|
||||
buffer := gbinary.EncodeBitsToBytes(bits)
|
||||
fmt.Println("buffer length:", len(buffer))
|
||||
// 网关编码
|
||||
bits := make([]gbinary.Bit, 0)
|
||||
for i := 0; i < count; i++ {
|
||||
bits = gbinary.EncodeBits(bits, status, 2)
|
||||
}
|
||||
buffer := gbinary.EncodeBitsToBytes(bits)
|
||||
fmt.Println("buffer length:", len(buffer))
|
||||
|
||||
/* 上报过程忽略,这里只展示编码/解码示例 */
|
||||
/* 上报过程忽略,这里只展示编码/解码示例 */
|
||||
|
||||
// 平台解码
|
||||
alivecount := 0
|
||||
sensorbits := gbinary.DecodeBytesToBits(buffer)
|
||||
for i := 0; i < len(sensorbits); i += 2 {
|
||||
if gbinary.DecodeBits(sensorbits[i:i+2]) == 1 {
|
||||
alivecount++
|
||||
}
|
||||
}
|
||||
fmt.Println("alived sensor:", alivecount)
|
||||
// 平台解码
|
||||
alivecount := 0
|
||||
sensorbits := gbinary.DecodeBytesToBits(buffer)
|
||||
for i := 0; i < len(sensorbits); i += 2 {
|
||||
if gbinary.DecodeBits(sensorbits[i:i+2]) == 1 {
|
||||
alivecount++
|
||||
}
|
||||
}
|
||||
fmt.Println("alived sensor:", alivecount)
|
||||
}
|
||||
|
||||
@ -1,32 +1,32 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/encoding/gbinary"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/encoding/gbinary"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Meta元数据文件数据结构:[键名哈希64(64bit,8byte) 键名长度(8bit,1byte) 键值长度(24bit,3byte) 数据文件偏移量(40bit,5byte)](变长)
|
||||
hash := 521369841259754125
|
||||
klen := 12
|
||||
vlen := 35535
|
||||
offset := 80000000
|
||||
// Meta元数据文件数据结构:[键名哈希64(64bit,8byte) 键名长度(8bit,1byte) 键值长度(24bit,3byte) 数据文件偏移量(40bit,5byte)](变长)
|
||||
hash := 521369841259754125
|
||||
klen := 12
|
||||
vlen := 35535
|
||||
offset := 80000000
|
||||
|
||||
// 编码
|
||||
bits := make([]gbinary.Bit, 0)
|
||||
bits = gbinary.EncodeBits(bits, hash, 64)
|
||||
bits = gbinary.EncodeBits(bits, klen, 8)
|
||||
bits = gbinary.EncodeBits(bits, vlen, 24)
|
||||
bits = gbinary.EncodeBits(bits, offset, 40)
|
||||
buffer := gbinary.EncodeBitsToBytes(bits)
|
||||
fmt.Println("meta length:", len(buffer))
|
||||
// 编码
|
||||
bits := make([]gbinary.Bit, 0)
|
||||
bits = gbinary.EncodeBits(bits, hash, 64)
|
||||
bits = gbinary.EncodeBits(bits, klen, 8)
|
||||
bits = gbinary.EncodeBits(bits, vlen, 24)
|
||||
bits = gbinary.EncodeBits(bits, offset, 40)
|
||||
buffer := gbinary.EncodeBitsToBytes(bits)
|
||||
fmt.Println("meta length:", len(buffer))
|
||||
|
||||
/* 文件存储及数据查询过程忽略,这里只展示元数据编码/解码示例 */
|
||||
/* 文件存储及数据查询过程忽略,这里只展示元数据编码/解码示例 */
|
||||
|
||||
// 解码
|
||||
metabits := gbinary.DecodeBytesToBits(buffer)
|
||||
fmt.Println("hash :", gbinary.DecodeBits(metabits[0 : 64]))
|
||||
fmt.Println("klen :", gbinary.DecodeBits(metabits[64 : 72]))
|
||||
fmt.Println("vlen :", gbinary.DecodeBits(metabits[72 : 96]))
|
||||
fmt.Println("offset:", gbinary.DecodeBits(metabits[96 : 136]))
|
||||
// 解码
|
||||
metabits := gbinary.DecodeBytesToBits(buffer)
|
||||
fmt.Println("hash :", gbinary.DecodeBits(metabits[0:64]))
|
||||
fmt.Println("klen :", gbinary.DecodeBits(metabits[64:72]))
|
||||
fmt.Println("vlen :", gbinary.DecodeBits(metabits[72:96]))
|
||||
fmt.Println("offset:", gbinary.DecodeBits(metabits[96:136]))
|
||||
}
|
||||
|
||||
@ -1,22 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(g.Config().Get("redis"))
|
||||
fmt.Println(g.Config().Get("redis"))
|
||||
|
||||
type RedisConfig struct {
|
||||
Disk string
|
||||
Cache string
|
||||
}
|
||||
type RedisConfig struct {
|
||||
Disk string
|
||||
Cache string
|
||||
}
|
||||
|
||||
redisCfg := new(RedisConfig)
|
||||
fmt.Println(g.Config().GetToStruct("redis", redisCfg))
|
||||
fmt.Println(redisCfg)
|
||||
redisCfg := new(RedisConfig)
|
||||
fmt.Println(g.Config().GetToStruct("redis", redisCfg))
|
||||
fmt.Println(redisCfg)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,20 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/encoding/ghash"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/encoding/ghash"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func main () {
|
||||
m := make(map[uint64]bool)
|
||||
for i := 0; i < 100000000; i++ {
|
||||
hash := ghash.BKDRHash64([]byte("key_" + strconv.Itoa(i)))
|
||||
if _, ok := m[hash]; ok {
|
||||
fmt.Printf("duplicated hash %d\n", hash)
|
||||
} else {
|
||||
m[hash] = true
|
||||
}
|
||||
}
|
||||
func main() {
|
||||
m := make(map[uint64]bool)
|
||||
for i := 0; i < 100000000; i++ {
|
||||
hash := ghash.BKDRHash64([]byte("key_" + strconv.Itoa(i)))
|
||||
if _, ok := m[hash]; ok {
|
||||
fmt.Printf("duplicated hash %d\n", hash)
|
||||
} else {
|
||||
m[hash] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/os/glog"
|
||||
"github.com/gogf/gf/g/encoding/gjson"
|
||||
"github.com/gogf/gf/g/os/gtime"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/encoding/gjson"
|
||||
"github.com/gogf/gf/g/os/glog"
|
||||
"github.com/gogf/gf/g/os/gtime"
|
||||
)
|
||||
|
||||
func getByPattern() {
|
||||
data :=
|
||||
`{
|
||||
data :=
|
||||
`{
|
||||
"users" : {
|
||||
"count" : 100,
|
||||
"list" : [
|
||||
@ -18,143 +18,137 @@ func getByPattern() {
|
||||
]
|
||||
}
|
||||
}`
|
||||
j, err := gjson.DecodeToJson([]byte(data))
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
} else {
|
||||
fmt.Println("John Score:", j.GetFloat32("users.list.1.score"))
|
||||
}
|
||||
j, err := gjson.DecodeToJson([]byte(data))
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
} else {
|
||||
fmt.Println("John Score:", j.GetFloat32("users.list.1.score"))
|
||||
}
|
||||
}
|
||||
|
||||
// 当键名存在"."号时,检索优先级:键名->层级,因此不会引起歧义
|
||||
func testMultiDots() {
|
||||
data :=
|
||||
`{
|
||||
data :=
|
||||
`{
|
||||
"users" : {
|
||||
"count" : 100
|
||||
},
|
||||
"users.count" : 101
|
||||
}`
|
||||
j, err := gjson.DecodeToJson([]byte(data))
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
} else {
|
||||
fmt.Println("Users Count:", j.GetInt("users.count"))
|
||||
}
|
||||
j, err := gjson.DecodeToJson([]byte(data))
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
} else {
|
||||
fmt.Println("Users Count:", j.GetInt("users.count"))
|
||||
}
|
||||
}
|
||||
|
||||
// 设置数据
|
||||
func testSet() {
|
||||
data :=
|
||||
`{
|
||||
data :=
|
||||
`{
|
||||
"users" : {
|
||||
"count" : 100
|
||||
}
|
||||
}`
|
||||
j, err := gjson.DecodeToJson([]byte(data))
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
} else {
|
||||
j.Set("users.count", 1)
|
||||
j.Set("users.list", []string{"John", "小明"})
|
||||
c, _ := j.ToJson()
|
||||
fmt.Println(string(c))
|
||||
}
|
||||
j, err := gjson.DecodeToJson([]byte(data))
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
} else {
|
||||
j.Set("users.count", 1)
|
||||
j.Set("users.list", []string{"John", "小明"})
|
||||
c, _ := j.ToJson()
|
||||
fmt.Println(string(c))
|
||||
}
|
||||
}
|
||||
|
||||
// 将Json数据转换为其他数据格式
|
||||
func testConvert() {
|
||||
data :=
|
||||
`{
|
||||
data :=
|
||||
`{
|
||||
"users" : {
|
||||
"count" : 100,
|
||||
"list" : ["John", "小明"]
|
||||
}
|
||||
}`
|
||||
j, err := gjson.DecodeToJson([]byte(data))
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
} else {
|
||||
c, _ := j.ToJson()
|
||||
fmt.Println("JSON:")
|
||||
fmt.Println(string(c))
|
||||
fmt.Println("======================")
|
||||
j, err := gjson.DecodeToJson([]byte(data))
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
} else {
|
||||
c, _ := j.ToJson()
|
||||
fmt.Println("JSON:")
|
||||
fmt.Println(string(c))
|
||||
fmt.Println("======================")
|
||||
|
||||
fmt.Println("XML:")
|
||||
c, _ = j.ToXmlIndent()
|
||||
fmt.Println(string(c))
|
||||
fmt.Println("======================")
|
||||
fmt.Println("XML:")
|
||||
c, _ = j.ToXmlIndent()
|
||||
fmt.Println(string(c))
|
||||
fmt.Println("======================")
|
||||
|
||||
fmt.Println("YAML:")
|
||||
c, _ = j.ToYaml()
|
||||
fmt.Println(string(c))
|
||||
fmt.Println("======================")
|
||||
fmt.Println("YAML:")
|
||||
c, _ = j.ToYaml()
|
||||
fmt.Println(string(c))
|
||||
fmt.Println("======================")
|
||||
|
||||
fmt.Println("TOML:")
|
||||
c, _ = j.ToToml()
|
||||
fmt.Println(string(c))
|
||||
}
|
||||
fmt.Println("TOML:")
|
||||
c, _ = j.ToToml()
|
||||
fmt.Println(string(c))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func testSplitChar() {
|
||||
var v interface{}
|
||||
j := gjson.New(nil)
|
||||
t1 := gtime.Nanosecond()
|
||||
j.Set("a.b.c.d.e.f.g.h.i.j.k", 1)
|
||||
t2 := gtime.Nanosecond()
|
||||
fmt.Println(t2 - t1)
|
||||
var v interface{}
|
||||
j := gjson.New(nil)
|
||||
t1 := gtime.Nanosecond()
|
||||
j.Set("a.b.c.d.e.f.g.h.i.j.k", 1)
|
||||
t2 := gtime.Nanosecond()
|
||||
fmt.Println(t2 - t1)
|
||||
|
||||
t5 := gtime.Nanosecond()
|
||||
v = j.Get("a.b.c.d.e.f.g.h.i.j.k")
|
||||
t6 := gtime.Nanosecond()
|
||||
fmt.Println(v)
|
||||
fmt.Println(t6 - t5)
|
||||
t5 := gtime.Nanosecond()
|
||||
v = j.Get("a.b.c.d.e.f.g.h.i.j.k")
|
||||
t6 := gtime.Nanosecond()
|
||||
fmt.Println(v)
|
||||
fmt.Println(t6 - t5)
|
||||
|
||||
j.SetSplitChar('#')
|
||||
j.SetSplitChar('#')
|
||||
|
||||
|
||||
|
||||
t7 := gtime.Nanosecond()
|
||||
v = j.Get("a#b#c#d#e#f#g#h#i#j#k")
|
||||
t8 := gtime.Nanosecond()
|
||||
fmt.Println(v)
|
||||
fmt.Println(t8 - t7)
|
||||
t7 := gtime.Nanosecond()
|
||||
v = j.Get("a#b#c#d#e#f#g#h#i#j#k")
|
||||
t8 := gtime.Nanosecond()
|
||||
fmt.Println(v)
|
||||
fmt.Println(t8 - t7)
|
||||
}
|
||||
|
||||
|
||||
func testViolenceCheck() {
|
||||
j := gjson.New(nil)
|
||||
t1 := gtime.Nanosecond()
|
||||
j.Set("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a", 1)
|
||||
t2 := gtime.Nanosecond()
|
||||
fmt.Println(t2 - t1)
|
||||
j := gjson.New(nil)
|
||||
t1 := gtime.Nanosecond()
|
||||
j.Set("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a", 1)
|
||||
t2 := gtime.Nanosecond()
|
||||
fmt.Println(t2 - t1)
|
||||
|
||||
t3 := gtime.Nanosecond()
|
||||
j.Set("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a", 1)
|
||||
t4 := gtime.Nanosecond()
|
||||
fmt.Println(t4 - t3)
|
||||
t3 := gtime.Nanosecond()
|
||||
j.Set("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a", 1)
|
||||
t4 := gtime.Nanosecond()
|
||||
fmt.Println(t4 - t3)
|
||||
|
||||
t5 := gtime.Nanosecond()
|
||||
j.Get("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a")
|
||||
t6 := gtime.Nanosecond()
|
||||
fmt.Println(t6 - t5)
|
||||
t5 := gtime.Nanosecond()
|
||||
j.Get("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a")
|
||||
t6 := gtime.Nanosecond()
|
||||
fmt.Println(t6 - t5)
|
||||
|
||||
j.SetViolenceCheck(false)
|
||||
|
||||
j.SetViolenceCheck(false)
|
||||
t7 := gtime.Nanosecond()
|
||||
j.Set("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a", 1)
|
||||
t8 := gtime.Nanosecond()
|
||||
fmt.Println(t8 - t7)
|
||||
|
||||
|
||||
t7 := gtime.Nanosecond()
|
||||
j.Set("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a", 1)
|
||||
t8 := gtime.Nanosecond()
|
||||
fmt.Println(t8 - t7)
|
||||
|
||||
t9 := gtime.Nanosecond()
|
||||
j.Get("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a")
|
||||
t10 := gtime.Nanosecond()
|
||||
fmt.Println(t10 - t9)
|
||||
t9 := gtime.Nanosecond()
|
||||
j.Get("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a")
|
||||
t10 := gtime.Nanosecond()
|
||||
fmt.Println(t10 - t9)
|
||||
}
|
||||
|
||||
func main() {
|
||||
testViolenceCheck()
|
||||
}
|
||||
testViolenceCheck()
|
||||
}
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/os/glog"
|
||||
"github.com/gogf/gf/g/encoding/gparser"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/encoding/gparser"
|
||||
"github.com/gogf/gf/g/os/glog"
|
||||
)
|
||||
|
||||
func getWithPattern1() {
|
||||
data :=
|
||||
`{
|
||||
data :=
|
||||
`{
|
||||
"users" : {
|
||||
"count" : 100,
|
||||
"list" : [
|
||||
@ -18,16 +18,16 @@ func getWithPattern1() {
|
||||
}
|
||||
}`
|
||||
|
||||
if p, e := gparser.LoadContent([]byte(data), "json"); e != nil {
|
||||
glog.Error(e)
|
||||
} else {
|
||||
fmt.Println("John Score:", p.GetFloat32("users.list.1.score"))
|
||||
}
|
||||
if p, e := gparser.LoadContent([]byte(data), "json"); e != nil {
|
||||
glog.Error(e)
|
||||
} else {
|
||||
fmt.Println("John Score:", p.GetFloat32("users.list.1.score"))
|
||||
}
|
||||
}
|
||||
|
||||
func getWithPattern2() {
|
||||
data :=
|
||||
`<?xml version="1.0" encoding="UTF-8"?>
|
||||
data :=
|
||||
`<?xml version="1.0" encoding="UTF-8"?>
|
||||
<note>
|
||||
<to>Tove</to>
|
||||
<from>Jani</from>
|
||||
@ -35,32 +35,32 @@ func getWithPattern2() {
|
||||
<body>Don't forget me this weekend!</body>
|
||||
</note>`
|
||||
|
||||
if p, e := gparser.LoadContent([]byte(data), "xml"); e != nil {
|
||||
glog.Error(e)
|
||||
} else {
|
||||
fmt.Println("Heading:", p.GetString("note.heading"))
|
||||
}
|
||||
if p, e := gparser.LoadContent([]byte(data), "xml"); e != nil {
|
||||
glog.Error(e)
|
||||
} else {
|
||||
fmt.Println("Heading:", p.GetString("note.heading"))
|
||||
}
|
||||
}
|
||||
|
||||
// 当键名存在"."号时,检索优先级:键名->层级,因此不会引起歧义
|
||||
func multiDots1() {
|
||||
data :=
|
||||
`{
|
||||
data :=
|
||||
`{
|
||||
"users" : {
|
||||
"count" : 100
|
||||
},
|
||||
"users.count" : 101
|
||||
}`
|
||||
if p, e := gparser.LoadContent([]byte(data), "json"); e != nil {
|
||||
glog.Error(e)
|
||||
} else {
|
||||
fmt.Println("Users Count:", p.Get("users.count"))
|
||||
}
|
||||
if p, e := gparser.LoadContent([]byte(data), "json"); e != nil {
|
||||
glog.Error(e)
|
||||
} else {
|
||||
fmt.Println("Users Count:", p.Get("users.count"))
|
||||
}
|
||||
}
|
||||
|
||||
func multiDots2() {
|
||||
data :=
|
||||
`{
|
||||
data :=
|
||||
`{
|
||||
"users" : {
|
||||
"count" : {
|
||||
"type1" : 1,
|
||||
@ -69,150 +69,148 @@ func multiDots2() {
|
||||
"count.type1" : 100
|
||||
}
|
||||
}`
|
||||
if p, e := gparser.LoadContent([]byte(data), "json"); e != nil {
|
||||
glog.Error(e)
|
||||
} else {
|
||||
fmt.Println("Users Count:", p.Get("users.count.type1"))
|
||||
fmt.Println("Users Count:", p.Get("users.count.type2"))
|
||||
}
|
||||
if p, e := gparser.LoadContent([]byte(data), "json"); e != nil {
|
||||
glog.Error(e)
|
||||
} else {
|
||||
fmt.Println("Users Count:", p.Get("users.count.type1"))
|
||||
fmt.Println("Users Count:", p.Get("users.count.type2"))
|
||||
}
|
||||
}
|
||||
|
||||
// 设置数据
|
||||
func set1() {
|
||||
data :=
|
||||
`<?xml version="1.0" encoding="UTF-8"?>
|
||||
data :=
|
||||
`<?xml version="1.0" encoding="UTF-8"?>
|
||||
<article>
|
||||
<count>10</count>
|
||||
<list><title>gf article1</title><content>gf content1</content></list>
|
||||
<list><title>gf article2</title><content>gf content2</content></list>
|
||||
<list><title>gf article3</title><content>gf content3</content></list>
|
||||
</article>`
|
||||
if p, e := gparser.LoadContent([]byte(data), "xml"); e != nil {
|
||||
glog.Error(e)
|
||||
} else {
|
||||
p.Set("article.list.0", nil)
|
||||
c, _ := p.ToJson()
|
||||
fmt.Println(string(c))
|
||||
// {"article":{"count":"10","list":[{"content":"gf content2","title":"gf article2"},{"content":"gf content3","title":"gf article3"}]}}
|
||||
}
|
||||
if p, e := gparser.LoadContent([]byte(data), "xml"); e != nil {
|
||||
glog.Error(e)
|
||||
} else {
|
||||
p.Set("article.list.0", nil)
|
||||
c, _ := p.ToJson()
|
||||
fmt.Println(string(c))
|
||||
// {"article":{"count":"10","list":[{"content":"gf content2","title":"gf article2"},{"content":"gf content3","title":"gf article3"}]}}
|
||||
}
|
||||
}
|
||||
|
||||
func set2() {
|
||||
data :=
|
||||
`{
|
||||
data :=
|
||||
`{
|
||||
"users" : {
|
||||
"count" : 100
|
||||
}
|
||||
}`
|
||||
if p, e := gparser.LoadContent([]byte(data), "json"); e != nil {
|
||||
glog.Error(e)
|
||||
} else {
|
||||
p.Set("users.count", 1)
|
||||
p.Set("users.list", []string{"John", "小明"})
|
||||
c, _ := p.ToJson()
|
||||
fmt.Println(string(c))
|
||||
}
|
||||
if p, e := gparser.LoadContent([]byte(data), "json"); e != nil {
|
||||
glog.Error(e)
|
||||
} else {
|
||||
p.Set("users.count", 1)
|
||||
p.Set("users.list", []string{"John", "小明"})
|
||||
c, _ := p.ToJson()
|
||||
fmt.Println(string(c))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func makeXml1() {
|
||||
p := gparser.New()
|
||||
p.Set("name", "john")
|
||||
p.Set("age", 18)
|
||||
p.Set("scores", map[string]int{
|
||||
"语文" : 100,
|
||||
"数学" : 100,
|
||||
"英语" : 100,
|
||||
})
|
||||
c, _ := p.ToXmlIndent("simple-xml")
|
||||
fmt.Println(string(c))
|
||||
p := gparser.New()
|
||||
p.Set("name", "john")
|
||||
p.Set("age", 18)
|
||||
p.Set("scores", map[string]int{
|
||||
"语文": 100,
|
||||
"数学": 100,
|
||||
"英语": 100,
|
||||
})
|
||||
c, _ := p.ToXmlIndent("simple-xml")
|
||||
fmt.Println(string(c))
|
||||
}
|
||||
|
||||
func makeJson1() {
|
||||
type Order struct {
|
||||
Id int `json:"id"`
|
||||
Price float32 `json:"price"`
|
||||
}
|
||||
p := gparser.New()
|
||||
p.Set("orders.list.0", Order{1, 100})
|
||||
p.Set("orders.list.1", Order{2, 666})
|
||||
p.Set("orders.list.2", Order{3, 999.99})
|
||||
fmt.Println("Order 1 Price:", p.Get("orders.list.1.price"))
|
||||
c, _ := p.ToJson()
|
||||
fmt.Println(string(c))
|
||||
type Order struct {
|
||||
Id int `json:"id"`
|
||||
Price float32 `json:"price"`
|
||||
}
|
||||
p := gparser.New()
|
||||
p.Set("orders.list.0", Order{1, 100})
|
||||
p.Set("orders.list.1", Order{2, 666})
|
||||
p.Set("orders.list.2", Order{3, 999.99})
|
||||
fmt.Println("Order 1 Price:", p.Get("orders.list.1.price"))
|
||||
c, _ := p.ToJson()
|
||||
fmt.Println(string(c))
|
||||
}
|
||||
|
||||
func makeJson2() {
|
||||
p := gparser.New(map[string]string{
|
||||
"k1" : "v1",
|
||||
"k2" : "v2",
|
||||
})
|
||||
p.Set("k1.1", []int{1,2,3})
|
||||
//p.Set("0.0.1", []int{1,2,3})
|
||||
c, _ := p.ToJson()
|
||||
fmt.Println(string(c))
|
||||
p := gparser.New(map[string]string{
|
||||
"k1": "v1",
|
||||
"k2": "v2",
|
||||
})
|
||||
p.Set("k1.1", []int{1, 2, 3})
|
||||
//p.Set("0.0.1", []int{1,2,3})
|
||||
c, _ := p.ToJson()
|
||||
fmt.Println(string(c))
|
||||
}
|
||||
|
||||
func makeJson3() {
|
||||
p := gparser.New([]string{"a"})
|
||||
p.Set("0.0.0", []int{1,2,3})
|
||||
c, _ := p.ToJson()
|
||||
fmt.Println(string(c))
|
||||
p := gparser.New([]string{"a"})
|
||||
p.Set("0.0.0", []int{1, 2, 3})
|
||||
c, _ := p.ToJson()
|
||||
fmt.Println(string(c))
|
||||
}
|
||||
|
||||
func toStruct1() {
|
||||
type Info struct {
|
||||
Name string
|
||||
Url string
|
||||
}
|
||||
o := Info{}
|
||||
p := gparser.New(map[string]string{
|
||||
"Name" : "gf",
|
||||
"Url" : "https://gitee.com/johng",
|
||||
})
|
||||
p.ToStruct(&o)
|
||||
fmt.Println("Name:", o.Name)
|
||||
fmt.Println("Url :", o.Url)
|
||||
type Info struct {
|
||||
Name string
|
||||
Url string
|
||||
}
|
||||
o := Info{}
|
||||
p := gparser.New(map[string]string{
|
||||
"Name": "gf",
|
||||
"Url": "https://gitee.com/johng",
|
||||
})
|
||||
p.ToStruct(&o)
|
||||
fmt.Println("Name:", o.Name)
|
||||
fmt.Println("Url :", o.Url)
|
||||
}
|
||||
|
||||
func convert() {
|
||||
p := gparser.New(map[string]string{
|
||||
"name" : "gf",
|
||||
"site" : "https://gitee.com/johng",
|
||||
})
|
||||
c, _ := p.ToJson()
|
||||
fmt.Println("JSON:")
|
||||
fmt.Println(string(c))
|
||||
fmt.Println("======================")
|
||||
p := gparser.New(map[string]string{
|
||||
"name": "gf",
|
||||
"site": "https://gitee.com/johng",
|
||||
})
|
||||
c, _ := p.ToJson()
|
||||
fmt.Println("JSON:")
|
||||
fmt.Println(string(c))
|
||||
fmt.Println("======================")
|
||||
|
||||
fmt.Println("XML:")
|
||||
c, _ = p.ToXmlIndent()
|
||||
fmt.Println(string(c))
|
||||
fmt.Println("======================")
|
||||
fmt.Println("XML:")
|
||||
c, _ = p.ToXmlIndent()
|
||||
fmt.Println(string(c))
|
||||
fmt.Println("======================")
|
||||
|
||||
fmt.Println("YAML:")
|
||||
c, _ = p.ToYaml()
|
||||
fmt.Println(string(c))
|
||||
fmt.Println("======================")
|
||||
fmt.Println("YAML:")
|
||||
c, _ = p.ToYaml()
|
||||
fmt.Println(string(c))
|
||||
fmt.Println("======================")
|
||||
|
||||
fmt.Println("TOML:")
|
||||
c, _ = p.ToToml()
|
||||
fmt.Println(string(c))
|
||||
fmt.Println("TOML:")
|
||||
c, _ = p.ToToml()
|
||||
fmt.Println(string(c))
|
||||
|
||||
}
|
||||
|
||||
func remove1() {
|
||||
p := gparser.New(map[string]string{
|
||||
"k1" : "v1",
|
||||
"k2" : "v2",
|
||||
})
|
||||
p.Set("0.0.0.0.0.0.0.0", []int{1,2,3})
|
||||
p.Remove("0.0")
|
||||
c, _ := p.ToJson()
|
||||
fmt.Println(string(c))
|
||||
p := gparser.New(map[string]string{
|
||||
"k1": "v1",
|
||||
"k2": "v2",
|
||||
})
|
||||
p.Set("0.0.0.0.0.0.0.0", []int{1, 2, 3})
|
||||
p.Remove("0.0")
|
||||
c, _ := p.ToJson()
|
||||
fmt.Println(string(c))
|
||||
}
|
||||
|
||||
|
||||
func main() {
|
||||
toStruct1()
|
||||
}
|
||||
toStruct1()
|
||||
}
|
||||
|
||||
@ -1,25 +1,25 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
)
|
||||
|
||||
func init() {
|
||||
s := g.Server()
|
||||
s.BindHandler("/apple", Apple)
|
||||
s.BindHandler("/pen", Pen)
|
||||
s.BindHandler("/apple-pen", ApplePen)
|
||||
s := g.Server()
|
||||
s.BindHandler("/apple", Apple)
|
||||
s.BindHandler("/pen", Pen)
|
||||
s.BindHandler("/apple-pen", ApplePen)
|
||||
}
|
||||
|
||||
func Apple(r *ghttp.Request) {
|
||||
r.Response.Write("Apple")
|
||||
r.Response.Write("Apple")
|
||||
}
|
||||
|
||||
func Pen(r *ghttp.Request) {
|
||||
r.Response.Write("Pen")
|
||||
r.Response.Write("Pen")
|
||||
}
|
||||
|
||||
func ApplePen(r *ghttp.Request) {
|
||||
r.Response.Write("Apple-Pen")
|
||||
}
|
||||
r.Response.Write("Apple-Pen")
|
||||
}
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
)
|
||||
|
||||
type Order struct { }
|
||||
type Order struct{}
|
||||
|
||||
func init() {
|
||||
g.Server().BindObject("/{.struct}-{.method}", new(Order))
|
||||
g.Server().BindObject("/{.struct}-{.method}", new(Order))
|
||||
}
|
||||
|
||||
func (o *Order) List(r *ghttp.Request) {
|
||||
r.Response.Write("List")
|
||||
r.Response.Write("List")
|
||||
}
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g/frame/gins"
|
||||
"github.com/gogf/gf/g/frame/gins"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
)
|
||||
|
||||
func init() {
|
||||
ghttp.GetServer().BindHandler("/config", func (r *ghttp.Request) {
|
||||
r.Response.Write(gins.Config().GetString("database.default.0.host"))
|
||||
})
|
||||
ghttp.GetServer().BindHandler("/config", func(r *ghttp.Request) {
|
||||
r.Response.Write(gins.Config().GetString("database.default.0.host"))
|
||||
})
|
||||
}
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/os/gtime"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g/os/gtime"
|
||||
)
|
||||
|
||||
func init() {
|
||||
ghttp.GetServer().BindHandler("/cookie", Cookie)
|
||||
ghttp.GetServer().BindHandler("/cookie", Cookie)
|
||||
}
|
||||
|
||||
func Cookie(r *ghttp.Request) {
|
||||
datetime := r.Cookie.Get("datetime")
|
||||
r.Cookie.Set("datetime", gtime.Datetime())
|
||||
r.Response.Write("datetime:" + datetime)
|
||||
}
|
||||
datetime := r.Cookie.Get("datetime")
|
||||
r.Cookie.Set("datetime", gtime.Datetime())
|
||||
r.Response.Write("datetime:" + datetime)
|
||||
}
|
||||
|
||||
@ -1,21 +1,20 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
)
|
||||
|
||||
type ControllerDomain struct {}
|
||||
type ControllerDomain struct{}
|
||||
|
||||
// 初始化控制器对象,并绑定操作到Web Server
|
||||
func init() {
|
||||
// 只有localhost域名下才能访问该对象,
|
||||
// 对应URL为:http://localhost:8199/test/show
|
||||
// 通过该地址将无法访问到内容:http://127.0.0.1:8199/test/show
|
||||
ghttp.GetServer().Domain("localhost").BindObject("/domain", &ControllerDomain{})
|
||||
// 只有localhost域名下才能访问该对象,
|
||||
// 对应URL为:http://localhost:8199/test/show
|
||||
// 通过该地址将无法访问到内容:http://127.0.0.1:8199/test/show
|
||||
ghttp.GetServer().Domain("localhost").BindObject("/domain", &ControllerDomain{})
|
||||
}
|
||||
|
||||
// 用于对象映射
|
||||
func (d *ControllerDomain) Show(r *ghttp.Request) {
|
||||
r.Response.Write("It's show time bibi!")
|
||||
r.Response.Write("It's show time bibi!")
|
||||
}
|
||||
|
||||
|
||||
@ -1,24 +1,24 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g/frame/gmvc"
|
||||
"github.com/gogf/gf/g/frame/gmvc"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
)
|
||||
|
||||
type ControllerExit struct {
|
||||
gmvc.Controller
|
||||
gmvc.Controller
|
||||
}
|
||||
|
||||
func (c *ControllerExit) Init(r *ghttp.Request) {
|
||||
c.Controller.Init(r)
|
||||
c.Response.Write("exit, it will not print \"show\"")
|
||||
c.Request.Exit()
|
||||
c.Controller.Init(r)
|
||||
c.Response.Write("exit, it will not print \"show\"")
|
||||
c.Request.Exit()
|
||||
}
|
||||
|
||||
func (c *ControllerExit) Show() {
|
||||
c.Response.Write("show")
|
||||
c.Response.Write("show")
|
||||
}
|
||||
|
||||
func init() {
|
||||
ghttp.GetServer().BindController("/exit", &ControllerExit{})
|
||||
ghttp.GetServer().BindController("/exit", &ControllerExit{})
|
||||
}
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"fmt"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
)
|
||||
|
||||
func Form(r *ghttp.Request) {
|
||||
fmt.Println(r.GetPostMap())
|
||||
fmt.Println(r.GetPostString("name"))
|
||||
fmt.Println(r.GetPostString("age"))
|
||||
fmt.Println(r.GetPostMap())
|
||||
fmt.Println(r.GetPostString("name"))
|
||||
fmt.Println(r.GetPostString("age"))
|
||||
|
||||
}
|
||||
|
||||
func FormShow(r *ghttp.Request) {
|
||||
r.Response.Write(`
|
||||
r.Response.Write(`
|
||||
<html>
|
||||
<head>
|
||||
<title>表单提交</title>
|
||||
@ -30,6 +30,6 @@ func FormShow(r *ghttp.Request) {
|
||||
}
|
||||
|
||||
func init() {
|
||||
ghttp.GetServer().BindHandler("/form", Form)
|
||||
ghttp.GetServer().BindHandler("/form/show", FormShow)
|
||||
}
|
||||
ghttp.GetServer().BindHandler("/form", Form)
|
||||
ghttp.GetServer().BindHandler("/form/show", FormShow)
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ package demo
|
||||
import "github.com/gogf/gf/g/net/ghttp"
|
||||
|
||||
func init() {
|
||||
ghttp.GetServer().BindHandler("/", func(r *ghttp.Request){
|
||||
r.Response.Write("Hello World!")
|
||||
})
|
||||
}
|
||||
ghttp.GetServer().BindHandler("/", func(r *ghttp.Request) {
|
||||
r.Response.Write("Hello World!")
|
||||
})
|
||||
}
|
||||
|
||||
@ -1,33 +1,30 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/frame/gmvc"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/frame/gmvc"
|
||||
)
|
||||
|
||||
type Method struct {
|
||||
gmvc.Controller
|
||||
gmvc.Controller
|
||||
}
|
||||
|
||||
func init() {
|
||||
// 第三个参数指定主要注册的方法,其他方法不注册,方法名称会自动追加到给定路由后面,构成新路由
|
||||
// 以下注册会中注册两个新路由: /method/name, /method/age
|
||||
g.Server().BindController("/method", new(Method), "Name, Age")
|
||||
// 绑定路由到指定的方法执行,以下注册只会注册一个路由: /method-name
|
||||
g.Server().BindControllerMethod("/method-name", new(Method), "Name")
|
||||
// 第三个参数指定主要注册的方法,其他方法不注册,方法名称会自动追加到给定路由后面,构成新路由
|
||||
// 以下注册会中注册两个新路由: /method/name, /method/age
|
||||
g.Server().BindController("/method", new(Method), "Name, Age")
|
||||
// 绑定路由到指定的方法执行,以下注册只会注册一个路由: /method-name
|
||||
g.Server().BindControllerMethod("/method-name", new(Method), "Name")
|
||||
}
|
||||
|
||||
func (c *Method) Name() {
|
||||
c.Response.Write("John")
|
||||
c.Response.Write("John")
|
||||
}
|
||||
|
||||
func (c *Method) Age() {
|
||||
c.Response.Write("18")
|
||||
c.Response.Write("18")
|
||||
}
|
||||
|
||||
func (c *Method) Info() {
|
||||
c.Response.Write("Info")
|
||||
c.Response.Write("Info")
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,21 +1,20 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
)
|
||||
|
||||
type Object struct {}
|
||||
type Object struct{}
|
||||
|
||||
func init() {
|
||||
g.Server().BindObject("/object", new(Object))
|
||||
g.Server().BindObject("/object", new(Object))
|
||||
}
|
||||
|
||||
func (o *Object) Index(r *ghttp.Request) {
|
||||
r.Response.Write("object index")
|
||||
r.Response.Write("object index")
|
||||
}
|
||||
|
||||
func (o *Object) Show(r *ghttp.Request) {
|
||||
r.Response.Write("object show")
|
||||
r.Response.Write("object show")
|
||||
}
|
||||
|
||||
|
||||
@ -1,33 +1,31 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
)
|
||||
|
||||
type ObjectMethod struct {}
|
||||
type ObjectMethod struct{}
|
||||
|
||||
func init() {
|
||||
obj := &ObjectMethod{}
|
||||
g.Server().BindObject("/object-method", obj, "Show1, Show2, Show3")
|
||||
g.Server().BindObjectMethod("/object-method-show1", obj, "Show1")
|
||||
g.Server().Domain("localhost").BindObject("/object-method", obj, "Show4")
|
||||
obj := &ObjectMethod{}
|
||||
g.Server().BindObject("/object-method", obj, "Show1, Show2, Show3")
|
||||
g.Server().BindObjectMethod("/object-method-show1", obj, "Show1")
|
||||
g.Server().Domain("localhost").BindObject("/object-method", obj, "Show4")
|
||||
}
|
||||
|
||||
func (o *ObjectMethod) Show1(r *ghttp.Request) {
|
||||
r.Response.Write("show 1")
|
||||
r.Response.Write("show 1")
|
||||
}
|
||||
|
||||
func (o *ObjectMethod) Show2(r *ghttp.Request) {
|
||||
r.Response.Write("show 2")
|
||||
r.Response.Write("show 2")
|
||||
}
|
||||
|
||||
func (o *ObjectMethod) Show3(r *ghttp.Request) {
|
||||
r.Response.Write("show 3")
|
||||
r.Response.Write("show 3")
|
||||
}
|
||||
|
||||
func (o *ObjectMethod) Show4(r *ghttp.Request) {
|
||||
r.Response.Write("show 4")
|
||||
r.Response.Write("show 4")
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -3,28 +3,28 @@ package demo
|
||||
import "github.com/gogf/gf/g/net/ghttp"
|
||||
|
||||
// 测试绑定对象
|
||||
type ObjectRest struct {}
|
||||
type ObjectRest struct{}
|
||||
|
||||
func init() {
|
||||
ghttp.GetServer().BindObjectRest("/object-rest", &ObjectRest{})
|
||||
ghttp.GetServer().BindObjectRest("/object-rest", &ObjectRest{})
|
||||
}
|
||||
|
||||
// RESTFul - GET
|
||||
func (o *ObjectRest) Get(r *ghttp.Request) {
|
||||
r.Response.Write("RESTFul HTTP Method GET")
|
||||
r.Response.Write("RESTFul HTTP Method GET")
|
||||
}
|
||||
|
||||
// RESTFul - POST
|
||||
func (c *ObjectRest) Post(r *ghttp.Request) {
|
||||
r.Response.Write("RESTFul HTTP Method POST")
|
||||
r.Response.Write("RESTFul HTTP Method POST")
|
||||
}
|
||||
|
||||
// RESTFul - DELETE
|
||||
func (c *ObjectRest) Delete(r *ghttp.Request) {
|
||||
r.Response.Write("RESTFul HTTP Method DELETE")
|
||||
r.Response.Write("RESTFul HTTP Method DELETE")
|
||||
}
|
||||
|
||||
// 该方法无法映射,将会无法访问到
|
||||
func (c *ObjectRest) Hello(r *ghttp.Request) {
|
||||
r.Response.Write("Hello")
|
||||
}
|
||||
r.Response.Write("Hello")
|
||||
}
|
||||
|
||||
@ -1,25 +1,25 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
)
|
||||
|
||||
type Product struct {
|
||||
total int
|
||||
total int
|
||||
}
|
||||
|
||||
func init() {
|
||||
p := &Product{}
|
||||
g.Server().BindHandler("/product/total", p.Total)
|
||||
g.Server().BindHandler("/product/list/{page}.html", p.List)
|
||||
p := &Product{}
|
||||
g.Server().BindHandler("/product/total", p.Total)
|
||||
g.Server().BindHandler("/product/list/{page}.html", p.List)
|
||||
}
|
||||
|
||||
func (p *Product) Total(r *ghttp.Request) {
|
||||
p.total++
|
||||
r.Response.Write("total: ", p.total)
|
||||
p.total++
|
||||
r.Response.Write("total: ", p.total)
|
||||
}
|
||||
|
||||
func (p *Product) List(r *ghttp.Request) {
|
||||
r.Response.Write("page: ", r.Get("page"))
|
||||
r.Response.Write("page: ", r.Get("page"))
|
||||
}
|
||||
|
||||
@ -1,37 +1,34 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/frame/gmvc"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/frame/gmvc"
|
||||
)
|
||||
|
||||
type Rest struct {
|
||||
gmvc.Controller
|
||||
gmvc.Controller
|
||||
}
|
||||
|
||||
func init() {
|
||||
g.Server().BindControllerRest("/rest", &Rest{})
|
||||
g.Server().BindControllerRest("/rest", &Rest{})
|
||||
}
|
||||
|
||||
// RESTFul - GET
|
||||
func (c *Rest) Get() {
|
||||
c.Response.Write("RESTFul HTTP Method GET")
|
||||
c.Response.Write("RESTFul HTTP Method GET")
|
||||
}
|
||||
|
||||
// RESTFul - POST
|
||||
func (c *Rest) Post() {
|
||||
c.Response.Write("RESTFul HTTP Method POST")
|
||||
c.Response.Write("RESTFul HTTP Method POST")
|
||||
}
|
||||
|
||||
// RESTFul - DELETE
|
||||
func (c *Rest) Delete() {
|
||||
c.Response.Write("RESTFul HTTP Method DELETE")
|
||||
c.Response.Write("RESTFul HTTP Method DELETE")
|
||||
}
|
||||
|
||||
// 该方法无法映射,将会无法访问到
|
||||
func (c *Rest) Hello() {
|
||||
c.Response.Write("Hello")
|
||||
c.Response.Write("Hello")
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,19 +1,18 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/frame/gmvc"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/frame/gmvc"
|
||||
)
|
||||
|
||||
type ControllerRule struct {
|
||||
gmvc.Controller
|
||||
gmvc.Controller
|
||||
}
|
||||
|
||||
func init() {
|
||||
g.Server().BindController("/rule/{method}/:name", &ControllerRule{})
|
||||
g.Server().BindController("/rule/{method}/:name", &ControllerRule{})
|
||||
}
|
||||
|
||||
func (c *ControllerRule) Show() {
|
||||
c.Response.Write(c.Request.Get("name"))
|
||||
c.Response.Write(c.Request.Get("name"))
|
||||
}
|
||||
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func init() {
|
||||
ghttp.GetServer().BindHandler("/session", Session)
|
||||
ghttp.GetServer().BindHandler("/session", Session)
|
||||
}
|
||||
|
||||
func Session(r *ghttp.Request) {
|
||||
id := r.Session.GetInt("id")
|
||||
r.Session.Set("id", id + 1)
|
||||
r.Response.Write("id:" + strconv.Itoa(id))
|
||||
}
|
||||
id := r.Session.GetInt("id")
|
||||
r.Session.Set("id", id+1)
|
||||
r.Response.Write("id:" + strconv.Itoa(id))
|
||||
}
|
||||
|
||||
@ -1,28 +1,23 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g/frame/gmvc"
|
||||
"github.com/gogf/gf/g/frame/gmvc"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
)
|
||||
|
||||
type ControllerTemplate struct {
|
||||
gmvc.Controller
|
||||
gmvc.Controller
|
||||
}
|
||||
|
||||
func (c *ControllerTemplate) Info() {
|
||||
c.View.Assign("name", "john")
|
||||
c.View.Assigns(map[string]interface{}{
|
||||
"age" : 18,
|
||||
"score" : 100,
|
||||
})
|
||||
c.View.Display("view/user/index.tpl")
|
||||
c.View.Assign("name", "john")
|
||||
c.View.Assigns(map[string]interface{}{
|
||||
"age": 18,
|
||||
"score": 100,
|
||||
})
|
||||
c.View.Display("view/user/index.tpl")
|
||||
}
|
||||
|
||||
func init() {
|
||||
ghttp.GetServer().BindController("/template", &ControllerTemplate{})
|
||||
ghttp.GetServer().BindController("/template", &ControllerTemplate{})
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
)
|
||||
|
||||
func init() {
|
||||
ghttp.GetServer().BindHandler("/template2", func(r *ghttp.Request){
|
||||
content, _ := g.View().Parse("index.tpl", map[string]interface{}{
|
||||
"id" : 123,
|
||||
"name" : "john",
|
||||
})
|
||||
r.Response.Write(content)
|
||||
})
|
||||
}
|
||||
ghttp.GetServer().BindHandler("/template2", func(r *ghttp.Request) {
|
||||
content, _ := g.View().Parse("index.tpl", map[string]interface{}{
|
||||
"id": 123,
|
||||
"name": "john",
|
||||
})
|
||||
r.Response.Write(content)
|
||||
})
|
||||
}
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g/frame/gins"
|
||||
"github.com/gogf/gf/g/frame/gins"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gins.View().SetPath("/home/www/template/")
|
||||
ghttp.GetServer().BindHandler("/template3", func(r *ghttp.Request){
|
||||
content, _ := gins.View().Parse("index.tpl", map[string]interface{}{
|
||||
"id" : 123,
|
||||
"name" : "john",
|
||||
})
|
||||
r.Response.Write(content)
|
||||
})
|
||||
}
|
||||
gins.View().SetPath("/home/www/template/")
|
||||
ghttp.GetServer().BindHandler("/template3", func(r *ghttp.Request) {
|
||||
content, _ := gins.View().Parse("index.tpl", map[string]interface{}{
|
||||
"id": 123,
|
||||
"name": "john",
|
||||
})
|
||||
r.Response.Write(content)
|
||||
})
|
||||
}
|
||||
|
||||
@ -1,25 +1,25 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/os/gfile"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g/os/gfile"
|
||||
)
|
||||
|
||||
func Upload(r *ghttp.Request) {
|
||||
if f, h, e := r.FormFile("upload-file"); e == nil {
|
||||
defer f.Close()
|
||||
fname := gfile.Basename(h.Filename)
|
||||
buffer := make([]byte, h.Size)
|
||||
f.Read(buffer)
|
||||
gfile.PutBinContents("/tmp/" + fname, buffer)
|
||||
r.Response.Write(fname + " uploaded successly")
|
||||
} else {
|
||||
r.Response.Write(e.Error())
|
||||
}
|
||||
if f, h, e := r.FormFile("upload-file"); e == nil {
|
||||
defer f.Close()
|
||||
fname := gfile.Basename(h.Filename)
|
||||
buffer := make([]byte, h.Size)
|
||||
f.Read(buffer)
|
||||
gfile.PutBinContents("/tmp/"+fname, buffer)
|
||||
r.Response.Write(fname + " uploaded successly")
|
||||
} else {
|
||||
r.Response.Write(e.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func UploadShow(r *ghttp.Request) {
|
||||
r.Response.Write(`
|
||||
r.Response.Write(`
|
||||
<html>
|
||||
<head>
|
||||
<title>上传文件</title>
|
||||
@ -35,6 +35,6 @@ func UploadShow(r *ghttp.Request) {
|
||||
}
|
||||
|
||||
func init() {
|
||||
ghttp.GetServer().BindHandler("/upload", Upload)
|
||||
ghttp.GetServer().BindHandler("/upload/show", UploadShow)
|
||||
}
|
||||
ghttp.GetServer().BindHandler("/upload", Upload)
|
||||
ghttp.GetServer().BindHandler("/upload/show", UploadShow)
|
||||
}
|
||||
|
||||
@ -1,33 +1,29 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/frame/gmvc"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/frame/gmvc"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
gmvc.Controller
|
||||
gmvc.Controller
|
||||
}
|
||||
|
||||
func init() {
|
||||
s := g.Server()
|
||||
s.BindController("/user", new(User))
|
||||
s.BindController("/user/{.method}/{uid}", new(User), "Info")
|
||||
s.BindController("/user/{.method}/{page}.html", new(User), "List")
|
||||
s := g.Server()
|
||||
s.BindController("/user", new(User))
|
||||
s.BindController("/user/{.method}/{uid}", new(User), "Info")
|
||||
s.BindController("/user/{.method}/{page}.html", new(User), "List")
|
||||
}
|
||||
|
||||
func (u *User) Index() {
|
||||
u.Response.Write("User")
|
||||
u.Response.Write("User")
|
||||
}
|
||||
|
||||
func (u *User) Info() {
|
||||
u.Response.Write("Info - Uid: ", u.Request.Get("uid"))
|
||||
u.Response.Write("Info - Uid: ", u.Request.Get("uid"))
|
||||
}
|
||||
|
||||
func (u *User) List() {
|
||||
u.Response.Write("List - Page: ", u.Request.Get("page"))
|
||||
u.Response.Write("List - Page: ", u.Request.Get("page"))
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
package stats
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
)
|
||||
|
||||
var (
|
||||
total int
|
||||
total int
|
||||
)
|
||||
|
||||
func init() {
|
||||
g.Server().BindHandler("/stats/total", showTotal)
|
||||
g.Server().BindHandler("/stats/total", showTotal)
|
||||
}
|
||||
|
||||
func showTotal(r *ghttp.Request) {
|
||||
total++
|
||||
r.Response.Write("total:", total)
|
||||
total++
|
||||
r.Response.Write("total:", total)
|
||||
}
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g"
|
||||
_ "github.com/gogf/gf/geg/frame/mvc/controller/demo"
|
||||
_ "github.com/gogf/gf/geg/frame/mvc/controller/stats"
|
||||
"github.com/gogf/gf/g"
|
||||
_ "github.com/gogf/gf/geg/frame/mvc/controller/demo"
|
||||
_ "github.com/gogf/gf/geg/frame/mvc/controller/stats"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
//g.Server().SetDumpRouteMap(false)
|
||||
g.Server().SetPort(8199)
|
||||
g.Server().Run()
|
||||
//g.Server().SetDumpRouteMap(false)
|
||||
g.Server().SetPort(8199)
|
||||
g.Server().Run()
|
||||
|
||||
}
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/os/glog"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g/os/glog"
|
||||
)
|
||||
|
||||
func main() {
|
||||
c := ghttp.NewClient()
|
||||
c.SetHeader("Cookie", "name=john; score=100")
|
||||
if r, e := c.Get("http://127.0.0.1:8199/"); e != nil {
|
||||
glog.Error(e)
|
||||
} else {
|
||||
fmt.Println(string(r.ReadAll()))
|
||||
}
|
||||
c := ghttp.NewClient()
|
||||
c.SetHeader("Cookie", "name=john; score=100")
|
||||
if r, e := c.Get("http://127.0.0.1:8199/"); e != nil {
|
||||
glog.Error(e)
|
||||
} else {
|
||||
fmt.Println(string(r.ReadAll()))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := g.Server()
|
||||
s.BindHandler("/", func(r *ghttp.Request){
|
||||
r.Response.Writeln(r.Cookie.Map())
|
||||
})
|
||||
s.SetPort(8199)
|
||||
s.Run()
|
||||
}
|
||||
s := g.Server()
|
||||
s.BindHandler("/", func(r *ghttp.Request) {
|
||||
r.Response.Writeln(r.Cookie.Map())
|
||||
})
|
||||
s.SetPort(8199)
|
||||
s.Run()
|
||||
}
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
c := ghttp.NewClient()
|
||||
r, _ := c.Get("http://baidu.com")
|
||||
fmt.Println(r.StatusCode)
|
||||
c := ghttp.NewClient()
|
||||
r, _ := c.Get("http://baidu.com")
|
||||
fmt.Println(r.StatusCode)
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user