mirror of
https://gitee.com/johng/gf
synced 2026-06-06 02:25:47 +08:00
Merge branch 'v2_release' into develop
This commit is contained in:
@ -17,25 +17,11 @@ func (v *Var) Struct(pointer interface{}, mapping ...map[string]string) error {
|
||||
return gconv.Struct(v.Val(), pointer, mapping...)
|
||||
}
|
||||
|
||||
// StructDeep maps value of `v` to `pointer` recursively.
|
||||
// The parameter `pointer` should be a pointer to a struct instance.
|
||||
// The parameter `mapping` is used to specify the key-to-attribute mapping rules.
|
||||
// Deprecated, use Struct instead.
|
||||
func (v *Var) StructDeep(pointer interface{}, mapping ...map[string]string) error {
|
||||
return gconv.StructDeep(v.Val(), pointer, mapping...)
|
||||
}
|
||||
|
||||
// Structs converts and returns `v` as given struct slice.
|
||||
func (v *Var) Structs(pointer interface{}, mapping ...map[string]string) error {
|
||||
return gconv.Structs(v.Val(), pointer, mapping...)
|
||||
}
|
||||
|
||||
// StructsDeep converts and returns `v` as given struct slice recursively.
|
||||
// Deprecated, use Struct instead.
|
||||
func (v *Var) StructsDeep(pointer interface{}, mapping ...map[string]string) error {
|
||||
return gconv.StructsDeep(v.Val(), pointer, mapping...)
|
||||
}
|
||||
|
||||
// Scan automatically calls Struct or Structs function according to the type of parameter
|
||||
// `pointer` to implement the converting.
|
||||
//
|
||||
@ -44,14 +30,3 @@ func (v *Var) StructsDeep(pointer interface{}, mapping ...map[string]string) err
|
||||
func (v *Var) Scan(pointer interface{}, mapping ...map[string]string) error {
|
||||
return gconv.Scan(v.Val(), pointer, mapping...)
|
||||
}
|
||||
|
||||
// ScanDeep automatically calls StructDeep or StructsDeep function according to the type of
|
||||
// parameter `pointer` to implement the converting.
|
||||
//
|
||||
// It calls function StructDeep if `pointer` is type of *struct/**struct to do the converting.
|
||||
// It calls function StructsDeep if `pointer` is type of *[]struct/*[]*struct to do the converting.
|
||||
//
|
||||
// Deprecated, use Scan instead.
|
||||
func (v *Var) ScanDeep(pointer interface{}, mapping ...map[string]string) error {
|
||||
return gconv.ScanDeep(v.Val(), pointer, mapping...)
|
||||
}
|
||||
|
||||
@ -33,14 +33,6 @@ type DB interface {
|
||||
// Model creation.
|
||||
// ===========================================================================
|
||||
|
||||
// Table function is deprecated, use Model instead.
|
||||
// The DB interface is designed not only for
|
||||
// relational databases but also for NoSQL databases in the future. The name
|
||||
// "Table" is not proper for that purpose any more.
|
||||
// Also see Core.Table.
|
||||
// Deprecated.
|
||||
Table(tableNameOrStruct ...interface{}) *Model
|
||||
|
||||
// Model creates and returns a new ORM model from given schema.
|
||||
// The parameter `table` can be more than one table names, and also alias name, like:
|
||||
// 1. Model names:
|
||||
|
||||
@ -679,9 +679,9 @@ func (c *Core) writeSqlToLogger(ctx context.Context, sql *Sql) {
|
||||
s := fmt.Sprintf("[%3d ms] [%s] %s%s", sql.End-sql.Start, sql.Group, transactionIdStr, sql.Format)
|
||||
if sql.Error != nil {
|
||||
s += "\nError: " + sql.Error.Error()
|
||||
c.logger.Ctx(ctx).Error(s)
|
||||
c.logger.Error(ctx, s)
|
||||
} else {
|
||||
c.logger.Ctx(ctx).Debug(s)
|
||||
c.logger.Debug(ctx, s)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -217,19 +217,16 @@ func (c *Core) GetGroup() string {
|
||||
}
|
||||
|
||||
// SetDryRun enables/disables the DryRun feature.
|
||||
// Deprecated, use GetConfig instead.
|
||||
func (c *Core) SetDryRun(enabled bool) {
|
||||
c.config.DryRun = enabled
|
||||
}
|
||||
|
||||
// GetDryRun returns the DryRun value.
|
||||
// Deprecated, use GetConfig instead.
|
||||
func (c *Core) GetDryRun() bool {
|
||||
return c.config.DryRun || allDryRun
|
||||
}
|
||||
|
||||
// GetPrefix returns the table prefix string configured.
|
||||
// Deprecated, use GetConfig instead.
|
||||
func (c *Core) GetPrefix() string {
|
||||
return c.config.Prefix
|
||||
}
|
||||
|
||||
@ -76,13 +76,6 @@ const (
|
||||
defaultFields = "*"
|
||||
)
|
||||
|
||||
// Table is alias of Core.Model.
|
||||
// See Core.Model.
|
||||
// Deprecated, use Model instead.
|
||||
func (c *Core) Table(tableNameQueryOrStruct ...interface{}) *Model {
|
||||
return c.db.Model(tableNameQueryOrStruct...)
|
||||
}
|
||||
|
||||
// Model creates and returns a new ORM model from given schema.
|
||||
// The parameter `tableNameQueryOrStruct` can be more than one table names, and also alias name, like:
|
||||
// 1. Model names:
|
||||
|
||||
@ -236,27 +236,6 @@ func (m *Model) WhereOrNotNull(columns ...string) *Model {
|
||||
return model
|
||||
}
|
||||
|
||||
// And adds "AND" condition to the where statement.
|
||||
// Deprecated, use Where instead.
|
||||
func (m *Model) And(where interface{}, args ...interface{}) *Model {
|
||||
model := m.getModel()
|
||||
if model.whereHolder == nil {
|
||||
model.whereHolder = make([]ModelWhereHolder, 0)
|
||||
}
|
||||
model.whereHolder = append(model.whereHolder, ModelWhereHolder{
|
||||
Operator: whereHolderOperatorAnd,
|
||||
Where: where,
|
||||
Args: args,
|
||||
})
|
||||
return model
|
||||
}
|
||||
|
||||
// Or adds "OR" condition to the where statement.
|
||||
// Deprecated, use WhereOr instead.
|
||||
func (m *Model) Or(where interface{}, args ...interface{}) *Model {
|
||||
return m.WhereOr(where, args...)
|
||||
}
|
||||
|
||||
// Group sets the "GROUP BY" statement for the model.
|
||||
func (m *Model) Group(groupBy ...string) *Model {
|
||||
if len(groupBy) == 0 {
|
||||
@ -350,13 +329,6 @@ func (m *Model) Page(page, limit int) *Model {
|
||||
return model
|
||||
}
|
||||
|
||||
// ForPage is alias of Model.Page.
|
||||
// See Model.Page.
|
||||
// Deprecated, use Page instead.
|
||||
func (m *Model) ForPage(page, limit int) *Model {
|
||||
return m.Page(page, limit)
|
||||
}
|
||||
|
||||
// formatCondition formats where arguments of the model and returns a new condition sql and its arguments.
|
||||
// Note that this function does not change any attribute value of the `m`.
|
||||
//
|
||||
|
||||
@ -150,25 +150,6 @@ func (m *Model) appendFieldsExByStr(fieldsEx string) *Model {
|
||||
return m
|
||||
}
|
||||
|
||||
// Filter marks filtering the fields which does not exist in the fields of the operated table.
|
||||
// Note that this function supports only single table operations.
|
||||
// Deprecated, filter feature is automatically enabled from GoFrame v1.16.0, it is so no longer used.
|
||||
func (m *Model) Filter() *Model {
|
||||
if gstr.Contains(m.tables, " ") {
|
||||
panic("function Filter supports only single table operations")
|
||||
}
|
||||
model := m.getModel()
|
||||
model.filter = true
|
||||
return model
|
||||
}
|
||||
|
||||
// FieldsStr retrieves and returns all fields from the table, joined with char ','.
|
||||
// The optional parameter `prefix` specifies the prefix for each field, eg: FieldsStr("u.").
|
||||
// Deprecated, use GetFieldsStr instead.
|
||||
func (m *Model) FieldsStr(prefix ...string) string {
|
||||
return m.GetFieldsStr(prefix...)
|
||||
}
|
||||
|
||||
// GetFieldsStr retrieves and returns all fields from the table, joined with char ','.
|
||||
// The optional parameter `prefix` specifies the prefix for each field, eg: GetFieldsStr("u.").
|
||||
func (m *Model) GetFieldsStr(prefix ...string) string {
|
||||
@ -198,15 +179,6 @@ func (m *Model) GetFieldsStr(prefix ...string) string {
|
||||
return newFields
|
||||
}
|
||||
|
||||
// FieldsExStr retrieves and returns fields which are not in parameter `fields` from the table,
|
||||
// joined with char ','.
|
||||
// The parameter `fields` specifies the fields that are excluded.
|
||||
// The optional parameter `prefix` specifies the prefix for each field, eg: FieldsExStr("id", "u.").
|
||||
// Deprecated, use GetFieldsExStr instead.
|
||||
func (m *Model) FieldsExStr(fields string, prefix ...string) string {
|
||||
return m.GetFieldsExStr(fields, prefix...)
|
||||
}
|
||||
|
||||
// GetFieldsExStr retrieves and returns fields which are not in parameter `fields` from the table,
|
||||
// joined with char ','.
|
||||
// The parameter `fields` specifies the fields that are excluded.
|
||||
|
||||
@ -15,14 +15,6 @@ const (
|
||||
optionOmitNilData // 64
|
||||
)
|
||||
|
||||
// Option adds extra operation option for the model.
|
||||
// Deprecated, use separate operations instead.
|
||||
func (m *Model) Option(option int) *Model {
|
||||
model := m.getModel()
|
||||
model.option = model.option | option
|
||||
return model
|
||||
}
|
||||
|
||||
// OmitEmpty sets optionOmitEmpty option for the model, which automatically filers
|
||||
// the data and where parameters for `empty` values.
|
||||
func (m *Model) OmitEmpty() *Model {
|
||||
|
||||
@ -20,13 +20,6 @@ import (
|
||||
"github.com/gogf/gf/util/gconv"
|
||||
)
|
||||
|
||||
// Select is alias of Model.All.
|
||||
// See Model.All.
|
||||
// Deprecated, use All instead.
|
||||
func (m *Model) Select(where ...interface{}) (Result, error) {
|
||||
return m.All(where...)
|
||||
}
|
||||
|
||||
// All does "SELECT FROM ..." statement for the model.
|
||||
// It retrieves the records from table and returns the result as slice type.
|
||||
// It returns nil if there's no record retrieved with the given conditions from table.
|
||||
@ -197,15 +190,6 @@ func (m *Model) Array(fieldsAndWhere ...interface{}) ([]Value, error) {
|
||||
return all.Array(), nil
|
||||
}
|
||||
|
||||
// Struct retrieves one record from table and converts it into given struct.
|
||||
// The parameter `pointer` should be type of *struct/**struct. If type **struct is given,
|
||||
// it can create the struct internally during converting.
|
||||
//
|
||||
// Deprecated, use Scan instead.
|
||||
func (m *Model) Struct(pointer interface{}, where ...interface{}) error {
|
||||
return m.doStruct(pointer, where...)
|
||||
}
|
||||
|
||||
// Struct retrieves one record from table and converts it into given struct.
|
||||
// The parameter `pointer` should be type of *struct/**struct. If type **struct is given,
|
||||
// it can create the struct internally during converting.
|
||||
@ -242,15 +226,6 @@ func (m *Model) doStruct(pointer interface{}, where ...interface{}) error {
|
||||
return model.doWithScanStruct(pointer)
|
||||
}
|
||||
|
||||
// Structs retrieves records from table and converts them into given struct slice.
|
||||
// The parameter `pointer` should be type of *[]struct/*[]*struct. It can create and fill the struct
|
||||
// slice internally during converting.
|
||||
//
|
||||
// Deprecated, use Scan instead.
|
||||
func (m *Model) Structs(pointer interface{}, where ...interface{}) error {
|
||||
return m.doStructs(pointer, where...)
|
||||
}
|
||||
|
||||
// Structs retrieves records from table and converts them into given struct slice.
|
||||
// The parameter `pointer` should be type of *[]struct/*[]*struct. It can create and fill the struct
|
||||
// slice internally during converting.
|
||||
|
||||
@ -9,21 +9,21 @@ package gdb
|
||||
import (
|
||||
"database/sql"
|
||||
"github.com/gogf/gf/container/gmap"
|
||||
"github.com/gogf/gf/encoding/gparser"
|
||||
"github.com/gogf/gf/encoding/gjson"
|
||||
"github.com/gogf/gf/internal/empty"
|
||||
"github.com/gogf/gf/util/gconv"
|
||||
)
|
||||
|
||||
// Json converts `r` to JSON format content.
|
||||
func (r Record) Json() string {
|
||||
content, _ := gparser.VarToJson(r.Map())
|
||||
return string(content)
|
||||
content, _ := gjson.New(r.Map()).ToJsonString()
|
||||
return content
|
||||
}
|
||||
|
||||
// Xml converts `r` to XML format content.
|
||||
func (r Record) Xml(rootTag ...string) string {
|
||||
content, _ := gparser.VarToXml(r.Map(), rootTag...)
|
||||
return string(content)
|
||||
content, _ := gjson.New(r.Map()).ToXmlString(rootTag...)
|
||||
return content
|
||||
}
|
||||
|
||||
// Map converts `r` to map[string]interface{}.
|
||||
|
||||
@ -8,7 +8,7 @@ package gdb
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/container/gvar"
|
||||
"github.com/gogf/gf/encoding/gparser"
|
||||
"github.com/gogf/gf/encoding/gjson"
|
||||
"github.com/gogf/gf/util/gconv"
|
||||
"math"
|
||||
)
|
||||
@ -51,14 +51,14 @@ func (r Result) Chunk(size int) []Result {
|
||||
|
||||
// Json converts `r` to JSON format content.
|
||||
func (r Result) Json() string {
|
||||
content, _ := gparser.VarToJson(r.List())
|
||||
return string(content)
|
||||
content, _ := gjson.New(r.List()).ToJsonString()
|
||||
return content
|
||||
}
|
||||
|
||||
// Xml converts `r` to XML format content.
|
||||
func (r Result) Xml(rootTag ...string) string {
|
||||
content, _ := gparser.VarToXml(r.List(), rootTag...)
|
||||
return string(content)
|
||||
content, _ := gjson.New(r.List()).ToXmlString(rootTag...)
|
||||
return content
|
||||
}
|
||||
|
||||
// List converts `r` to a List.
|
||||
|
||||
@ -10,7 +10,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/container/garray"
|
||||
"github.com/gogf/gf/encoding/gparser"
|
||||
"github.com/gogf/gf/text/gstr"
|
||||
"testing"
|
||||
"time"
|
||||
@ -210,7 +209,7 @@ func Test_DB_Insert_WithStructAndSliceAttribute(t *testing.T) {
|
||||
t.AssertNil(err)
|
||||
t.Assert(one["passport"], data["passport"])
|
||||
t.Assert(one["create_time"], data["create_time"])
|
||||
t.Assert(one["nickname"], gparser.MustToJson(data["nickname"]))
|
||||
t.Assert(one["nickname"], gjson.New(data["nickname"]).MustToJson())
|
||||
})
|
||||
}
|
||||
|
||||
@ -785,7 +784,7 @@ func Test_DB_ToJson(t *testing.T) {
|
||||
gtest.AssertNil(err)
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
result, err := db.Model(table).Fields("*").Where("id =? ", 1).Select()
|
||||
result, err := db.Model(table).Fields("*").Where("id =? ", 1).All()
|
||||
if err != nil {
|
||||
gtest.Fatal(err)
|
||||
}
|
||||
@ -814,11 +813,11 @@ func Test_DB_ToJson(t *testing.T) {
|
||||
gtest.Fatal(err)
|
||||
}
|
||||
|
||||
t.Assert(users[0].Id, resultJson.GetInt("0.id"))
|
||||
t.Assert(users[0].Passport, resultJson.GetString("0.passport"))
|
||||
t.Assert(users[0].Password, resultJson.GetString("0.password"))
|
||||
t.Assert(users[0].NickName, resultJson.GetString("0.nickname"))
|
||||
t.Assert(users[0].CreateTime, resultJson.GetString("0.create_time"))
|
||||
t.Assert(users[0].Id, resultJson.Get("0.id").Int())
|
||||
t.Assert(users[0].Passport, resultJson.Get("0.passport").String())
|
||||
t.Assert(users[0].Password, resultJson.Get("0.password").String())
|
||||
t.Assert(users[0].NickName, resultJson.Get("0.nickname").String())
|
||||
t.Assert(users[0].CreateTime, resultJson.Get("0.create_time").String())
|
||||
|
||||
result = nil
|
||||
err = result.Structs(&users)
|
||||
@ -925,7 +924,7 @@ func Test_DB_ToStringMap(t *testing.T) {
|
||||
gtest.AssertNil(err)
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
id := "1"
|
||||
result, err := db.Model(table).Fields("*").Where("id = ?", 1).Select()
|
||||
result, err := db.Model(table).Fields("*").Where("id = ?", 1).All()
|
||||
if err != nil {
|
||||
gtest.Fatal(err)
|
||||
}
|
||||
@ -962,7 +961,7 @@ func Test_DB_ToIntMap(t *testing.T) {
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
id := 1
|
||||
result, err := db.Model(table).Fields("*").Where("id = ?", id).Select()
|
||||
result, err := db.Model(table).Fields("*").Where("id = ?", id).All()
|
||||
if err != nil {
|
||||
gtest.Fatal(err)
|
||||
}
|
||||
@ -998,7 +997,7 @@ func Test_DB_ToUintMap(t *testing.T) {
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
id := 1
|
||||
result, err := db.Model(table).Fields("*").Where("id = ?", id).Select()
|
||||
result, err := db.Model(table).Fields("*").Where("id = ?", id).All()
|
||||
if err != nil {
|
||||
gtest.Fatal(err)
|
||||
}
|
||||
@ -1036,7 +1035,7 @@ func Test_DB_ToStringRecord(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
id := 1
|
||||
ids := "1"
|
||||
result, err := db.Model(table).Fields("*").Where("id = ?", id).Select()
|
||||
result, err := db.Model(table).Fields("*").Where("id = ?", id).All()
|
||||
if err != nil {
|
||||
gtest.Fatal(err)
|
||||
}
|
||||
@ -1073,7 +1072,7 @@ func Test_DB_ToIntRecord(t *testing.T) {
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
id := 1
|
||||
result, err := db.Model(table).Fields("*").Where("id = ?", id).Select()
|
||||
result, err := db.Model(table).Fields("*").Where("id = ?", id).All()
|
||||
if err != nil {
|
||||
gtest.Fatal(err)
|
||||
}
|
||||
@ -1110,7 +1109,7 @@ func Test_DB_ToUintRecord(t *testing.T) {
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
id := 1
|
||||
result, err := db.Model(table).Fields("*").Where("id = ?", id).Select()
|
||||
result, err := db.Model(table).Fields("*").Where("id = ?", id).All()
|
||||
if err != nil {
|
||||
gtest.Fatal(err)
|
||||
}
|
||||
@ -1182,7 +1181,7 @@ func Test_DB_TableField(t *testing.T) {
|
||||
gtest.Assert(n, 1)
|
||||
}
|
||||
|
||||
result, err := db.Model(name).Fields("*").Where("field_int = ?", 2).Select()
|
||||
result, err := db.Model(name).Fields("*").Where("field_int = ?", 2).All()
|
||||
if err != nil {
|
||||
gtest.Fatal(err)
|
||||
}
|
||||
@ -1313,14 +1312,14 @@ func Test_Model_InnerJoin(t *testing.T) {
|
||||
|
||||
t.Assert(n, 5)
|
||||
|
||||
result, err := db.Model(table1+" u1").InnerJoin(table2+" u2", "u1.id = u2.id").Order("u1.id").Select()
|
||||
result, err := db.Model(table1+" u1").InnerJoin(table2+" u2", "u1.id = u2.id").Order("u1.id").All()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Assert(len(result), 5)
|
||||
|
||||
result, err = db.Model(table1+" u1").InnerJoin(table2+" u2", "u1.id = u2.id").Where("u1.id > ?", 1).Order("u1.id").Select()
|
||||
result, err = db.Model(table1+" u1").InnerJoin(table2+" u2", "u1.id = u2.id").Where("u1.id > ?", 1).Order("u1.id").All()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -1349,14 +1348,14 @@ func Test_Model_LeftJoin(t *testing.T) {
|
||||
t.Assert(n, 7)
|
||||
}
|
||||
|
||||
result, err := db.Model(table1+" u1").LeftJoin(table2+" u2", "u1.id = u2.id").Select()
|
||||
result, err := db.Model(table1+" u1").LeftJoin(table2+" u2", "u1.id = u2.id").All()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Assert(len(result), 10)
|
||||
|
||||
result, err = db.Model(table1+" u1").LeftJoin(table2+" u2", "u1.id = u2.id").Where("u1.id > ? ", 2).Select()
|
||||
result, err = db.Model(table1+" u1").LeftJoin(table2+" u2", "u1.id = u2.id").Where("u1.id > ? ", 2).All()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -1385,13 +1384,13 @@ func Test_Model_RightJoin(t *testing.T) {
|
||||
|
||||
t.Assert(n, 7)
|
||||
|
||||
result, err := db.Model(table1+" u1").RightJoin(table2+" u2", "u1.id = u2.id").Select()
|
||||
result, err := db.Model(table1+" u1").RightJoin(table2+" u2", "u1.id = u2.id").All()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Assert(len(result), 10)
|
||||
|
||||
result, err = db.Model(table1+" u1").RightJoin(table2+" u2", "u1.id = u2.id").Where("u1.id > 2").Select()
|
||||
result, err = db.Model(table1+" u1").RightJoin(table2+" u2", "u1.id = u2.id").Where("u1.id > 2").All()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@ -10,13 +10,13 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/encoding/gjson"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/container/garray"
|
||||
"github.com/gogf/gf/container/gmap"
|
||||
"github.com/gogf/gf/debug/gdebug"
|
||||
"github.com/gogf/gf/encoding/gparser"
|
||||
"github.com/gogf/gf/os/gfile"
|
||||
"github.com/gogf/gf/util/gutil"
|
||||
|
||||
@ -124,7 +124,7 @@ func Test_Model_Insert_WithStructAndSliceAttribute(t *testing.T) {
|
||||
t.AssertNil(err)
|
||||
t.Assert(one["passport"], data["passport"])
|
||||
t.Assert(one["create_time"], data["create_time"])
|
||||
t.Assert(one["nickname"], gparser.MustToJson(data["nickname"]))
|
||||
t.Assert(one["nickname"], gjson.New(data["nickname"]).MustToJson())
|
||||
})
|
||||
}
|
||||
|
||||
@ -464,7 +464,7 @@ func Test_Model_Safe(t *testing.T) {
|
||||
t.AssertNil(err)
|
||||
t.Assert(count, 2)
|
||||
|
||||
md.And("id = ?", 1)
|
||||
md.Where("id = ?", 1)
|
||||
count, err = md.Count()
|
||||
t.AssertNil(err)
|
||||
t.Assert(count, 1)
|
||||
@ -475,7 +475,7 @@ func Test_Model_Safe(t *testing.T) {
|
||||
t.AssertNil(err)
|
||||
t.Assert(count, 2)
|
||||
|
||||
md.And("id = ?", 1)
|
||||
md.Where("id = ?", 1)
|
||||
count, err = md.Count()
|
||||
t.AssertNil(err)
|
||||
t.Assert(count, 2)
|
||||
@ -487,7 +487,7 @@ func Test_Model_Safe(t *testing.T) {
|
||||
t.AssertNil(err)
|
||||
t.Assert(count, 2)
|
||||
|
||||
md.And("id = ?", 1)
|
||||
md.Where("id = ?", 1)
|
||||
count, err = md.Count()
|
||||
t.AssertNil(err)
|
||||
t.Assert(count, 2)
|
||||
@ -881,7 +881,7 @@ func Test_Model_Select(t *testing.T) {
|
||||
table := createInitTable()
|
||||
defer dropTable(table)
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
result, err := db.Model(table).Select()
|
||||
result, err := db.Model(table).All()
|
||||
t.AssertNil(err)
|
||||
t.Assert(len(result), TableSize)
|
||||
})
|
||||
@ -1213,7 +1213,7 @@ func Test_Model_OrderBy(t *testing.T) {
|
||||
defer dropTable(table)
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
result, err := db.Model(table).Order("id DESC").Select()
|
||||
result, err := db.Model(table).Order("id DESC").All()
|
||||
t.AssertNil(err)
|
||||
t.Assert(len(result), TableSize)
|
||||
t.Assert(result[0]["nickname"].String(), fmt.Sprintf("name_%d", TableSize))
|
||||
@ -1325,7 +1325,7 @@ func Test_Model_Where(t *testing.T) {
|
||||
result, err := db.Model(table).Where(g.Map{
|
||||
"id": g.Slice{1, 2, 3},
|
||||
"passport": g.Slice{"user_2", "user_3"},
|
||||
}).And("id=? and nickname=?", g.Slice{3, "name_3"}).One()
|
||||
}).Where("id=? and nickname=?", g.Slice{3, "name_3"}).One()
|
||||
t.AssertNil(err)
|
||||
t.AssertGT(len(result), 0)
|
||||
t.Assert(result["id"].Int(), 3)
|
||||
@ -1354,22 +1354,22 @@ func Test_Model_Where(t *testing.T) {
|
||||
t.Assert(result["id"].Int(), 3)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
result, err := db.Model(table).Where("id", 3).And("nickname", "name_3").One()
|
||||
result, err := db.Model(table).Where("id", 3).Where("nickname", "name_3").One()
|
||||
t.AssertNil(err)
|
||||
t.Assert(result["id"].Int(), 3)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
result, err := db.Model(table).Where("id", 30).Or("nickname", "name_3").One()
|
||||
result, err := db.Model(table).Where("id", 30).WhereOr("nickname", "name_3").One()
|
||||
t.AssertNil(err)
|
||||
t.Assert(result["id"].Int(), 3)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
result, err := db.Model(table).Where("id", 30).Or("nickname", "name_3").And("id>?", 1).One()
|
||||
result, err := db.Model(table).Where("id", 30).WhereOr("nickname", "name_3").Where("id>?", 1).One()
|
||||
t.AssertNil(err)
|
||||
t.Assert(result["id"].Int(), 3)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
result, err := db.Model(table).Where("id", 30).Or("nickname", "name_3").And("id>", 1).One()
|
||||
result, err := db.Model(table).Where("id", 30).WhereOr("nickname", "name_3").Where("id>", 1).One()
|
||||
t.AssertNil(err)
|
||||
t.Assert(result["id"].Int(), 3)
|
||||
})
|
||||
@ -1652,7 +1652,7 @@ func Test_Model_WherePri(t *testing.T) {
|
||||
result, err := db.Model(table).WherePri(g.Map{
|
||||
"id": g.Slice{1, 2, 3},
|
||||
"passport": g.Slice{"user_2", "user_3"},
|
||||
}).And("id=? and nickname=?", g.Slice{3, "name_3"}).One()
|
||||
}).Where("id=? and nickname=?", g.Slice{3, "name_3"}).One()
|
||||
t.AssertNil(err)
|
||||
t.AssertGT(len(result), 0)
|
||||
t.Assert(result["id"].Int(), 3)
|
||||
@ -1661,7 +1661,7 @@ func Test_Model_WherePri(t *testing.T) {
|
||||
result, err := db.Model(table).WherePri(g.Map{
|
||||
"id": g.Slice{1, 2, 3},
|
||||
"passport": g.Slice{"user_2", "user_3"},
|
||||
}).Or("nickname=?", g.Slice{"name_4"}).And("id", 3).One()
|
||||
}).WhereOr("nickname=?", g.Slice{"name_4"}).Where("id", 3).One()
|
||||
t.AssertNil(err)
|
||||
t.AssertGT(len(result), 0)
|
||||
t.Assert(result["id"].Int(), 2)
|
||||
@ -1690,22 +1690,22 @@ func Test_Model_WherePri(t *testing.T) {
|
||||
t.Assert(result["id"].Int(), 3)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
result, err := db.Model(table).WherePri("id", 3).And("nickname", "name_3").One()
|
||||
result, err := db.Model(table).WherePri("id", 3).Where("nickname", "name_3").One()
|
||||
t.AssertNil(err)
|
||||
t.Assert(result["id"].Int(), 3)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
result, err := db.Model(table).WherePri("id", 30).Or("nickname", "name_3").One()
|
||||
result, err := db.Model(table).WherePri("id", 30).WhereOr("nickname", "name_3").One()
|
||||
t.AssertNil(err)
|
||||
t.Assert(result["id"].Int(), 3)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
result, err := db.Model(table).WherePri("id", 30).Or("nickname", "name_3").And("id>?", 1).One()
|
||||
result, err := db.Model(table).WherePri("id", 30).WhereOr("nickname", "name_3").Where("id>?", 1).One()
|
||||
t.AssertNil(err)
|
||||
t.Assert(result["id"].Int(), 3)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
result, err := db.Model(table).WherePri("id", 30).Or("nickname", "name_3").And("id>", 1).One()
|
||||
result, err := db.Model(table).WherePri("id", 30).WhereOr("nickname", "name_3").Where("id>", 1).One()
|
||||
t.AssertNil(err)
|
||||
t.Assert(result["id"].Int(), 3)
|
||||
})
|
||||
@ -1886,7 +1886,7 @@ func Test_Model_Offset(t *testing.T) {
|
||||
table := createInitTable()
|
||||
defer dropTable(table)
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
result, err := db.Model(table).Limit(2).Offset(5).Order("id").Select()
|
||||
result, err := db.Model(table).Limit(2).Offset(5).Order("id").All()
|
||||
t.AssertNil(err)
|
||||
t.Assert(len(result), 2)
|
||||
t.Assert(result[0]["id"], 6)
|
||||
@ -2207,7 +2207,7 @@ func Test_Model_Option_Where(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
table := createInitTable()
|
||||
defer dropTable(table)
|
||||
r, err := db.Model(table).OmitEmpty().Data("nickname", 1).Where(g.Map{"id": 0, "passport": ""}).And(1).Update()
|
||||
r, err := db.Model(table).OmitEmpty().Data("nickname", 1).Where(g.Map{"id": 0, "passport": ""}).Where(1).Update()
|
||||
t.AssertNil(err)
|
||||
n, _ := r.RowsAffected()
|
||||
t.Assert(n, TableSize)
|
||||
@ -2245,7 +2245,7 @@ func Test_Model_Where_MultiSliceArguments(t *testing.T) {
|
||||
result, err := db.Model(table).Where(g.Map{
|
||||
"id": g.Slice{1, 2, 3},
|
||||
"passport": g.Slice{"user_2", "user_3"},
|
||||
}).Or("nickname=?", g.Slice{"name_4"}).And("id", 3).One()
|
||||
}).WhereOr("nickname=?", g.Slice{"name_4"}).Where("id", 3).One()
|
||||
t.AssertNil(err)
|
||||
t.AssertGT(len(result), 0)
|
||||
t.Assert(result["id"].Int(), 2)
|
||||
@ -2299,26 +2299,6 @@ func Test_Model_FieldsEx_WithReservedWords(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Model_FieldsStr(t *testing.T) {
|
||||
table := createTable()
|
||||
defer dropTable(table)
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
t.Assert(db.Model(table).FieldsStr(), "`id`,`passport`,`password`,`nickname`,`create_time`")
|
||||
t.Assert(db.Model(table).FieldsStr("a."), "`a`.`id`,`a`.`passport`,`a`.`password`,`a`.`nickname`,`a`.`create_time`")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Model_FieldsExStr(t *testing.T) {
|
||||
table := createTable()
|
||||
defer dropTable(table)
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
t.Assert(db.Model(table).FieldsExStr("create_time,nickname"), "`id`,`passport`,`password`")
|
||||
t.Assert(db.Model(table).FieldsExStr("create_time,nickname", "a."), "`a`.`id`,`a`.`passport`,`a`.`password`")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Model_Prefix(t *testing.T) {
|
||||
db := dbPrefix
|
||||
table := fmt.Sprintf(`%s_%d`, TableName, gtime.TimestampNano())
|
||||
|
||||
@ -641,7 +641,7 @@ CREATE TABLE %s (
|
||||
n, _ := r.RowsAffected()
|
||||
t.Assert(n, 3)
|
||||
|
||||
count, err := db.Model(table).Where("id", 1).Or("id", 3).Count()
|
||||
count, err := db.Model(table).Where("id", 1).WhereOr("id", 3).Count()
|
||||
t.AssertNil(err)
|
||||
t.Assert(count, 0)
|
||||
})
|
||||
|
||||
@ -14,253 +14,27 @@
|
||||
package gredis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/internal/intlog"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/container/gmap"
|
||||
"github.com/gogf/gf/container/gvar"
|
||||
"github.com/gomodule/redigo/redis"
|
||||
"github.com/gogf/gf/errors/gcode"
|
||||
"github.com/gogf/gf/errors/gerror"
|
||||
)
|
||||
|
||||
// Redis client.
|
||||
type Redis struct {
|
||||
pool *redis.Pool // Underlying connection pool.
|
||||
group string // Configuration group.
|
||||
config *Config // Configuration.
|
||||
ctx context.Context // Context.
|
||||
}
|
||||
|
||||
// Conn is redis connection.
|
||||
type Conn struct {
|
||||
redis.Conn
|
||||
ctx context.Context
|
||||
redis *Redis
|
||||
}
|
||||
|
||||
// Config is redis configuration.
|
||||
type Config struct {
|
||||
Host string `json:"host"`
|
||||
Port int `json:"port"`
|
||||
Db int `json:"db"`
|
||||
Pass string `json:"pass"` // Password for AUTH.
|
||||
MaxIdle int `json:"maxIdle"` // Maximum number of connections allowed to be idle (default is 10)
|
||||
MaxActive int `json:"maxActive"` // Maximum number of connections limit (default is 0 means no limit).
|
||||
IdleTimeout time.Duration `json:"idleTimeout"` // Maximum idle time for connection (default is 10 seconds, not allowed to be set to 0)
|
||||
MaxConnLifetime time.Duration `json:"maxConnLifetime"` // Maximum lifetime of the connection (default is 30 seconds, not allowed to be set to 0)
|
||||
ConnectTimeout time.Duration `json:"connectTimeout"` // Dial connection timeout.
|
||||
TLS bool `json:"tls"` // Specifies the config to use when a TLS connection is dialed.
|
||||
TLSSkipVerify bool `json:"tlsSkipVerify"` // Disables server name verification when connecting over TLS.
|
||||
}
|
||||
|
||||
// PoolStats is statistics of redis connection pool.
|
||||
type PoolStats struct {
|
||||
redis.PoolStats
|
||||
}
|
||||
|
||||
const (
|
||||
defaultPoolIdleTimeout = 10 * time.Second
|
||||
defaultPoolConnTimeout = 10 * time.Second
|
||||
defaultPoolMaxIdle = 10
|
||||
defaultPoolMaxActive = 100
|
||||
defaultPoolMaxLifeTime = 30 * time.Second
|
||||
)
|
||||
|
||||
var (
|
||||
// Pool map.
|
||||
pools = gmap.NewStrAnyMap(true)
|
||||
)
|
||||
|
||||
// New creates a redis client object with given configuration.
|
||||
// Redis client maintains a connection pool automatically.
|
||||
func New(config *Config) *Redis {
|
||||
// The MaxIdle is the most important attribute of the connection pool.
|
||||
// Only if this attribute is set, the created connections from client
|
||||
// can not exceed the limit of the server.
|
||||
if config.MaxIdle == 0 {
|
||||
config.MaxIdle = defaultPoolMaxIdle
|
||||
// New creates and returns a redis client.
|
||||
// It creates a default redis adapter of go-redis.
|
||||
func New(config ...*Config) (*Redis, error) {
|
||||
if len(config) > 0 {
|
||||
return &Redis{adapter: NewAdapterGoRedis(config[0])}, nil
|
||||
}
|
||||
// This value SHOULD NOT exceed the connection limit of redis server.
|
||||
if config.MaxActive == 0 {
|
||||
config.MaxActive = defaultPoolMaxActive
|
||||
}
|
||||
if config.IdleTimeout == 0 {
|
||||
config.IdleTimeout = defaultPoolIdleTimeout
|
||||
}
|
||||
if config.ConnectTimeout == 0 {
|
||||
config.ConnectTimeout = defaultPoolConnTimeout
|
||||
}
|
||||
if config.MaxConnLifetime == 0 {
|
||||
config.MaxConnLifetime = defaultPoolMaxLifeTime
|
||||
}
|
||||
return &Redis{
|
||||
config: config,
|
||||
pool: pools.GetOrSetFuncLock(fmt.Sprintf("%v", config), func() interface{} {
|
||||
return &redis.Pool{
|
||||
Wait: true,
|
||||
IdleTimeout: config.IdleTimeout,
|
||||
MaxActive: config.MaxActive,
|
||||
MaxIdle: config.MaxIdle,
|
||||
MaxConnLifetime: config.MaxConnLifetime,
|
||||
Dial: func() (redis.Conn, error) {
|
||||
c, err := redis.Dial(
|
||||
"tcp",
|
||||
fmt.Sprintf("%s:%d", config.Host, config.Port),
|
||||
redis.DialConnectTimeout(config.ConnectTimeout),
|
||||
redis.DialUseTLS(config.TLS),
|
||||
redis.DialTLSSkipVerify(config.TLSSkipVerify),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
intlog.Printf(context.TODO(), `open new connection, config:%+v`, config)
|
||||
// AUTH
|
||||
if len(config.Pass) > 0 {
|
||||
if _, err := c.Do("AUTH", config.Pass); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// DB
|
||||
if _, err := c.Do("SELECT", config.Db); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c, nil
|
||||
},
|
||||
// After the conn is taken from the connection pool, to test if the connection is available,
|
||||
// If error is returned then it closes the connection object and recreate a new connection.
|
||||
TestOnBorrow: func(c redis.Conn, t time.Time) error {
|
||||
_, err := c.Do("PING")
|
||||
return err
|
||||
},
|
||||
}
|
||||
}).(*redis.Pool),
|
||||
configFromGlobal, ok := GetConfig()
|
||||
if !ok {
|
||||
return nil, gerror.NewCode(
|
||||
gcode.CodeMissingConfiguration,
|
||||
`configuration not found for creating Redis client`,
|
||||
)
|
||||
}
|
||||
return &Redis{adapter: NewAdapterGoRedis(configFromGlobal)}, nil
|
||||
}
|
||||
|
||||
// NewFromStr creates a redis client object with given configuration string.
|
||||
// Redis client maintains a connection pool automatically.
|
||||
// The parameter `str` like:
|
||||
// 127.0.0.1:6379,0
|
||||
// 127.0.0.1:6379,0,password
|
||||
func NewFromStr(str string) (*Redis, error) {
|
||||
config, err := ConfigFromStr(str)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return New(config), nil
|
||||
}
|
||||
|
||||
// Close closes the redis connection pool,
|
||||
// it will release all connections reserved by this pool.
|
||||
// It is not necessary to call Close manually.
|
||||
func (r *Redis) Close() error {
|
||||
if r.group != "" {
|
||||
// If it is an instance object,
|
||||
// it needs to remove it from the instance Map.
|
||||
instances.Remove(r.group)
|
||||
}
|
||||
pools.Remove(fmt.Sprintf("%v", r.config))
|
||||
return r.pool.Close()
|
||||
}
|
||||
|
||||
// Clone clones and returns a new Redis object, which is a shallow copy of current one.
|
||||
func (r *Redis) Clone() *Redis {
|
||||
newRedis := New(r.config)
|
||||
*newRedis = *r
|
||||
return newRedis
|
||||
}
|
||||
|
||||
// Ctx is a channing function which sets the context for next operation.
|
||||
func (r *Redis) Ctx(ctx context.Context) *Redis {
|
||||
newRedis := r.Clone()
|
||||
newRedis.ctx = ctx
|
||||
return newRedis
|
||||
}
|
||||
|
||||
// Conn returns a raw underlying connection object,
|
||||
// which expose more methods to communicate with server.
|
||||
// **You should call Close function manually if you do not use this connection any further.**
|
||||
func (r *Redis) Conn() *Conn {
|
||||
return &Conn{
|
||||
Conn: r.pool.Get(),
|
||||
ctx: r.ctx,
|
||||
redis: r,
|
||||
}
|
||||
}
|
||||
|
||||
// GetConn is alias of Conn, see Conn.
|
||||
// Deprecated, use Conn instead.
|
||||
func (r *Redis) GetConn() *Conn {
|
||||
return r.Conn()
|
||||
}
|
||||
|
||||
// SetMaxIdle sets the maximum number of idle connections in the pool.
|
||||
func (r *Redis) SetMaxIdle(value int) {
|
||||
r.pool.MaxIdle = value
|
||||
}
|
||||
|
||||
// SetMaxActive sets the maximum number of connections allocated by the pool at a given time.
|
||||
// When zero, there is no limit on the number of connections in the pool.
|
||||
//
|
||||
// Note that if the pool is at the MaxActive limit, then all the operations will wait for
|
||||
// a connection to be returned to the pool before returning.
|
||||
func (r *Redis) SetMaxActive(value int) {
|
||||
r.pool.MaxActive = value
|
||||
}
|
||||
|
||||
// SetIdleTimeout sets the IdleTimeout attribute of the connection pool.
|
||||
// It closes connections after remaining idle for this duration. If the value
|
||||
// is zero, then idle connections are not closed. Applications should set
|
||||
// the timeout to a value less than the server's timeout.
|
||||
func (r *Redis) SetIdleTimeout(value time.Duration) {
|
||||
r.pool.IdleTimeout = value
|
||||
}
|
||||
|
||||
// SetMaxConnLifetime sets the MaxConnLifetime attribute of the connection pool.
|
||||
// It closes connections older than this duration. If the value is zero, then
|
||||
// the pool does not close connections based on age.
|
||||
func (r *Redis) SetMaxConnLifetime(value time.Duration) {
|
||||
r.pool.MaxConnLifetime = value
|
||||
}
|
||||
|
||||
// Stats returns pool's statistics.
|
||||
func (r *Redis) Stats() *PoolStats {
|
||||
return &PoolStats{r.pool.Stats()}
|
||||
}
|
||||
|
||||
// Do sends a command to the server and returns the received reply.
|
||||
// Do automatically get a connection from pool, and close it when the reply received.
|
||||
// It does not really "close" the connection, but drops it back to the connection pool.
|
||||
func (r *Redis) Do(commandName string, args ...interface{}) (interface{}, error) {
|
||||
conn := &Conn{
|
||||
Conn: r.pool.Get(),
|
||||
ctx: r.ctx,
|
||||
redis: r,
|
||||
}
|
||||
defer conn.Close()
|
||||
return conn.Do(commandName, args...)
|
||||
}
|
||||
|
||||
// DoWithTimeout sends a command to the server and returns the received reply.
|
||||
// The timeout overrides the read timeout set when dialing the connection.
|
||||
func (r *Redis) DoWithTimeout(timeout time.Duration, commandName string, args ...interface{}) (interface{}, error) {
|
||||
conn := &Conn{
|
||||
Conn: r.pool.Get(),
|
||||
ctx: r.ctx,
|
||||
redis: r,
|
||||
}
|
||||
defer conn.Close()
|
||||
return conn.DoWithTimeout(timeout, commandName, args...)
|
||||
}
|
||||
|
||||
// DoVar returns value from Do as gvar.Var.
|
||||
func (r *Redis) DoVar(commandName string, args ...interface{}) (*gvar.Var, error) {
|
||||
return resultToVar(r.Do(commandName, args...))
|
||||
}
|
||||
|
||||
// DoVarWithTimeout returns value from Do as gvar.Var.
|
||||
// The timeout overrides the read timeout set when dialing the connection.
|
||||
func (r *Redis) DoVarWithTimeout(timeout time.Duration, commandName string, args ...interface{}) (*gvar.Var, error) {
|
||||
return resultToVar(r.DoWithTimeout(timeout, commandName, args...))
|
||||
// NewWithAdapter creates and returns a redis client with given adapter.
|
||||
func NewWithAdapter(adapter Adapter) *Redis {
|
||||
return &Redis{adapter: adapter}
|
||||
}
|
||||
|
||||
35
database/gredis/gredis_adapter.go
Normal file
35
database/gredis/gredis_adapter.go
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). 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 (
|
||||
"context"
|
||||
"github.com/gogf/gf/container/gvar"
|
||||
)
|
||||
|
||||
// Adapter is an interface for universal redis operations.
|
||||
type Adapter interface {
|
||||
// Conn retrieves and returns a connection object for continuous operations.
|
||||
// Note that you should call Close function manually if you do not use this connection any further.
|
||||
Conn(ctx context.Context) (conn Conn, err error)
|
||||
|
||||
// Close closes current redis client, closes its connection pool and releases all its related resources.
|
||||
Close(ctx context.Context) (err error)
|
||||
}
|
||||
|
||||
// Conn is an interface of a connection from universal redis client.
|
||||
type Conn interface {
|
||||
// Do sends a command to the server and returns the received reply.
|
||||
// It uses json.Marshal for struct/slice/map type values before committing them to redis.
|
||||
Do(ctx context.Context, command string, args ...interface{}) (result *gvar.Var, err error)
|
||||
|
||||
// Receive receives a single reply as gvar.Var from the Redis server.
|
||||
Receive(ctx context.Context) (result *gvar.Var, err error)
|
||||
|
||||
// Close puts the connection back to connection pool.
|
||||
Close(ctx context.Context) (err error)
|
||||
}
|
||||
87
database/gredis/gredis_adapter_goredis.go
Normal file
87
database/gredis/gredis_adapter_goredis.go
Normal file
@ -0,0 +1,87 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). 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 (
|
||||
"context"
|
||||
"github.com/go-redis/redis/v8"
|
||||
"github.com/gogf/gf/text/gstr"
|
||||
"time"
|
||||
)
|
||||
|
||||
// AdapterGoRedis is an implement of Adapter using go-redis.
|
||||
type AdapterGoRedis struct {
|
||||
client redis.UniversalClient
|
||||
config *Config
|
||||
}
|
||||
|
||||
const (
|
||||
defaultPoolMaxIdle = 10
|
||||
defaultPoolMaxActive = 100
|
||||
defaultPoolIdleTimeout = 10 * time.Second
|
||||
defaultPoolWaitTimeout = 10 * time.Second
|
||||
defaultPoolMaxLifeTime = 30 * time.Second
|
||||
)
|
||||
|
||||
// NewAdapterGoRedis creates and returns a redis adapter using go-redis.
|
||||
func NewAdapterGoRedis(config *Config) *AdapterGoRedis {
|
||||
fillWithDefaultConfiguration(config)
|
||||
client := redis.NewUniversalClient(&redis.UniversalOptions{
|
||||
Addrs: gstr.SplitAndTrim(config.Address, ","),
|
||||
Password: config.Pass,
|
||||
DB: config.Db,
|
||||
MinIdleConns: config.MinIdle,
|
||||
MaxConnAge: config.MaxConnLifetime,
|
||||
IdleTimeout: config.IdleTimeout,
|
||||
PoolTimeout: config.WaitTimeout,
|
||||
DialTimeout: config.DialTimeout,
|
||||
ReadTimeout: config.ReadTimeout,
|
||||
WriteTimeout: config.WriteTimeout,
|
||||
MasterName: config.MasterName,
|
||||
TLSConfig: config.TLSConfig,
|
||||
})
|
||||
return &AdapterGoRedis{
|
||||
client: client,
|
||||
config: config,
|
||||
}
|
||||
}
|
||||
|
||||
// Close closes the redis connection pool, which will release all connections reserved by this pool.
|
||||
// It is commonly not necessary to call Close manually.
|
||||
func (r *AdapterGoRedis) Close(ctx context.Context) error {
|
||||
return r.client.Close()
|
||||
}
|
||||
|
||||
// Conn retrieves and returns a connection object for continuous operations.
|
||||
// Note that you should call Close function manually if you do not use this connection any further.
|
||||
func (r *AdapterGoRedis) Conn(ctx context.Context) (Conn, error) {
|
||||
return &localAdapterGoRedisConn{
|
||||
redis: r,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func fillWithDefaultConfiguration(config *Config) {
|
||||
// The MaxIdle is the most important attribute of the connection pool.
|
||||
// Only if this attribute is set, the created connections from client
|
||||
// can not exceed the limit of the server.
|
||||
if config.MaxIdle == 0 {
|
||||
config.MaxIdle = defaultPoolMaxIdle
|
||||
}
|
||||
// This value SHOULD NOT exceed the connection limit of redis server.
|
||||
if config.MaxActive == 0 {
|
||||
config.MaxActive = defaultPoolMaxActive
|
||||
}
|
||||
if config.IdleTimeout == 0 {
|
||||
config.IdleTimeout = defaultPoolIdleTimeout
|
||||
}
|
||||
if config.WaitTimeout == 0 {
|
||||
config.WaitTimeout = defaultPoolWaitTimeout
|
||||
}
|
||||
if config.MaxConnLifetime == 0 {
|
||||
config.MaxConnLifetime = defaultPoolMaxLifeTime
|
||||
}
|
||||
}
|
||||
100
database/gredis/gredis_adapter_goredis_conn.go
Normal file
100
database/gredis/gredis_adapter_goredis_conn.go
Normal file
@ -0,0 +1,100 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). 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 (
|
||||
"context"
|
||||
"github.com/go-redis/redis/v8"
|
||||
"github.com/gogf/gf/container/gvar"
|
||||
"github.com/gogf/gf/text/gstr"
|
||||
"github.com/gogf/gf/util/gconv"
|
||||
)
|
||||
|
||||
type localAdapterGoRedisConn struct {
|
||||
ps *redis.PubSub
|
||||
redis *AdapterGoRedis
|
||||
}
|
||||
|
||||
// Do sends a command to the server and returns the received reply.
|
||||
// It uses json.Marshal for struct/slice/map type values before committing them to redis.
|
||||
func (c *localAdapterGoRedisConn) Do(ctx context.Context, command string, args ...interface{}) (reply *gvar.Var, err error) {
|
||||
switch gstr.ToLower(command) {
|
||||
case `subscribe`:
|
||||
c.ps = c.redis.client.Subscribe(ctx, gconv.Strings(args)...)
|
||||
|
||||
case `psubscribe`:
|
||||
c.ps = c.redis.client.PSubscribe(ctx, gconv.Strings(args)...)
|
||||
|
||||
case `unsubscribe`:
|
||||
if c.ps != nil {
|
||||
err = c.ps.Unsubscribe(ctx, gconv.Strings(args)...)
|
||||
}
|
||||
|
||||
case `punsubscribe`:
|
||||
if c.ps != nil {
|
||||
err = c.ps.PUnsubscribe(ctx, gconv.Strings(args)...)
|
||||
}
|
||||
|
||||
default:
|
||||
arguments := make([]interface{}, len(args)+1)
|
||||
copy(arguments, []interface{}{command})
|
||||
copy(arguments[1:], args)
|
||||
reply, err = c.resultToVar(
|
||||
c.redis.client.Do(ctx, arguments...).Result(),
|
||||
)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Receive receives a single reply as gvar.Var from the Redis server.
|
||||
func (c *localAdapterGoRedisConn) Receive(ctx context.Context) (*gvar.Var, error) {
|
||||
if c.ps != nil {
|
||||
return c.resultToVar(c.ps.Receive(ctx))
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Close closes current PubSub or puts the connection back to connection pool.
|
||||
func (c *localAdapterGoRedisConn) Close(ctx context.Context) error {
|
||||
if c.ps != nil {
|
||||
return c.ps.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// resultToVar converts redis operation result to gvar.Var.
|
||||
func (c *localAdapterGoRedisConn) resultToVar(result interface{}, err error) (*gvar.Var, error) {
|
||||
if err == redis.Nil {
|
||||
err = nil
|
||||
}
|
||||
if err == nil {
|
||||
switch v := result.(type) {
|
||||
case []byte:
|
||||
return gvar.New(string(v)), err
|
||||
|
||||
case []interface{}:
|
||||
return gvar.New(gconv.Strings(v)), err
|
||||
|
||||
case *redis.Message:
|
||||
result = &Message{
|
||||
Channel: v.Channel,
|
||||
Pattern: v.Pattern,
|
||||
Payload: v.Payload,
|
||||
PayloadSlice: v.PayloadSlice,
|
||||
}
|
||||
|
||||
case *redis.Subscription:
|
||||
result = &Subscription{
|
||||
Kind: v.Kind,
|
||||
Channel: v.Channel,
|
||||
Count: v.Count,
|
||||
}
|
||||
}
|
||||
}
|
||||
return gvar.New(result), err
|
||||
}
|
||||
@ -8,24 +8,43 @@ package gredis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"github.com/gogf/gf/errors/gcode"
|
||||
"github.com/gogf/gf/errors/gerror"
|
||||
"github.com/gogf/gf/internal/intlog"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/container/gmap"
|
||||
"github.com/gogf/gf/text/gregex"
|
||||
"github.com/gogf/gf/text/gstr"
|
||||
"github.com/gogf/gf/util/gconv"
|
||||
)
|
||||
|
||||
// Config is redis configuration.
|
||||
type Config struct {
|
||||
Address string `json:"address"` // It supports single and cluster redis server. Multiple addresses joined with char ','.
|
||||
Db int `json:"db"` // Redis db.
|
||||
Pass string `json:"pass"` // Password for AUTH.
|
||||
MinIdle int `json:"minIdle"` // Minimum number of connections allowed to be idle (default is 0)
|
||||
MaxIdle int `json:"maxIdle"` // Maximum number of connections allowed to be idle (default is 10)
|
||||
MaxActive int `json:"maxActive"` // Maximum number of connections limit (default is 0 means no limit).
|
||||
MaxConnLifetime time.Duration `json:"maxConnLifetime"` // Maximum lifetime of the connection (default is 30 seconds, not allowed to be set to 0)
|
||||
IdleTimeout time.Duration `json:"idleTimeout"` // Maximum idle time for connection (default is 10 seconds, not allowed to be set to 0)
|
||||
WaitTimeout time.Duration `json:"waitTimeout"` // Timed out duration waiting to get a connection from the connection pool.
|
||||
DialTimeout time.Duration `json:"dialTimeout"` // Dial connection timeout for TCP.
|
||||
ReadTimeout time.Duration `json:"readTimeout"` // Read timeout for TCP.
|
||||
WriteTimeout time.Duration `json:"writeTimeout"` // Write timeout for TCP.
|
||||
MasterName string `json:"masterName"` // Used in Redis Sentinel mode.
|
||||
TLS bool `json:"tls"` // Specifies whether TLS should be used when connecting to the server.
|
||||
TLSSkipVerify bool `json:"tlsSkipVerify"` // Disables server name verification when connecting over TLS.
|
||||
TLSConfig *tls.Config `json:"-"` // TLS Config to use. When set TLS will be negotiated.
|
||||
}
|
||||
|
||||
const (
|
||||
DefaultGroupName = "default" // Default configuration group name.
|
||||
DefaultRedisPort = 6379 // Default redis port configuration if not passed.
|
||||
)
|
||||
|
||||
var (
|
||||
// Configuration groups.
|
||||
configs = gmap.NewStrAnyMap(true)
|
||||
localConfigMap = gmap.NewStrAnyMap(true)
|
||||
)
|
||||
|
||||
// SetConfig sets the global configuration for specified group.
|
||||
@ -35,28 +54,53 @@ func SetConfig(config *Config, name ...string) {
|
||||
if len(name) > 0 {
|
||||
group = name[0]
|
||||
}
|
||||
configs.Set(group, config)
|
||||
instances.Remove(group)
|
||||
localConfigMap.Set(group, config)
|
||||
|
||||
intlog.Printf(context.TODO(), `SetConfig for group "%s": %+v`, group, config)
|
||||
}
|
||||
|
||||
// SetConfigByStr sets the global configuration for specified group with string.
|
||||
// SetConfigByMap sets the global configuration for specified group with map.
|
||||
// If `name` is not passed, it sets configuration for the default group name.
|
||||
func SetConfigByStr(str string, name ...string) error {
|
||||
func SetConfigByMap(m map[string]interface{}, name ...string) error {
|
||||
group := DefaultGroupName
|
||||
if len(name) > 0 {
|
||||
group = name[0]
|
||||
}
|
||||
config, err := ConfigFromStr(str)
|
||||
config, err := ConfigFromMap(m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
configs.Set(group, config)
|
||||
instances.Remove(group)
|
||||
localConfigMap.Set(group, config)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ConfigFromMap parses and returns config from given map.
|
||||
func ConfigFromMap(m map[string]interface{}) (config *Config, err error) {
|
||||
config = &Config{}
|
||||
if err = gconv.Scan(m, config); err != nil {
|
||||
err = gerror.NewCodef(gcode.CodeInvalidConfiguration, `invalid redis configuration: "%+v"`, m)
|
||||
}
|
||||
if config.DialTimeout < 1000 {
|
||||
config.DialTimeout = config.DialTimeout * time.Second
|
||||
}
|
||||
if config.WaitTimeout < 1000 {
|
||||
config.WaitTimeout = config.WaitTimeout * time.Second
|
||||
}
|
||||
if config.WriteTimeout < 1000 {
|
||||
config.WriteTimeout = config.WriteTimeout * time.Second
|
||||
}
|
||||
if config.ReadTimeout < 1000 {
|
||||
config.ReadTimeout = config.ReadTimeout * time.Second
|
||||
}
|
||||
if config.IdleTimeout < 1000 {
|
||||
config.IdleTimeout = config.IdleTimeout * time.Second
|
||||
}
|
||||
if config.MaxConnLifetime < 1000 {
|
||||
config.MaxConnLifetime = config.MaxConnLifetime * time.Second
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetConfig returns the global configuration with specified group name.
|
||||
// If `name` is not passed, it returns configuration of the default group name.
|
||||
func GetConfig(name ...string) (config *Config, ok bool) {
|
||||
@ -64,7 +108,7 @@ func GetConfig(name ...string) (config *Config, ok bool) {
|
||||
if len(name) > 0 {
|
||||
group = name[0]
|
||||
}
|
||||
if v := configs.Get(group); v != nil {
|
||||
if v := localConfigMap.Get(group); v != nil {
|
||||
return v.(*Config), true
|
||||
}
|
||||
return &Config{}, false
|
||||
@ -77,51 +121,12 @@ func RemoveConfig(name ...string) {
|
||||
if len(name) > 0 {
|
||||
group = name[0]
|
||||
}
|
||||
configs.Remove(group)
|
||||
instances.Remove(group)
|
||||
localConfigMap.Remove(group)
|
||||
|
||||
intlog.Printf(context.TODO(), `RemoveConfig: %s`, group)
|
||||
}
|
||||
|
||||
// ConfigFromStr parses and returns config from given str.
|
||||
// Eg: host:port[,db,pass?maxIdle=x&maxActive=x&idleTimeout=x&maxConnLifetime=x]
|
||||
func ConfigFromStr(str string) (config *Config, err error) {
|
||||
array, _ := gregex.MatchString(`^([^:]+):*(\d*),{0,1}(\d*),{0,1}(.*)\?(.+)$`, str)
|
||||
if len(array) == 6 {
|
||||
parse, _ := gstr.Parse(array[5])
|
||||
config = &Config{
|
||||
Host: array[1],
|
||||
Port: gconv.Int(array[2]),
|
||||
Db: gconv.Int(array[3]),
|
||||
Pass: array[4],
|
||||
}
|
||||
if config.Port == 0 {
|
||||
config.Port = DefaultRedisPort
|
||||
}
|
||||
if err = gconv.Struct(parse, config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
array, _ = gregex.MatchString(`([^:]+):*(\d*),{0,1}(\d*),{0,1}(.*)`, str)
|
||||
if len(array) == 5 {
|
||||
config = &Config{
|
||||
Host: array[1],
|
||||
Port: gconv.Int(array[2]),
|
||||
Db: gconv.Int(array[3]),
|
||||
Pass: array[4],
|
||||
}
|
||||
if config.Port == 0 {
|
||||
config.Port = DefaultRedisPort
|
||||
}
|
||||
} else {
|
||||
err = gerror.NewCodef(gcode.CodeInvalidConfiguration, `invalid redis configuration: "%s"`, str)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ClearConfig removes all configurations and instances of redis.
|
||||
// ClearConfig removes all configurations of redis.
|
||||
func ClearConfig() {
|
||||
configs.Clear()
|
||||
instances.Clear()
|
||||
localConfigMap.Clear()
|
||||
}
|
||||
|
||||
@ -1,128 +0,0 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). 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 (
|
||||
"context"
|
||||
"github.com/gogf/gf/container/gvar"
|
||||
"github.com/gogf/gf/errors/gcode"
|
||||
"github.com/gogf/gf/errors/gerror"
|
||||
"github.com/gogf/gf/internal/json"
|
||||
"github.com/gogf/gf/os/gtime"
|
||||
"github.com/gogf/gf/util/gconv"
|
||||
"github.com/gomodule/redigo/redis"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Do sends a command to the server and returns the received reply.
|
||||
// It uses json.Marshal for struct/slice/map type values before committing them to redis.
|
||||
// The timeout overrides the read timeout set when dialing the connection.
|
||||
func (c *Conn) do(timeout time.Duration, commandName string, args ...interface{}) (reply interface{}, err error) {
|
||||
var (
|
||||
reflectValue reflect.Value
|
||||
reflectKind reflect.Kind
|
||||
)
|
||||
for k, v := range args {
|
||||
reflectValue = reflect.ValueOf(v)
|
||||
reflectKind = reflectValue.Kind()
|
||||
if reflectKind == reflect.Ptr {
|
||||
reflectValue = reflectValue.Elem()
|
||||
reflectKind = reflectValue.Kind()
|
||||
}
|
||||
switch reflectKind {
|
||||
case
|
||||
reflect.Struct,
|
||||
reflect.Map,
|
||||
reflect.Slice,
|
||||
reflect.Array:
|
||||
// Ignore slice type of: []byte.
|
||||
if _, ok := v.([]byte); !ok {
|
||||
if args[k], err = json.Marshal(v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if timeout > 0 {
|
||||
conn, ok := c.Conn.(redis.ConnWithTimeout)
|
||||
if !ok {
|
||||
return gvar.New(nil), gerror.NewCode(gcode.CodeNotSupported, `current connection does not support "ConnWithTimeout"`)
|
||||
}
|
||||
return conn.DoWithTimeout(timeout, commandName, args...)
|
||||
}
|
||||
timestampMilli1 := gtime.TimestampMilli()
|
||||
reply, err = c.Conn.Do(commandName, args...)
|
||||
timestampMilli2 := gtime.TimestampMilli()
|
||||
|
||||
// Tracing.
|
||||
c.addTracingItem(&tracingItem{
|
||||
err: err,
|
||||
commandName: commandName,
|
||||
arguments: args,
|
||||
costMilli: timestampMilli2 - timestampMilli1,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Ctx is a channing function which sets the context for next operation.
|
||||
func (c *Conn) Ctx(ctx context.Context) *Conn {
|
||||
c.ctx = ctx
|
||||
return c
|
||||
}
|
||||
|
||||
// Do sends a command to the server and returns the received reply.
|
||||
// It uses json.Marshal for struct/slice/map type values before committing them to redis.
|
||||
func (c *Conn) Do(commandName string, args ...interface{}) (reply interface{}, err error) {
|
||||
return c.do(0, commandName, args...)
|
||||
}
|
||||
|
||||
// DoWithTimeout sends a command to the server and returns the received reply.
|
||||
// The timeout overrides the read timeout set when dialing the connection.
|
||||
func (c *Conn) DoWithTimeout(timeout time.Duration, commandName string, args ...interface{}) (reply interface{}, err error) {
|
||||
return c.do(timeout, commandName, args...)
|
||||
}
|
||||
|
||||
// DoVar retrieves and returns the result from command as gvar.Var.
|
||||
func (c *Conn) DoVar(commandName string, args ...interface{}) (*gvar.Var, error) {
|
||||
return resultToVar(c.Do(commandName, args...))
|
||||
}
|
||||
|
||||
// DoVarWithTimeout retrieves and returns the result from command as gvar.Var.
|
||||
// The timeout overrides the read timeout set when dialing the connection.
|
||||
func (c *Conn) DoVarWithTimeout(timeout time.Duration, commandName string, args ...interface{}) (*gvar.Var, error) {
|
||||
return resultToVar(c.DoWithTimeout(timeout, commandName, args...))
|
||||
}
|
||||
|
||||
// ReceiveVar receives a single reply as gvar.Var from the Redis server.
|
||||
func (c *Conn) ReceiveVar() (*gvar.Var, error) {
|
||||
return resultToVar(c.Receive())
|
||||
}
|
||||
|
||||
// ReceiveVarWithTimeout receives a single reply as gvar.Var from the Redis server.
|
||||
// The timeout overrides the read timeout set when dialing the connection.
|
||||
func (c *Conn) ReceiveVarWithTimeout(timeout time.Duration) (*gvar.Var, error) {
|
||||
conn, ok := c.Conn.(redis.ConnWithTimeout)
|
||||
if !ok {
|
||||
return gvar.New(nil), gerror.NewCode(gcode.CodeNotSupported, `current connection does not support "ConnWithTimeout"`)
|
||||
}
|
||||
return resultToVar(conn.ReceiveWithTimeout(timeout))
|
||||
}
|
||||
|
||||
// resultToVar converts redis operation result to gvar.Var.
|
||||
func resultToVar(result interface{}, err error) (*gvar.Var, error) {
|
||||
if err == nil {
|
||||
if result, ok := result.([]byte); ok {
|
||||
return gvar.New(string(result)), err
|
||||
}
|
||||
// It treats all returned slice as string slice.
|
||||
if result, ok := result.([]interface{}); ok {
|
||||
return gvar.New(gconv.Strings(result)), err
|
||||
}
|
||||
}
|
||||
return gvar.New(result), err
|
||||
}
|
||||
@ -6,11 +6,14 @@
|
||||
|
||||
package gredis
|
||||
|
||||
import "github.com/gogf/gf/container/gmap"
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/container/gmap"
|
||||
"github.com/gogf/gf/internal/intlog"
|
||||
)
|
||||
|
||||
var (
|
||||
// Instance map
|
||||
instances = gmap.NewStrAnyMap(true)
|
||||
localInstances = gmap.NewStrAnyMap(true)
|
||||
)
|
||||
|
||||
// Instance returns an instance of redis client with specified group.
|
||||
@ -21,10 +24,13 @@ func Instance(name ...string) *Redis {
|
||||
if len(name) > 0 && name[0] != "" {
|
||||
group = name[0]
|
||||
}
|
||||
v := instances.GetOrSetFuncLock(group, func() interface{} {
|
||||
v := localInstances.GetOrSetFuncLock(group, func() interface{} {
|
||||
if config, ok := GetConfig(group); ok {
|
||||
r := New(config)
|
||||
r.group = group
|
||||
r, err := New(config)
|
||||
if err != nil {
|
||||
intlog.Error(context.TODO(), err)
|
||||
return nil
|
||||
}
|
||||
return r
|
||||
}
|
||||
return nil
|
||||
|
||||
15
database/gredis/gredis_message.go
Normal file
15
database/gredis/gredis_message.go
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). 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
|
||||
|
||||
// Message received as result of a PUBLISH command issued by another client.
|
||||
type Message struct {
|
||||
Channel string
|
||||
Pattern string
|
||||
Payload string
|
||||
PayloadSlice []string
|
||||
}
|
||||
82
database/gredis/gredis_redis.go
Normal file
82
database/gredis/gredis_redis.go
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). 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 (
|
||||
"context"
|
||||
"github.com/gogf/gf/container/gvar"
|
||||
"github.com/gogf/gf/errors/gcode"
|
||||
"github.com/gogf/gf/errors/gerror"
|
||||
"github.com/gogf/gf/internal/intlog"
|
||||
)
|
||||
|
||||
// Redis client.
|
||||
type Redis struct {
|
||||
adapter Adapter
|
||||
}
|
||||
|
||||
const (
|
||||
errorNilRedis = `the Redis object is nil`
|
||||
)
|
||||
|
||||
// SetAdapter sets custom adapter for current redis client.
|
||||
func (r *Redis) SetAdapter(adapter Adapter) {
|
||||
if r == nil {
|
||||
return
|
||||
}
|
||||
r.adapter = adapter
|
||||
}
|
||||
|
||||
// GetAdapter returns the adapter that is set in current redis client.
|
||||
func (r *Redis) GetAdapter() Adapter {
|
||||
if r == nil {
|
||||
return nil
|
||||
}
|
||||
return r.adapter
|
||||
}
|
||||
|
||||
// Conn retrieves and returns a connection object for continuous operations.
|
||||
// Note that you should call Close function manually if you do not use this connection any further.
|
||||
func (r *Redis) Conn(ctx context.Context) (*RedisConn, error) {
|
||||
if r == nil {
|
||||
return nil, gerror.NewCode(gcode.CodeInvalidParameter, errorNilRedis)
|
||||
}
|
||||
conn, err := r.adapter.Conn(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &RedisConn{
|
||||
conn: conn,
|
||||
redis: r,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Do sends a command to the server and returns the received reply.
|
||||
// It uses json.Marshal for struct/slice/map type values before committing them to redis.
|
||||
func (r *Redis) Do(ctx context.Context, command string, args ...interface{}) (*gvar.Var, error) {
|
||||
if r == nil {
|
||||
return nil, gerror.NewCode(gcode.CodeInvalidParameter, errorNilRedis)
|
||||
}
|
||||
conn, err := r.Conn(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
if err := conn.Close(ctx); err != nil {
|
||||
intlog.Error(ctx, err)
|
||||
}
|
||||
}()
|
||||
return conn.Do(ctx, command, args...)
|
||||
}
|
||||
|
||||
// Close closes current redis client, closes its connection pool and releases all its related resources.
|
||||
func (r *Redis) Close(ctx context.Context) error {
|
||||
if r == nil {
|
||||
return gerror.NewCode(gcode.CodeInvalidParameter, errorNilRedis)
|
||||
}
|
||||
return r.adapter.Close(ctx)
|
||||
}
|
||||
73
database/gredis/gredis_redis_conn.go
Normal file
73
database/gredis/gredis_redis_conn.go
Normal file
@ -0,0 +1,73 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). 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 (
|
||||
"context"
|
||||
"github.com/gogf/gf/container/gvar"
|
||||
"github.com/gogf/gf/internal/json"
|
||||
"github.com/gogf/gf/os/gtime"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// RedisConn is a connection of redis client.
|
||||
type RedisConn struct {
|
||||
conn Conn
|
||||
redis *Redis
|
||||
}
|
||||
|
||||
// Do sends a command to the server and returns the received reply.
|
||||
// It uses json.Marshal for struct/slice/map type values before committing them to redis.
|
||||
func (c *RedisConn) Do(ctx context.Context, command string, args ...interface{}) (reply *gvar.Var, err error) {
|
||||
var (
|
||||
reflectValue reflect.Value
|
||||
reflectKind reflect.Kind
|
||||
)
|
||||
for k, v := range args {
|
||||
reflectValue = reflect.ValueOf(v)
|
||||
reflectKind = reflectValue.Kind()
|
||||
if reflectKind == reflect.Ptr {
|
||||
reflectValue = reflectValue.Elem()
|
||||
reflectKind = reflectValue.Kind()
|
||||
}
|
||||
switch reflectKind {
|
||||
case
|
||||
reflect.Struct,
|
||||
reflect.Map,
|
||||
reflect.Slice,
|
||||
reflect.Array:
|
||||
// Ignore slice type of: []byte.
|
||||
if _, ok := v.([]byte); !ok {
|
||||
if args[k], err = json.Marshal(v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
timestampMilli1 := gtime.TimestampMilli()
|
||||
reply, err = c.conn.Do(ctx, command, args...)
|
||||
timestampMilli2 := gtime.TimestampMilli()
|
||||
|
||||
// Tracing.
|
||||
c.addTracingItem(ctx, &tracingItem{
|
||||
err: err,
|
||||
command: command,
|
||||
args: args,
|
||||
costMilli: timestampMilli2 - timestampMilli1,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Receive receives a single reply as gvar.Var from the Redis server.
|
||||
func (c *RedisConn) Receive(ctx context.Context) (*gvar.Var, error) {
|
||||
return c.conn.Receive(ctx)
|
||||
}
|
||||
|
||||
// Close puts the connection back to connection pool.
|
||||
func (c *RedisConn) Close(ctx context.Context) error {
|
||||
return c.conn.Close(ctx)
|
||||
}
|
||||
@ -20,16 +20,15 @@ import (
|
||||
|
||||
// tracingItem holds the information for redis tracing.
|
||||
type tracingItem struct {
|
||||
err error
|
||||
commandName string
|
||||
arguments []interface{}
|
||||
costMilli int64
|
||||
err error
|
||||
command string
|
||||
args []interface{}
|
||||
costMilli int64
|
||||
}
|
||||
|
||||
const (
|
||||
tracingInstrumentName = "github.com/gogf/gf/database/gredis"
|
||||
tracingAttrRedisHost = "redis.host"
|
||||
tracingAttrRedisPort = "redis.port"
|
||||
tracingAttrRedisAddress = "redis.address"
|
||||
tracingAttrRedisDb = "redis.db"
|
||||
tracingEventRedisExecution = "redis.execution"
|
||||
tracingEventRedisExecutionCommand = "redis.execution.command"
|
||||
@ -38,32 +37,35 @@ const (
|
||||
)
|
||||
|
||||
// addTracingItem checks and adds redis tracing information to OpenTelemetry.
|
||||
func (c *Conn) addTracingItem(item *tracingItem) {
|
||||
if !gtrace.IsTracingInternal() || !gtrace.IsActivated(c.ctx) {
|
||||
func (c *RedisConn) addTracingItem(ctx context.Context, item *tracingItem) {
|
||||
if !gtrace.IsTracingInternal() || !gtrace.IsActivated(ctx) {
|
||||
return
|
||||
}
|
||||
tr := otel.GetTracerProvider().Tracer(
|
||||
tracingInstrumentName,
|
||||
trace.WithInstrumentationVersion(gf.VERSION),
|
||||
)
|
||||
ctx := c.ctx
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
}
|
||||
_, span := tr.Start(ctx, "Redis."+item.commandName, trace.WithSpanKind(trace.SpanKindInternal))
|
||||
_, span := tr.Start(ctx, "Redis."+item.command, trace.WithSpanKind(trace.SpanKindInternal))
|
||||
defer span.End()
|
||||
if item.err != nil {
|
||||
span.SetStatus(codes.Error, fmt.Sprintf(`%+v`, item.err))
|
||||
}
|
||||
|
||||
span.SetAttributes(gtrace.CommonLabels()...)
|
||||
span.SetAttributes(
|
||||
attribute.String(tracingAttrRedisHost, c.redis.config.Host),
|
||||
attribute.Int(tracingAttrRedisPort, c.redis.config.Port),
|
||||
attribute.Int(tracingAttrRedisDb, c.redis.config.Db),
|
||||
)
|
||||
jsonBytes, _ := json.Marshal(item.arguments)
|
||||
|
||||
if adapter, ok := c.redis.GetAdapter().(*AdapterGoRedis); ok {
|
||||
span.SetAttributes(
|
||||
attribute.String(tracingAttrRedisAddress, adapter.config.Address),
|
||||
attribute.Int(tracingAttrRedisDb, adapter.config.Db),
|
||||
)
|
||||
}
|
||||
|
||||
jsonBytes, _ := json.Marshal(item.args)
|
||||
span.AddEvent(tracingEventRedisExecution, trace.WithAttributes(
|
||||
attribute.String(tracingEventRedisExecutionCommand, item.commandName),
|
||||
attribute.String(tracingEventRedisExecutionCommand, item.command),
|
||||
attribute.String(tracingEventRedisExecutionCost, fmt.Sprintf(`%d ms`, item.costMilli)),
|
||||
attribute.String(tracingEventRedisExecutionArguments, string(jsonBytes)),
|
||||
))
|
||||
21
database/gredis/gredis_subscription.go
Normal file
21
database/gredis/gredis_subscription.go
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). 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 "fmt"
|
||||
|
||||
// Subscription received after a successful subscription to channel.
|
||||
type Subscription struct {
|
||||
Kind string // Can be "subscribe", "unsubscribe", "psubscribe" or "punsubscribe".
|
||||
Channel string // Channel name we have subscribed to.
|
||||
Count int // Number of channels we are currently subscribed to.
|
||||
}
|
||||
|
||||
// String converts current object to a readable string.
|
||||
func (m *Subscription) String() string {
|
||||
return fmt.Sprintf("%s: %s", m.Kind, m.Channel)
|
||||
}
|
||||
@ -7,6 +7,7 @@
|
||||
package gredis_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/container/gvar"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
@ -17,17 +18,18 @@ func Example_autoMarshalUnmarshalMap() {
|
||||
var (
|
||||
err error
|
||||
result *gvar.Var
|
||||
ctx = context.Background()
|
||||
key = "user"
|
||||
data = g.Map{
|
||||
"id": 10000,
|
||||
"name": "john",
|
||||
}
|
||||
)
|
||||
_, err = g.Redis().Do("SET", key, data)
|
||||
_, err = g.Redis().Do(ctx, "SET", key, data)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
result, err = g.Redis().DoVar("GET", key)
|
||||
result, err = g.Redis().Do(ctx, "GET", key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -42,6 +44,7 @@ func Example_autoMarshalUnmarshalStruct() {
|
||||
var (
|
||||
err error
|
||||
result *gvar.Var
|
||||
ctx = context.Background()
|
||||
key = "user"
|
||||
user = &User{
|
||||
Id: 10000,
|
||||
@ -49,11 +52,11 @@ func Example_autoMarshalUnmarshalStruct() {
|
||||
}
|
||||
)
|
||||
|
||||
_, err = g.Redis().Do("SET", key, user)
|
||||
_, err = g.Redis().Do(ctx, "SET", key, user)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
result, err = g.Redis().DoVar("GET", key)
|
||||
result, err = g.Redis().Do(ctx, "GET", key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -73,6 +76,7 @@ func Example_autoMarshalUnmarshalStructSlice() {
|
||||
var (
|
||||
err error
|
||||
result *gvar.Var
|
||||
ctx = context.Background()
|
||||
key = "user-slice"
|
||||
users1 = []User{
|
||||
{
|
||||
@ -86,11 +90,11 @@ func Example_autoMarshalUnmarshalStructSlice() {
|
||||
}
|
||||
)
|
||||
|
||||
_, err = g.Redis().Do("SET", key, users1)
|
||||
_, err = g.Redis().Do(ctx, "SET", key, users1)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
result, err = g.Redis().DoVar("GET", key)
|
||||
result, err = g.Redis().Do(ctx, "GET", key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -106,17 +110,18 @@ func Example_hSet() {
|
||||
var (
|
||||
err error
|
||||
result *gvar.Var
|
||||
ctx = context.Background()
|
||||
key = "user"
|
||||
)
|
||||
_, err = g.Redis().Do("HSET", key, "id", 10000)
|
||||
_, err = g.Redis().Do(ctx, "HSET", key, "id", 10000)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_, err = g.Redis().Do("HSET", key, "name", "john")
|
||||
_, err = g.Redis().Do(ctx, "HSET", key, "name", "john")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
result, err = g.Redis().DoVar("HGETALL", key)
|
||||
result, err = g.Redis().Do(ctx, "HGETALL", key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -128,6 +133,7 @@ func Example_hSet() {
|
||||
|
||||
func Example_hMSet_Map() {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
key = "user_100"
|
||||
data = g.Map{
|
||||
"name": "gf",
|
||||
@ -135,11 +141,11 @@ func Example_hMSet_Map() {
|
||||
"score": 100,
|
||||
}
|
||||
)
|
||||
_, err := g.Redis().Do("HMSET", append(g.Slice{key}, gutil.MapToSlice(data)...)...)
|
||||
_, err := g.Redis().Do(ctx, "HMSET", append(g.Slice{key}, gutil.MapToSlice(data)...)...)
|
||||
if err != nil {
|
||||
g.Log().Fatal(err)
|
||||
}
|
||||
v, err := g.Redis().DoVar("HMGET", key, "name")
|
||||
v, err := g.Redis().Do(ctx, "HMGET", key, "name")
|
||||
if err != nil {
|
||||
g.Log().Fatal(err)
|
||||
}
|
||||
@ -156,6 +162,7 @@ func Example_hMSet_Struct() {
|
||||
Score int `json:"score"`
|
||||
}
|
||||
var (
|
||||
ctx = context.Background()
|
||||
key = "user_100"
|
||||
data = &User{
|
||||
Name: "gf",
|
||||
@ -163,11 +170,11 @@ func Example_hMSet_Struct() {
|
||||
Score: 100,
|
||||
}
|
||||
)
|
||||
_, err := g.Redis().Do("HMSET", append(g.Slice{key}, gutil.StructToSlice(data)...)...)
|
||||
_, err := g.Redis().Do(ctx, "HMSET", append(g.Slice{key}, gutil.StructToSlice(data)...)...)
|
||||
if err != nil {
|
||||
g.Log().Fatal(err)
|
||||
}
|
||||
v, err := g.Redis().DoVar("HMGET", key, "name")
|
||||
v, err := g.Redis().Do(ctx, "HMGET", key, "name")
|
||||
if err != nil {
|
||||
g.Log().Fatal(err)
|
||||
}
|
||||
|
||||
35
database/gredis/gredis_z_unit_config_test.go
Normal file
35
database/gredis/gredis_z_unit_config_test.go
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). 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_test
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/database/gredis"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"github.com/gogf/gf/test/gtest"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Test_ConfigFromMap(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
c, err := gredis.ConfigFromMap(g.Map{
|
||||
`address`: `127.0.0.1:6379`,
|
||||
`db`: `10`,
|
||||
`pass`: `&*^%$#65Gv`,
|
||||
`minIdle`: `10`,
|
||||
`MaxIdle`: `100`,
|
||||
`ReadTimeout`: `10s`,
|
||||
})
|
||||
t.AssertNil(err)
|
||||
t.Assert(c.Address, `127.0.0.1:6379`)
|
||||
t.Assert(c.Db, `10`)
|
||||
t.Assert(c.Pass, `&*^%$#65Gv`)
|
||||
t.Assert(c.MinIdle, 10)
|
||||
t.Assert(c.MaxIdle, 100)
|
||||
t.Assert(c.ReadTimeout, 10*time.Second)
|
||||
})
|
||||
}
|
||||
@ -7,45 +7,61 @@
|
||||
package gredis_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/database/gredis"
|
||||
"github.com/gogf/gf/test/gtest"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
ctx = context.TODO()
|
||||
)
|
||||
|
||||
func TestConn_DoWithTimeout(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
redis := gredis.New(config)
|
||||
redis, err := gredis.New(config)
|
||||
t.AssertNil(err)
|
||||
t.AssertNE(redis, nil)
|
||||
conn := redis.Conn()
|
||||
defer conn.Close()
|
||||
defer redis.Close(ctx)
|
||||
|
||||
_, err := conn.DoWithTimeout(time.Second, "set", "test", "123")
|
||||
t.Assert(err, nil)
|
||||
defer conn.DoWithTimeout(time.Second, "del", "test")
|
||||
conn, err := redis.Conn(ctx)
|
||||
t.AssertNil(err)
|
||||
defer conn.Close(ctx)
|
||||
|
||||
r, err := conn.DoWithTimeout(time.Second, "get", "test")
|
||||
_, err = conn.Do(ctx, "set", "test", "123")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(r, "123")
|
||||
defer conn.Do(ctx, "del", "test")
|
||||
|
||||
r, err := conn.Do(ctx, "get", "test")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(r.String(), "123")
|
||||
})
|
||||
}
|
||||
|
||||
func TestConn_ReceiveVarWithTimeout(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
redis := gredis.New(config)
|
||||
redis, err := gredis.New(config)
|
||||
t.AssertNil(err)
|
||||
t.AssertNE(redis, nil)
|
||||
conn := redis.Conn()
|
||||
defer conn.Close()
|
||||
defer redis.Close(ctx)
|
||||
|
||||
_, err := conn.DoVarWithTimeout(time.Second, "Subscribe", "gf")
|
||||
t.Assert(err, nil)
|
||||
conn, err := redis.Conn(ctx)
|
||||
t.AssertNil(err)
|
||||
defer conn.Close(ctx)
|
||||
|
||||
v, err := redis.DoVarWithTimeout(time.Second, "PUBLISH", "gf", "test")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(v.String(), "1")
|
||||
_, err = conn.Do(ctx, "Subscribe", "gf")
|
||||
t.AssertNil(err)
|
||||
|
||||
v, err := redis.Do(ctx, "PUBLISH", "gf", "test")
|
||||
|
||||
v, err = conn.Receive(ctx)
|
||||
t.AssertNil(err)
|
||||
t.Assert(v.Val().(*gredis.Subscription).Channel, "gf")
|
||||
|
||||
v, err = conn.Receive(ctx)
|
||||
t.AssertNil(err)
|
||||
t.Assert(v.Val().(*gredis.Message).Channel, "gf")
|
||||
t.Assert(v.Val().(*gredis.Message).Payload, "test")
|
||||
|
||||
v, _ = conn.ReceiveVar()
|
||||
t.Assert(len(v.Strings()), 3)
|
||||
t.Assert(v.Strings()[2], "test")
|
||||
})
|
||||
}
|
||||
|
||||
@ -23,89 +23,67 @@ import (
|
||||
|
||||
var (
|
||||
config = &gredis.Config{
|
||||
Host: "127.0.0.1",
|
||||
Port: 6379,
|
||||
Db: 1,
|
||||
Address: `:6379`,
|
||||
Db: 1,
|
||||
}
|
||||
)
|
||||
|
||||
func Test_NewClose(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
redis := gredis.New(config)
|
||||
redis, err := gredis.New(config)
|
||||
t.AssertNil(err)
|
||||
t.AssertNE(redis, nil)
|
||||
err := redis.Close()
|
||||
t.Assert(err, nil)
|
||||
|
||||
err = redis.Close(ctx)
|
||||
t.AssertNil(err)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Do(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
redis := gredis.New(config)
|
||||
defer redis.Close()
|
||||
_, err := redis.Do("SET", "k", "v")
|
||||
redis, err := gredis.New(config)
|
||||
t.AssertNil(err)
|
||||
t.AssertNE(redis, nil)
|
||||
defer redis.Close(ctx)
|
||||
|
||||
_, err = redis.Do(ctx, "SET", "k", "v")
|
||||
t.Assert(err, nil)
|
||||
|
||||
r, err := redis.Do("GET", "k")
|
||||
r, err := redis.Do(ctx, "GET", "k")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(r, []byte("v"))
|
||||
|
||||
_, err = redis.Do("DEL", "k")
|
||||
_, err = redis.Do(ctx, "DEL", "k")
|
||||
t.Assert(err, nil)
|
||||
r, err = redis.Do("GET", "k")
|
||||
r, err = redis.Do(ctx, "GET", "k")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(r, nil)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Stats(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
redis := gredis.New(config)
|
||||
defer redis.Close()
|
||||
redis.SetMaxIdle(2)
|
||||
redis.SetMaxActive(100)
|
||||
redis.SetIdleTimeout(500 * time.Millisecond)
|
||||
redis.SetMaxConnLifetime(500 * time.Millisecond)
|
||||
|
||||
array := make([]*gredis.Conn, 0)
|
||||
for i := 0; i < 10; i++ {
|
||||
array = append(array, redis.Conn())
|
||||
}
|
||||
stats := redis.Stats()
|
||||
t.Assert(stats.ActiveCount, 10)
|
||||
t.Assert(stats.IdleCount, 0)
|
||||
for i := 0; i < 10; i++ {
|
||||
array[i].Close()
|
||||
}
|
||||
stats = redis.Stats()
|
||||
t.Assert(stats.ActiveCount, 2)
|
||||
t.Assert(stats.IdleCount, 2)
|
||||
//time.Sleep(3000*time.Millisecond)
|
||||
//stats = redis.Stats()
|
||||
//fmt.Println(stats)
|
||||
//t.Assert(stats.ActiveCount, 0)
|
||||
//t.Assert(stats.IdleCount, 0)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Conn(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
redis := gredis.New(config)
|
||||
defer redis.Close()
|
||||
conn := redis.Conn()
|
||||
defer conn.Close()
|
||||
redis, err := gredis.New(config)
|
||||
t.AssertNil(err)
|
||||
t.AssertNE(redis, nil)
|
||||
defer redis.Close(ctx)
|
||||
|
||||
conn, err := redis.Conn(ctx)
|
||||
t.AssertNil(err)
|
||||
defer conn.Close(ctx)
|
||||
|
||||
key := gconv.String(gtime.TimestampNano())
|
||||
value := []byte("v")
|
||||
r, err := conn.Do("SET", key, value)
|
||||
r, err := conn.Do(ctx, "SET", key, value)
|
||||
t.Assert(err, nil)
|
||||
|
||||
r, err = conn.Do("GET", key)
|
||||
r, err = conn.Do(ctx, "GET", key)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(r, value)
|
||||
|
||||
_, err = conn.Do("DEL", key)
|
||||
_, err = conn.Do(ctx, "DEL", key)
|
||||
t.Assert(err, nil)
|
||||
r, err = conn.Do("GET", key)
|
||||
r, err = conn.Do(ctx, "GET", key)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(r, nil)
|
||||
})
|
||||
@ -116,22 +94,24 @@ func Test_Instance(t *testing.T) {
|
||||
group := "my-test"
|
||||
gredis.SetConfig(config, group)
|
||||
defer gredis.RemoveConfig(group)
|
||||
|
||||
redis := gredis.Instance(group)
|
||||
defer redis.Close()
|
||||
defer redis.Close(ctx)
|
||||
|
||||
conn := redis.Conn()
|
||||
defer conn.Close()
|
||||
conn, err := redis.Conn(ctx)
|
||||
t.AssertNil(err)
|
||||
defer conn.Close(ctx)
|
||||
|
||||
_, err := conn.Do("SET", "k", "v")
|
||||
_, err = conn.Do(ctx, "SET", "k", "v")
|
||||
t.Assert(err, nil)
|
||||
|
||||
r, err := conn.Do("GET", "k")
|
||||
r, err := conn.Do(ctx, "GET", "k")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(r, []byte("v"))
|
||||
|
||||
_, err = conn.Do("DEL", "k")
|
||||
_, err = conn.Do(ctx, "DEL", "k")
|
||||
t.Assert(err, nil)
|
||||
r, err = conn.Do("GET", "k")
|
||||
r, err = conn.Do(ctx, "GET", "k")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(r, nil)
|
||||
})
|
||||
@ -140,51 +120,66 @@ func Test_Instance(t *testing.T) {
|
||||
func Test_Error(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
config1 := &gredis.Config{
|
||||
Host: "192.111.0.2",
|
||||
Port: 6379,
|
||||
Db: 1,
|
||||
ConnectTimeout: time.Second,
|
||||
Address: "192.111.0.2:6379",
|
||||
Db: 1,
|
||||
DialTimeout: time.Second,
|
||||
}
|
||||
redis := gredis.New(config1)
|
||||
_, err := redis.Do("info")
|
||||
redis, err := gredis.New(config1)
|
||||
t.AssertNil(err)
|
||||
t.AssertNE(redis, nil)
|
||||
defer redis.Close(ctx)
|
||||
|
||||
_, err = redis.Do(ctx, "info")
|
||||
t.AssertNE(err, nil)
|
||||
|
||||
config1 = &gredis.Config{
|
||||
Host: "127.0.0.1",
|
||||
Port: 6379,
|
||||
Db: 100,
|
||||
Address: "127.0.0.1:6379",
|
||||
Db: 100,
|
||||
}
|
||||
redis = gredis.New(config1)
|
||||
_, err = redis.Do("info")
|
||||
redis, err = gredis.New(config1)
|
||||
t.AssertNil(err)
|
||||
t.AssertNE(redis, nil)
|
||||
defer redis.Close(ctx)
|
||||
|
||||
_, err = redis.Do(ctx, "info")
|
||||
t.AssertNE(err, nil)
|
||||
|
||||
redis = gredis.Instance("gf")
|
||||
t.Assert(redis == nil, true)
|
||||
gredis.ClearConfig()
|
||||
|
||||
redis = gredis.New(config)
|
||||
defer redis.Close()
|
||||
_, err = redis.DoVar("SET", "k", "v")
|
||||
redis, err = gredis.New(config)
|
||||
t.AssertNil(err)
|
||||
t.AssertNE(redis, nil)
|
||||
defer redis.Close(ctx)
|
||||
|
||||
_, err = redis.Do(ctx, "SET", "k", "v")
|
||||
t.Assert(err, nil)
|
||||
|
||||
v, err := redis.DoVar("GET", "k")
|
||||
v, err := redis.Do(ctx, "GET", "k")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(v.String(), "v")
|
||||
|
||||
conn := redis.Conn()
|
||||
defer conn.Close()
|
||||
_, err = conn.DoVar("SET", "k", "v")
|
||||
t.Assert(err, nil)
|
||||
conn, err := redis.Conn(ctx)
|
||||
t.AssertNil(err)
|
||||
defer conn.Close(ctx)
|
||||
_, err = conn.Do(ctx, "SET", "k", "v")
|
||||
t.AssertNil(err)
|
||||
|
||||
_, err = conn.DoVar("Subscribe", "gf")
|
||||
t.Assert(err, nil)
|
||||
_, err = conn.Do(ctx, "Subscribe", "gf")
|
||||
t.AssertNil(err)
|
||||
|
||||
_, err = redis.DoVar("PUBLISH", "gf", "test")
|
||||
t.Assert(err, nil)
|
||||
_, err = redis.Do(ctx, "PUBLISH", "gf", "test")
|
||||
t.AssertNil(err)
|
||||
|
||||
v, _ = conn.ReceiveVar()
|
||||
t.Assert(len(v.Strings()), 3)
|
||||
t.Assert(v.Strings()[2], "test")
|
||||
v, err = conn.Receive(ctx)
|
||||
t.AssertNil(err)
|
||||
t.Assert(v.Val().(*gredis.Subscription).Channel, "gf")
|
||||
|
||||
v, err = conn.Receive(ctx)
|
||||
t.AssertNil(err)
|
||||
t.Assert(v.Val().(*gredis.Message).Channel, "gf")
|
||||
t.Assert(v.Val().(*gredis.Message).Payload, "test")
|
||||
|
||||
time.Sleep(time.Second)
|
||||
})
|
||||
@ -192,23 +187,27 @@ func Test_Error(t *testing.T) {
|
||||
|
||||
func Test_Bool(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
redis := gredis.New(config)
|
||||
redis, err := gredis.New(config)
|
||||
t.AssertNil(err)
|
||||
t.AssertNE(redis, nil)
|
||||
defer redis.Close(ctx)
|
||||
|
||||
defer func() {
|
||||
redis.Do("DEL", "key-true")
|
||||
redis.Do("DEL", "key-false")
|
||||
redis.Do(ctx, "DEL", "key-true")
|
||||
redis.Do(ctx, "DEL", "key-false")
|
||||
}()
|
||||
|
||||
_, err := redis.Do("SET", "key-true", true)
|
||||
_, err = redis.Do(ctx, "SET", "key-true", true)
|
||||
t.Assert(err, nil)
|
||||
|
||||
_, err = redis.Do("SET", "key-false", false)
|
||||
_, err = redis.Do(ctx, "SET", "key-false", false)
|
||||
t.Assert(err, nil)
|
||||
|
||||
r, err := redis.DoVar("GET", "key-true")
|
||||
r, err := redis.Do(ctx, "GET", "key-true")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(r.Bool(), true)
|
||||
|
||||
r, err = redis.DoVar("GET", "key-false")
|
||||
r, err = redis.Do(ctx, "GET", "key-false")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(r.Bool(), false)
|
||||
})
|
||||
@ -216,14 +215,18 @@ func Test_Bool(t *testing.T) {
|
||||
|
||||
func Test_Int(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
redis := gredis.New(config)
|
||||
key := guid.S()
|
||||
defer redis.Do("DEL", key)
|
||||
redis, err := gredis.New(config)
|
||||
t.AssertNil(err)
|
||||
t.AssertNE(redis, nil)
|
||||
defer redis.Close(ctx)
|
||||
|
||||
_, err := redis.Do("SET", key, 1)
|
||||
key := guid.S()
|
||||
defer redis.Do(ctx, "DEL", key)
|
||||
|
||||
_, err = redis.Do(ctx, "SET", key, 1)
|
||||
t.Assert(err, nil)
|
||||
|
||||
r, err := redis.DoVar("GET", key)
|
||||
r, err := redis.Do(ctx, "GET", key)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(r.Int(), 1)
|
||||
})
|
||||
@ -231,14 +234,18 @@ func Test_Int(t *testing.T) {
|
||||
|
||||
func Test_HSet(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
redis := gredis.New(config)
|
||||
key := guid.S()
|
||||
defer redis.Do("DEL", key)
|
||||
redis, err := gredis.New(config)
|
||||
t.AssertNil(err)
|
||||
t.AssertNE(redis, nil)
|
||||
defer redis.Close(ctx)
|
||||
|
||||
_, err := redis.Do("HSET", key, "name", "john")
|
||||
key := guid.S()
|
||||
defer redis.Do(ctx, "DEL", key)
|
||||
|
||||
_, err = redis.Do(ctx, "HSET", key, "name", "john")
|
||||
t.Assert(err, nil)
|
||||
|
||||
r, err := redis.DoVar("HGETALL", key)
|
||||
r, err := redis.Do(ctx, "HGETALL", key)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(r.Strings(), g.ArrayStr{"name", "john"})
|
||||
})
|
||||
@ -247,18 +254,20 @@ func Test_HSet(t *testing.T) {
|
||||
func Test_HGetAll1(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var (
|
||||
err error
|
||||
key = guid.S()
|
||||
redis = gredis.New(config)
|
||||
key = guid.S()
|
||||
)
|
||||
defer redis.Do("DEL", key)
|
||||
redis, err := gredis.New(config)
|
||||
t.AssertNil(err)
|
||||
t.AssertNE(redis, nil)
|
||||
defer redis.Close(ctx)
|
||||
defer redis.Do(ctx, "DEL", key)
|
||||
|
||||
_, err = redis.Do("HSET", key, "id", 100)
|
||||
_, err = redis.Do(ctx, "HSET", key, "id", 100)
|
||||
t.Assert(err, nil)
|
||||
_, err = redis.Do("HSET", key, "name", "john")
|
||||
_, err = redis.Do(ctx, "HSET", key, "name", "john")
|
||||
t.Assert(err, nil)
|
||||
|
||||
r, err := redis.DoVar("HGETALL", key)
|
||||
r, err := redis.Do(ctx, "HGETALL", key)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(r.Map(), g.MapStrAny{
|
||||
"id": 100,
|
||||
@ -270,18 +279,20 @@ func Test_HGetAll1(t *testing.T) {
|
||||
func Test_HGetAll2(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var (
|
||||
err error
|
||||
key = guid.S()
|
||||
redis = gredis.New(config)
|
||||
key = guid.S()
|
||||
)
|
||||
defer redis.Do("DEL", key)
|
||||
redis, err := gredis.New(config)
|
||||
t.AssertNil(err)
|
||||
t.AssertNE(redis, nil)
|
||||
defer redis.Close(ctx)
|
||||
defer redis.Do(ctx, "DEL", key)
|
||||
|
||||
_, err = redis.Do("HSET", key, "id", 100)
|
||||
_, err = redis.Do(ctx, "HSET", key, "id", 100)
|
||||
t.Assert(err, nil)
|
||||
_, err = redis.Do("HSET", key, "name", "john")
|
||||
_, err = redis.Do(ctx, "HSET", key, "name", "john")
|
||||
t.Assert(err, nil)
|
||||
|
||||
result, err := redis.DoVar("HGETALL", key)
|
||||
result, err := redis.Do(ctx, "HGETALL", key)
|
||||
t.Assert(err, nil)
|
||||
|
||||
t.Assert(gconv.Uint(result.MapStrVar()["id"]), 100)
|
||||
@ -293,20 +304,22 @@ func Test_HMSet(t *testing.T) {
|
||||
// map
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var (
|
||||
err error
|
||||
key = guid.S()
|
||||
redis = gredis.New(config)
|
||||
data = g.Map{
|
||||
key = guid.S()
|
||||
data = g.Map{
|
||||
"name": "gf",
|
||||
"sex": 0,
|
||||
"score": 100,
|
||||
}
|
||||
)
|
||||
defer redis.Do("DEL", key)
|
||||
redis, err := gredis.New(config)
|
||||
t.AssertNil(err)
|
||||
t.AssertNE(redis, nil)
|
||||
defer redis.Close(ctx)
|
||||
defer redis.Do(ctx, "DEL", key)
|
||||
|
||||
_, err = redis.Do("HMSET", append(g.Slice{key}, gutil.MapToSlice(data)...)...)
|
||||
_, err = redis.Do(ctx, "HMSET", append(g.Slice{key}, gutil.MapToSlice(data)...)...)
|
||||
t.Assert(err, nil)
|
||||
v, err := redis.DoVar("HMGET", key, "name")
|
||||
v, err := redis.Do(ctx, "HMGET", key, "name")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(v.Slice(), g.Slice{data["name"]})
|
||||
})
|
||||
@ -318,48 +331,53 @@ func Test_HMSet(t *testing.T) {
|
||||
Score int `json:"score"`
|
||||
}
|
||||
var (
|
||||
err error
|
||||
key = guid.S()
|
||||
redis = gredis.New(config)
|
||||
data = &User{
|
||||
key = guid.S()
|
||||
data = &User{
|
||||
Name: "gf",
|
||||
Sex: 0,
|
||||
Score: 100,
|
||||
}
|
||||
)
|
||||
defer redis.Do("DEL", key)
|
||||
redis, err := gredis.New(config)
|
||||
t.AssertNil(err)
|
||||
t.AssertNE(redis, nil)
|
||||
defer redis.Close(ctx)
|
||||
defer redis.Do(ctx, "DEL", key)
|
||||
|
||||
_, err = redis.Do("HMSET", append(g.Slice{key}, gutil.StructToSlice(data)...)...)
|
||||
_, err = redis.Do(ctx, "HMSET", append(g.Slice{key}, gutil.StructToSlice(data)...)...)
|
||||
t.Assert(err, nil)
|
||||
v, err := redis.DoVar("HMGET", key, "name")
|
||||
v, err := redis.Do(ctx, "HMGET", key, "name")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(v.Slice(), g.Slice{data.Name})
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Auto_Marshal(t *testing.T) {
|
||||
var (
|
||||
err error
|
||||
redis = gredis.New(config)
|
||||
key = guid.S()
|
||||
)
|
||||
defer redis.Do("DEL", key)
|
||||
|
||||
type User struct {
|
||||
Id int
|
||||
Name string
|
||||
}
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var (
|
||||
key = guid.S()
|
||||
)
|
||||
redis, err := gredis.New(config)
|
||||
t.AssertNil(err)
|
||||
t.AssertNE(redis, nil)
|
||||
defer redis.Close(ctx)
|
||||
|
||||
defer redis.Do(ctx, "DEL", key)
|
||||
|
||||
type User struct {
|
||||
Id int
|
||||
Name string
|
||||
}
|
||||
|
||||
user := &User{
|
||||
Id: 10000,
|
||||
Name: "john",
|
||||
}
|
||||
|
||||
_, err = redis.Do("SET", key, user)
|
||||
_, err = redis.Do(ctx, "SET", key, user)
|
||||
t.Assert(err, nil)
|
||||
|
||||
r, err := redis.DoVar("GET", key)
|
||||
r, err := redis.Do(ctx, "GET", key)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(r.Map(), g.MapStrAny{
|
||||
"Id": user.Id,
|
||||
@ -374,22 +392,20 @@ func Test_Auto_Marshal(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_Auto_MarshalSlice(t *testing.T) {
|
||||
var (
|
||||
err error
|
||||
redis = gredis.New(config)
|
||||
key = guid.S()
|
||||
)
|
||||
defer redis.Do("DEL", key)
|
||||
|
||||
type User struct {
|
||||
Id int
|
||||
Name string
|
||||
}
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var (
|
||||
key = "user-slice"
|
||||
)
|
||||
redis, err := gredis.New(config)
|
||||
t.AssertNil(err)
|
||||
t.AssertNE(redis, nil)
|
||||
defer redis.Do(ctx, "DEL", key)
|
||||
type User struct {
|
||||
Id int
|
||||
Name string
|
||||
}
|
||||
var (
|
||||
result *gvar.Var
|
||||
key = "user-slice"
|
||||
users1 = []User{
|
||||
{
|
||||
Id: 1,
|
||||
@ -402,10 +418,10 @@ func Test_Auto_MarshalSlice(t *testing.T) {
|
||||
}
|
||||
)
|
||||
|
||||
_, err = redis.Do("SET", key, users1)
|
||||
_, err = redis.Do(ctx, "SET", key, users1)
|
||||
t.Assert(err, nil)
|
||||
|
||||
result, err = redis.DoVar("GET", key)
|
||||
result, err = redis.Do(ctx, "GET", key)
|
||||
t.Assert(err, nil)
|
||||
|
||||
var users2 []User
|
||||
|
||||
@ -10,21 +10,11 @@ import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/errors/gcode"
|
||||
"github.com/gogf/gf/errors/gerror"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/util/gutil"
|
||||
|
||||
"github.com/gogf/gf/container/gvar"
|
||||
"github.com/gogf/gf/os/gtime"
|
||||
"github.com/gogf/gf/util/gconv"
|
||||
)
|
||||
|
||||
// Value returns the json value.
|
||||
// Deprecated, use Interface instead.
|
||||
func (j *Json) Value() interface{} {
|
||||
return j.Interface()
|
||||
}
|
||||
|
||||
// Interface returns the json value.
|
||||
func (j *Json) Interface() interface{} {
|
||||
j.mu.RLock()
|
||||
@ -34,7 +24,7 @@ func (j *Json) Interface() interface{} {
|
||||
|
||||
// Var returns the json value as *gvar.Var.
|
||||
func (j *Json) Var() *gvar.Var {
|
||||
return gvar.New(j.Value())
|
||||
return gvar.New(j.Interface())
|
||||
}
|
||||
|
||||
// IsNil checks whether the value pointed by <j> is nil.
|
||||
@ -52,7 +42,7 @@ func (j *Json) IsNil() bool {
|
||||
// "list.10", "array.0.name", "array.0.1.id".
|
||||
//
|
||||
// It returns a default value specified by <def> if value for <pattern> is not found.
|
||||
func (j *Json) Get(pattern string, def ...interface{}) interface{} {
|
||||
func (j *Json) Get(pattern string, def ...interface{}) *gvar.Var {
|
||||
j.mu.RLock()
|
||||
defer j.mu.RUnlock()
|
||||
|
||||
@ -68,47 +58,10 @@ func (j *Json) Get(pattern string, def ...interface{}) interface{} {
|
||||
result = j.getPointerByPatternWithoutViolenceCheck(pattern)
|
||||
}
|
||||
if result != nil {
|
||||
return *result
|
||||
return gvar.New(*result)
|
||||
}
|
||||
if len(def) > 0 {
|
||||
return def[0]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetVar returns a gvar.Var with value by given <pattern>.
|
||||
func (j *Json) GetVar(pattern string, def ...interface{}) *gvar.Var {
|
||||
return gvar.New(j.Get(pattern, def...))
|
||||
}
|
||||
|
||||
// GetVars returns []*gvar.Var with value by given <pattern>.
|
||||
func (j *Json) GetVars(pattern string, def ...interface{}) []*gvar.Var {
|
||||
return gvar.New(j.Get(pattern, def...)).Vars()
|
||||
}
|
||||
|
||||
// GetMap retrieves and returns the value by specified <pattern> as map[string]interface{}.
|
||||
func (j *Json) GetMap(pattern string, def ...interface{}) map[string]interface{} {
|
||||
result := j.Get(pattern, def...)
|
||||
if result != nil {
|
||||
return gconv.Map(result)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetMapStrStr retrieves and returns the value by specified <pattern> as map[string]string.
|
||||
func (j *Json) GetMapStrStr(pattern string, def ...interface{}) map[string]string {
|
||||
result := j.Get(pattern, def...)
|
||||
if result != nil {
|
||||
return gconv.MapStrStr(result)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetMaps retrieves and returns the value by specified <pattern> as []map[string]interface{}.
|
||||
func (j *Json) GetMaps(pattern string, def ...interface{}) []map[string]interface{} {
|
||||
result := j.Get(pattern, def...)
|
||||
if result != nil {
|
||||
return gconv.Maps(result)
|
||||
return gvar.New(def[0])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -116,13 +69,13 @@ func (j *Json) GetMaps(pattern string, def ...interface{}) []map[string]interfac
|
||||
// GetJson gets the value by specified <pattern>,
|
||||
// and converts it to a un-concurrent-safe Json object.
|
||||
func (j *Json) GetJson(pattern string, def ...interface{}) *Json {
|
||||
return New(j.Get(pattern, def...))
|
||||
return New(j.Get(pattern, def...).Val())
|
||||
}
|
||||
|
||||
// GetJsons gets the value by specified <pattern>,
|
||||
// and converts it to a slice of un-concurrent-safe Json object.
|
||||
func (j *Json) GetJsons(pattern string, def ...interface{}) []*Json {
|
||||
array := j.GetArray(pattern, def...)
|
||||
array := j.Get(pattern, def...).Array()
|
||||
if len(array) > 0 {
|
||||
jsonSlice := make([]*Json, len(array))
|
||||
for i := 0; i < len(array); i++ {
|
||||
@ -136,7 +89,7 @@ func (j *Json) GetJsons(pattern string, def ...interface{}) []*Json {
|
||||
// GetJsonMap gets the value by specified <pattern>,
|
||||
// and converts it to a map of un-concurrent-safe Json object.
|
||||
func (j *Json) GetJsonMap(pattern string, def ...interface{}) map[string]*Json {
|
||||
m := j.GetMap(pattern, def...)
|
||||
m := j.Get(pattern, def...).Map()
|
||||
if len(m) > 0 {
|
||||
jsonMap := make(map[string]*Json, len(m))
|
||||
for k, v := range m {
|
||||
@ -147,126 +100,6 @@ func (j *Json) GetJsonMap(pattern string, def ...interface{}) map[string]*Json {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetArray retrieves the value by specified <pattern>,
|
||||
// and converts it to a slice of []interface{}.
|
||||
func (j *Json) GetArray(pattern string, def ...interface{}) []interface{} {
|
||||
return gconv.Interfaces(j.Get(pattern, def...))
|
||||
}
|
||||
|
||||
// GetString retrieves the value by specified <pattern> and converts it to string.
|
||||
func (j *Json) GetString(pattern string, def ...interface{}) string {
|
||||
return gconv.String(j.Get(pattern, def...))
|
||||
}
|
||||
|
||||
// GetBytes retrieves the value by specified <pattern> and converts it to []byte.
|
||||
func (j *Json) GetBytes(pattern string, def ...interface{}) []byte {
|
||||
return gconv.Bytes(j.Get(pattern, def...))
|
||||
}
|
||||
|
||||
// GetBool retrieves the value by specified <pattern>,
|
||||
// converts and returns it as bool.
|
||||
// It returns false when value is: "", 0, false, off, nil;
|
||||
// or returns true instead.
|
||||
func (j *Json) GetBool(pattern string, def ...interface{}) bool {
|
||||
return gconv.Bool(j.Get(pattern, def...))
|
||||
}
|
||||
|
||||
// GetInt retrieves the value by specified <pattern> and converts it to int.
|
||||
func (j *Json) GetInt(pattern string, def ...interface{}) int {
|
||||
return gconv.Int(j.Get(pattern, def...))
|
||||
}
|
||||
|
||||
// GetInt8 retrieves the value by specified <pattern> and converts it to int8.
|
||||
func (j *Json) GetInt8(pattern string, def ...interface{}) int8 {
|
||||
return gconv.Int8(j.Get(pattern, def...))
|
||||
}
|
||||
|
||||
// GetInt16 retrieves the value by specified <pattern> and converts it to int16.
|
||||
func (j *Json) GetInt16(pattern string, def ...interface{}) int16 {
|
||||
return gconv.Int16(j.Get(pattern, def...))
|
||||
}
|
||||
|
||||
// GetInt32 retrieves the value by specified <pattern> and converts it to int32.
|
||||
func (j *Json) GetInt32(pattern string, def ...interface{}) int32 {
|
||||
return gconv.Int32(j.Get(pattern, def...))
|
||||
}
|
||||
|
||||
// GetInt64 retrieves the value by specified <pattern> and converts it to int64.
|
||||
func (j *Json) GetInt64(pattern string, def ...interface{}) int64 {
|
||||
return gconv.Int64(j.Get(pattern, def...))
|
||||
}
|
||||
|
||||
// GetUint retrieves the value by specified <pattern> and converts it to uint.
|
||||
func (j *Json) GetUint(pattern string, def ...interface{}) uint {
|
||||
return gconv.Uint(j.Get(pattern, def...))
|
||||
}
|
||||
|
||||
// GetUint8 retrieves the value by specified <pattern> and converts it to uint8.
|
||||
func (j *Json) GetUint8(pattern string, def ...interface{}) uint8 {
|
||||
return gconv.Uint8(j.Get(pattern, def...))
|
||||
}
|
||||
|
||||
// GetUint16 retrieves the value by specified <pattern> and converts it to uint16.
|
||||
func (j *Json) GetUint16(pattern string, def ...interface{}) uint16 {
|
||||
return gconv.Uint16(j.Get(pattern, def...))
|
||||
}
|
||||
|
||||
// GetUint32 retrieves the value by specified <pattern> and converts it to uint32.
|
||||
func (j *Json) GetUint32(pattern string, def ...interface{}) uint32 {
|
||||
return gconv.Uint32(j.Get(pattern, def...))
|
||||
}
|
||||
|
||||
// GetUint64 retrieves the value by specified <pattern> and converts it to uint64.
|
||||
func (j *Json) GetUint64(pattern string, def ...interface{}) uint64 {
|
||||
return gconv.Uint64(j.Get(pattern, def...))
|
||||
}
|
||||
|
||||
// GetFloat32 retrieves the value by specified <pattern> and converts it to float32.
|
||||
func (j *Json) GetFloat32(pattern string, def ...interface{}) float32 {
|
||||
return gconv.Float32(j.Get(pattern, def...))
|
||||
}
|
||||
|
||||
// GetFloat64 retrieves the value by specified <pattern> and converts it to float64.
|
||||
func (j *Json) GetFloat64(pattern string, def ...interface{}) float64 {
|
||||
return gconv.Float64(j.Get(pattern, def...))
|
||||
}
|
||||
|
||||
// GetFloats retrieves the value by specified <pattern> and converts it to []float64.
|
||||
func (j *Json) GetFloats(pattern string, def ...interface{}) []float64 {
|
||||
return gconv.Floats(j.Get(pattern, def...))
|
||||
}
|
||||
|
||||
// GetInts retrieves the value by specified <pattern> and converts it to []int.
|
||||
func (j *Json) GetInts(pattern string, def ...interface{}) []int {
|
||||
return gconv.Ints(j.Get(pattern, def...))
|
||||
}
|
||||
|
||||
// GetStrings retrieves the value by specified <pattern> and converts it to []string.
|
||||
func (j *Json) GetStrings(pattern string, def ...interface{}) []string {
|
||||
return gconv.Strings(j.Get(pattern, def...))
|
||||
}
|
||||
|
||||
// GetInterfaces is alias of GetArray.
|
||||
// See GetArray.
|
||||
func (j *Json) GetInterfaces(pattern string, def ...interface{}) []interface{} {
|
||||
return gconv.Interfaces(j.Get(pattern, def...))
|
||||
}
|
||||
|
||||
// GetTime retrieves the value by specified <pattern> and converts it to time.Time.
|
||||
func (j *Json) GetTime(pattern string, format ...string) time.Time {
|
||||
return gconv.Time(j.Get(pattern), format...)
|
||||
}
|
||||
|
||||
// GetDuration retrieves the value by specified <pattern> and converts it to time.Duration.
|
||||
func (j *Json) GetDuration(pattern string, def ...interface{}) time.Duration {
|
||||
return gconv.Duration(j.Get(pattern, def...))
|
||||
}
|
||||
|
||||
// GetGTime retrieves the value by specified <pattern> and converts it to *gtime.Time.
|
||||
func (j *Json) GetGTime(pattern string, format ...string) *gtime.Time {
|
||||
return gconv.GTime(j.Get(pattern), format...)
|
||||
}
|
||||
|
||||
// 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 {
|
||||
@ -322,101 +155,22 @@ func (j *Json) Append(pattern string, value interface{}) error {
|
||||
return gerror.NewCodef(gcode.CodeInvalidParameter, "invalid variable type of %s", pattern)
|
||||
}
|
||||
|
||||
// GetStruct retrieves the value by specified <pattern> and converts it to specified object
|
||||
// <pointer>. The <pointer> should be the pointer to an object.
|
||||
func (j *Json) GetStruct(pattern string, pointer interface{}, mapping ...map[string]string) error {
|
||||
return gconv.Struct(j.Get(pattern), pointer, mapping...)
|
||||
}
|
||||
|
||||
// GetStructs converts any slice to given struct slice.
|
||||
func (j *Json) GetStructs(pattern string, pointer interface{}, mapping ...map[string]string) error {
|
||||
return gconv.Structs(j.Get(pattern), pointer, mapping...)
|
||||
}
|
||||
|
||||
// GetScan automatically calls Struct or Structs function according to the type of parameter
|
||||
// <pointer> to implement the converting..
|
||||
func (j *Json) GetScan(pattern string, pointer interface{}, mapping ...map[string]string) error {
|
||||
return gconv.Scan(j.Get(pattern), pointer, mapping...)
|
||||
}
|
||||
|
||||
// GetScanDeep automatically calls StructDeep or StructsDeep function according to the type of
|
||||
// parameter <pointer> to implement the converting..
|
||||
func (j *Json) GetScanDeep(pattern string, pointer interface{}, mapping ...map[string]string) error {
|
||||
return gconv.ScanDeep(j.Get(pattern), pointer, mapping...)
|
||||
}
|
||||
|
||||
// GetMapToMap retrieves the value by specified <pattern> and converts it to specified map variable.
|
||||
// See gconv.MapToMap.
|
||||
func (j *Json) GetMapToMap(pattern string, pointer interface{}, mapping ...map[string]string) error {
|
||||
return gconv.MapToMap(j.Get(pattern), pointer, mapping...)
|
||||
}
|
||||
|
||||
// GetMapToMaps retrieves the value by specified <pattern> and converts it to specified map slice
|
||||
// variable.
|
||||
// See gconv.MapToMaps.
|
||||
func (j *Json) GetMapToMaps(pattern string, pointer interface{}, mapping ...map[string]string) error {
|
||||
return gconv.MapToMaps(j.Get(pattern), pointer, mapping...)
|
||||
}
|
||||
|
||||
// GetMapToMapsDeep retrieves the value by specified <pattern> and converts it to specified map slice
|
||||
// variable recursively.
|
||||
// See gconv.MapToMapsDeep.
|
||||
func (j *Json) GetMapToMapsDeep(pattern string, pointer interface{}, mapping ...map[string]string) error {
|
||||
return gconv.MapToMapsDeep(j.Get(pattern), pointer, mapping...)
|
||||
}
|
||||
|
||||
// Map converts current Json object to map[string]interface{}.
|
||||
// It returns nil if fails.
|
||||
func (j *Json) Map() map[string]interface{} {
|
||||
j.mu.RLock()
|
||||
defer j.mu.RUnlock()
|
||||
return gconv.Map(*(j.p))
|
||||
return j.Var().Map()
|
||||
}
|
||||
|
||||
// Array converts current Json object to []interface{}.
|
||||
// It returns nil if fails.
|
||||
func (j *Json) Array() []interface{} {
|
||||
j.mu.RLock()
|
||||
defer j.mu.RUnlock()
|
||||
return gconv.Interfaces(*(j.p))
|
||||
}
|
||||
|
||||
// Struct converts current Json object to specified object.
|
||||
// The <pointer> should be a pointer type of *struct.
|
||||
func (j *Json) Struct(pointer interface{}, mapping ...map[string]string) error {
|
||||
j.mu.RLock()
|
||||
defer j.mu.RUnlock()
|
||||
return gconv.Struct(*(j.p), pointer, mapping...)
|
||||
}
|
||||
|
||||
// Structs converts current Json object to specified object slice.
|
||||
// The <pointer> should be a pointer type of []struct/*struct.
|
||||
func (j *Json) Structs(pointer interface{}, mapping ...map[string]string) error {
|
||||
j.mu.RLock()
|
||||
defer j.mu.RUnlock()
|
||||
return gconv.Structs(*(j.p), pointer, mapping...)
|
||||
return j.Var().Array()
|
||||
}
|
||||
|
||||
// Scan automatically calls Struct or Structs function according to the type of parameter
|
||||
// <pointer> to implement the converting..
|
||||
// <pointer> to implement the converting.
|
||||
func (j *Json) Scan(pointer interface{}, mapping ...map[string]string) error {
|
||||
return gconv.Scan(*(j.p), pointer, mapping...)
|
||||
}
|
||||
|
||||
// MapToMap converts current Json object to specified map variable.
|
||||
// The parameter of <pointer> should be type of *map.
|
||||
func (j *Json) MapToMap(pointer interface{}, mapping ...map[string]string) error {
|
||||
j.mu.RLock()
|
||||
defer j.mu.RUnlock()
|
||||
return gconv.MapToMap(*(j.p), pointer, mapping...)
|
||||
}
|
||||
|
||||
// MapToMaps converts current Json object to specified map variable slice.
|
||||
// The parameter of <pointer> should be type of []map/*map.
|
||||
func (j *Json) MapToMaps(pointer interface{}, mapping ...map[string]string) error {
|
||||
j.mu.RLock()
|
||||
defer j.mu.RUnlock()
|
||||
return gconv.MapToMaps(*(j.p), pointer, mapping...)
|
||||
return j.Var().Scan(pointer, mapping...)
|
||||
}
|
||||
|
||||
// Dump prints current Json object with more manually readable.
|
||||
|
||||
@ -69,7 +69,7 @@ func (j *Json) MustToJsonIndentString() string {
|
||||
// ========================================================================
|
||||
|
||||
func (j *Json) ToXml(rootTag ...string) ([]byte, error) {
|
||||
return gxml.Encode(j.Map(), rootTag...)
|
||||
return gxml.Encode(j.Var().Map(), rootTag...)
|
||||
}
|
||||
|
||||
func (j *Json) ToXmlString(rootTag ...string) (string, error) {
|
||||
@ -78,7 +78,7 @@ func (j *Json) ToXmlString(rootTag ...string) (string, error) {
|
||||
}
|
||||
|
||||
func (j *Json) ToXmlIndent(rootTag ...string) ([]byte, error) {
|
||||
return gxml.EncodeWithIndent(j.Map(), rootTag...)
|
||||
return gxml.EncodeWithIndent(j.Var().Map(), rootTag...)
|
||||
}
|
||||
|
||||
func (j *Json) ToXmlIndentString(rootTag ...string) (string, error) {
|
||||
|
||||
@ -76,7 +76,7 @@ func Example_conversionGetStruct() {
|
||||
Array []string
|
||||
}
|
||||
users := new(Users)
|
||||
if err := j.GetStruct("users", users); err != nil {
|
||||
if err := j.Get("users").Scan(users); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf(`%+v`, users)
|
||||
@ -101,7 +101,7 @@ func Example_conversionToStruct() {
|
||||
Array []string
|
||||
}
|
||||
users := new(Users)
|
||||
if err := j.Struct(users); err != nil {
|
||||
if err := j.Var().Scan(users); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf(`%+v`, users)
|
||||
|
||||
@ -17,8 +17,8 @@ func Example_dataSetCreate1() {
|
||||
j.Set("score", 99.5)
|
||||
fmt.Printf(
|
||||
"Name: %s, Score: %v\n",
|
||||
j.GetString("name"),
|
||||
j.GetFloat32("score"),
|
||||
j.Get("name").String(),
|
||||
j.Get("score").Float32(),
|
||||
)
|
||||
fmt.Println(j.MustToJsonString())
|
||||
|
||||
@ -54,7 +54,7 @@ func Example_dataSetRuntimeEdit() {
|
||||
panic(err)
|
||||
} else {
|
||||
j.Set("users.list.1.score", 100)
|
||||
fmt.Println("John Score:", j.GetFloat32("users.list.1.score"))
|
||||
fmt.Println("John Score:", j.Get("users.list.1.score").Float32())
|
||||
fmt.Println(j.MustToJsonString())
|
||||
}
|
||||
// Output:
|
||||
|
||||
@ -60,7 +60,7 @@ func Example_newFromStructWithTag() {
|
||||
Score: 100,
|
||||
Title: "engineer",
|
||||
}
|
||||
// The parameter <tags> specifies custom priority tags for struct conversion to map,
|
||||
// The parameter `tags` specifies custom priority tags for struct conversion to map,
|
||||
// multiple tags joined with char ','.
|
||||
j := gjson.NewWithTag(me, "tag")
|
||||
fmt.Println(j.Get("name"))
|
||||
|
||||
@ -25,7 +25,7 @@ func Example_patternGet() {
|
||||
if j, err := gjson.DecodeToJson(data); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
fmt.Println("John Score:", j.GetFloat32("users.list.1.score"))
|
||||
fmt.Println("John Score:", j.Get("users.list.1.score").Float32())
|
||||
}
|
||||
// Output:
|
||||
// John Score: 99.5
|
||||
@ -46,7 +46,7 @@ func Example_patternCustomSplitChar() {
|
||||
panic(err)
|
||||
} else {
|
||||
j.SetSplitChar('#')
|
||||
fmt.Println("John Score:", j.GetFloat32("users#list#1#score"))
|
||||
fmt.Println("John Score:", j.Get("users#list#1#score").Float32())
|
||||
}
|
||||
// Output:
|
||||
// John Score: 99.5
|
||||
@ -64,7 +64,7 @@ func Example_patternViolenceCheck() {
|
||||
panic(err)
|
||||
} else {
|
||||
j.SetViolenceCheck(true)
|
||||
fmt.Println("Users Count:", j.GetInt("users.count"))
|
||||
fmt.Println("Users Count:", j.Get("users.count").Int())
|
||||
}
|
||||
// Output:
|
||||
// Users Count: 101
|
||||
@ -73,23 +73,23 @@ func Example_patternViolenceCheck() {
|
||||
func Example_mapSliceChange() {
|
||||
jsonContent := `{"map":{"key":"value"}, "slice":[59,90]}`
|
||||
j, _ := gjson.LoadJson(jsonContent)
|
||||
m := j.GetMap("map")
|
||||
m := j.Get("map").Map()
|
||||
fmt.Println(m)
|
||||
|
||||
// Change the key-value pair.
|
||||
m["key"] = "john"
|
||||
|
||||
// It changes the underlying key-value pair.
|
||||
fmt.Println(j.GetMap("map"))
|
||||
fmt.Println(j.Get("map").Map())
|
||||
|
||||
s := j.GetArray("slice")
|
||||
s := j.Get("slice").Array()
|
||||
fmt.Println(s)
|
||||
|
||||
// Change the value of specified index.
|
||||
s[0] = 100
|
||||
|
||||
// It changes the underlying slice.
|
||||
fmt.Println(j.GetArray("slice"))
|
||||
fmt.Println(j.Get("slice").Array())
|
||||
|
||||
// output:
|
||||
// map[key:value]
|
||||
|
||||
@ -19,9 +19,9 @@ func Test_New(t *testing.T) {
|
||||
data := []byte(`{"n":123456789, "m":{"k":"v"}, "a":[1,2,3]}`)
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j := gjson.New(data)
|
||||
t.Assert(j.Get("n"), "123456789")
|
||||
t.Assert(j.Get("m"), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("n").String(), "123456789")
|
||||
t.Assert(j.Get("m").Map(), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("a").Array(), g.Slice{1, 2, 3})
|
||||
})
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
@ -82,11 +82,11 @@ func Test_Decode(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j, err := gjson.DecodeToJson(data)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("n"), "123456789")
|
||||
t.Assert(j.Get("m"), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("n").String(), "123456789")
|
||||
t.Assert(j.Get("m").Map(), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m.k"), "v")
|
||||
t.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("a.1"), 2)
|
||||
t.Assert(j.Get("a").Array(), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("a.1").Int(), 2)
|
||||
})
|
||||
}
|
||||
|
||||
@ -96,11 +96,11 @@ func Test_SplitChar(t *testing.T) {
|
||||
j, err := gjson.DecodeToJson(data)
|
||||
j.SetSplitChar(byte('#'))
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("n"), "123456789")
|
||||
t.Assert(j.Get("m"), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m#k"), "v")
|
||||
t.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("a#1"), 2)
|
||||
t.Assert(j.Get("n").String(), "123456789")
|
||||
t.Assert(j.Get("m").Map(), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m#k").String(), "v")
|
||||
t.Assert(j.Get("a").Array(), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("a#1").Int(), 2)
|
||||
})
|
||||
}
|
||||
|
||||
@ -121,11 +121,11 @@ func Test_GetVar(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j, err := gjson.DecodeToJson(data)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.GetVar("n").String(), "123456789")
|
||||
t.Assert(j.GetVar("m").Map(), g.Map{"k": "v"})
|
||||
t.Assert(j.GetVar("a").Interfaces(), g.Slice{1, 2, 3})
|
||||
t.Assert(j.GetVar("a").Slice(), g.Slice{1, 2, 3})
|
||||
t.Assert(j.GetVar("a").Array(), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("n").String(), "123456789")
|
||||
t.Assert(j.Get("m").Map(), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("a").Interfaces(), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("a").Slice(), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("a").Array(), g.Slice{1, 2, 3})
|
||||
})
|
||||
}
|
||||
|
||||
@ -134,9 +134,9 @@ func Test_GetMap(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j, err := gjson.DecodeToJson(data)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.GetMap("n"), nil)
|
||||
t.Assert(j.GetMap("m"), g.Map{"k": "v"})
|
||||
t.Assert(j.GetMap("a"), g.Map{"1": "2", "3": nil})
|
||||
t.Assert(j.Get("n").Map(), nil)
|
||||
t.Assert(j.Get("m").Map(), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("a").Map(), g.Map{"1": "2", "3": nil})
|
||||
})
|
||||
}
|
||||
|
||||
@ -158,9 +158,9 @@ func Test_GetArray(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j, err := gjson.DecodeToJson(data)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.GetArray("n"), g.Array{123456789})
|
||||
t.Assert(j.GetArray("m"), g.Array{g.Map{"k": "v"}})
|
||||
t.Assert(j.GetArray("a"), g.Array{1, 2, 3})
|
||||
t.Assert(j.Get("n").Array(), g.Array{123456789})
|
||||
t.Assert(j.Get("m").Array(), g.Array{g.Map{"k": "v"}})
|
||||
t.Assert(j.Get("a").Array(), g.Array{1, 2, 3})
|
||||
})
|
||||
}
|
||||
|
||||
@ -169,10 +169,10 @@ func Test_GetString(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j, err := gjson.DecodeToJson(data)
|
||||
t.Assert(err, nil)
|
||||
t.AssertEQ(j.GetString("n"), "123456789")
|
||||
t.AssertEQ(j.GetString("m"), `{"k":"v"}`)
|
||||
t.AssertEQ(j.GetString("a"), `[1,2,3]`)
|
||||
t.AssertEQ(j.GetString("i"), "")
|
||||
t.AssertEQ(j.Get("n").String(), "123456789")
|
||||
t.AssertEQ(j.Get("m").String(), `{"k":"v"}`)
|
||||
t.AssertEQ(j.Get("a").String(), `[1,2,3]`)
|
||||
t.AssertEQ(j.Get("i").String(), "")
|
||||
})
|
||||
}
|
||||
|
||||
@ -181,10 +181,10 @@ func Test_GetStrings(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j, err := gjson.DecodeToJson(data)
|
||||
t.Assert(err, nil)
|
||||
t.AssertEQ(j.GetStrings("n"), g.SliceStr{"123456789"})
|
||||
t.AssertEQ(j.GetStrings("m"), g.SliceStr{`{"k":"v"}`})
|
||||
t.AssertEQ(j.GetStrings("a"), g.SliceStr{"1", "2", "3"})
|
||||
t.AssertEQ(j.GetStrings("i"), nil)
|
||||
t.AssertEQ(j.Get("n").Strings(), g.SliceStr{"123456789"})
|
||||
t.AssertEQ(j.Get("m").Strings(), g.SliceStr{`{"k":"v"}`})
|
||||
t.AssertEQ(j.Get("a").Strings(), g.SliceStr{"1", "2", "3"})
|
||||
t.AssertEQ(j.Get("i").Strings(), nil)
|
||||
})
|
||||
}
|
||||
|
||||
@ -193,9 +193,9 @@ func Test_GetInterfaces(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j, err := gjson.DecodeToJson(data)
|
||||
t.Assert(err, nil)
|
||||
t.AssertEQ(j.GetInterfaces("n"), g.Array{123456789})
|
||||
t.AssertEQ(j.GetInterfaces("m"), g.Array{g.Map{"k": "v"}})
|
||||
t.AssertEQ(j.GetInterfaces("a"), g.Array{1, 2, 3})
|
||||
t.AssertEQ(j.Get("n").Interfaces(), g.Array{123456789})
|
||||
t.AssertEQ(j.Get("m").Interfaces(), g.Array{g.Map{"k": "v"}})
|
||||
t.AssertEQ(j.Get("a").Interfaces(), g.Array{1, 2, 3})
|
||||
})
|
||||
}
|
||||
|
||||
@ -230,7 +230,7 @@ func Test_Append(t *testing.T) {
|
||||
p := gjson.New(nil)
|
||||
p.Append("a.b", 1)
|
||||
p.Append("a.c", 2)
|
||||
t.Assert(p.Get("a"), g.Map{
|
||||
t.Assert(p.Get("a").Map(), g.Map{
|
||||
"b": g.Slice{1},
|
||||
"c": g.Slice{2},
|
||||
})
|
||||
@ -278,36 +278,36 @@ func TestJson_ToJson(t *testing.T) {
|
||||
func TestJson_Default(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j := gjson.New(nil)
|
||||
t.AssertEQ(j.Get("no", 100), 100)
|
||||
t.AssertEQ(j.GetString("no", 100), "100")
|
||||
t.AssertEQ(j.GetBool("no", "on"), true)
|
||||
t.AssertEQ(j.GetInt("no", 100), 100)
|
||||
t.AssertEQ(j.GetInt8("no", 100), int8(100))
|
||||
t.AssertEQ(j.GetInt16("no", 100), int16(100))
|
||||
t.AssertEQ(j.GetInt32("no", 100), int32(100))
|
||||
t.AssertEQ(j.GetInt64("no", 100), int64(100))
|
||||
t.AssertEQ(j.GetUint("no", 100), uint(100))
|
||||
t.AssertEQ(j.GetUint8("no", 100), uint8(100))
|
||||
t.AssertEQ(j.GetUint16("no", 100), uint16(100))
|
||||
t.AssertEQ(j.GetUint32("no", 100), uint32(100))
|
||||
t.AssertEQ(j.GetUint64("no", 100), uint64(100))
|
||||
t.AssertEQ(j.GetFloat32("no", 123.456), float32(123.456))
|
||||
t.AssertEQ(j.GetFloat64("no", 123.456), float64(123.456))
|
||||
t.AssertEQ(j.GetArray("no", g.Slice{1, 2, 3}), g.Slice{1, 2, 3})
|
||||
t.AssertEQ(j.GetInts("no", g.Slice{1, 2, 3}), g.SliceInt{1, 2, 3})
|
||||
t.AssertEQ(j.GetFloats("no", g.Slice{1, 2, 3}), []float64{1, 2, 3})
|
||||
t.AssertEQ(j.GetMap("no", g.Map{"k": "v"}), g.Map{"k": "v"})
|
||||
t.AssertEQ(j.GetVar("no", 123.456).Float64(), float64(123.456))
|
||||
t.AssertEQ(j.GetJson("no", g.Map{"k": "v"}).Get("k"), "v")
|
||||
t.AssertEQ(j.Get("no", 100).Int(), 100)
|
||||
t.AssertEQ(j.Get("no", 100).String(), "100")
|
||||
t.AssertEQ(j.Get("no", "on").Bool(), true)
|
||||
t.AssertEQ(j.Get("no", 100).Int(), 100)
|
||||
t.AssertEQ(j.Get("no", 100).Int8(), int8(100))
|
||||
t.AssertEQ(j.Get("no", 100).Int16(), int16(100))
|
||||
t.AssertEQ(j.Get("no", 100).Int32(), int32(100))
|
||||
t.AssertEQ(j.Get("no", 100).Int64(), int64(100))
|
||||
t.AssertEQ(j.Get("no", 100).Uint(), uint(100))
|
||||
t.AssertEQ(j.Get("no", 100).Uint8(), uint8(100))
|
||||
t.AssertEQ(j.Get("no", 100).Uint16(), uint16(100))
|
||||
t.AssertEQ(j.Get("no", 100).Uint32(), uint32(100))
|
||||
t.AssertEQ(j.Get("no", 100).Uint64(), uint64(100))
|
||||
t.AssertEQ(j.Get("no", 123.456).Float32(), float32(123.456))
|
||||
t.AssertEQ(j.Get("no", 123.456).Float64(), float64(123.456))
|
||||
t.AssertEQ(j.Get("no", g.Slice{1, 2, 3}).Array(), g.Slice{1, 2, 3})
|
||||
t.AssertEQ(j.Get("no", g.Slice{1, 2, 3}).Ints(), g.SliceInt{1, 2, 3})
|
||||
t.AssertEQ(j.Get("no", g.Slice{1, 2, 3}).Floats(), []float64{1, 2, 3})
|
||||
t.AssertEQ(j.Get("no", g.Map{"k": "v"}).Map(), g.Map{"k": "v"})
|
||||
t.AssertEQ(j.Get("no", 123.456).Float64(), float64(123.456))
|
||||
t.AssertEQ(j.GetJson("no", g.Map{"k": "v"}).Get("k").String(), "v")
|
||||
t.AssertEQ(j.GetJsons("no", g.Slice{
|
||||
g.Map{"k1": "v1"},
|
||||
g.Map{"k2": "v2"},
|
||||
g.Map{"k3": "v3"},
|
||||
})[0].Get("k1"), "v1")
|
||||
})[0].Get("k1").String(), "v1")
|
||||
t.AssertEQ(j.GetJsonMap("no", g.Map{
|
||||
"m1": g.Map{"k1": "v1"},
|
||||
"m2": g.Map{"k2": "v2"},
|
||||
})["m2"].Get("k2"), "v2")
|
||||
})["m2"].Get("k2").String(), "v2")
|
||||
})
|
||||
}
|
||||
|
||||
@ -356,27 +356,27 @@ func Test_Convert2(t *testing.T) {
|
||||
Name string
|
||||
}{}
|
||||
j := gjson.New(`{"name":"gf","time":"2019-06-12"}`)
|
||||
t.Assert(j.Value().(g.Map)["name"], "gf")
|
||||
t.Assert(j.GetMap("name1"), nil)
|
||||
t.Assert(j.Interface().(g.Map)["name"], "gf")
|
||||
t.Assert(j.Get("name1").Map(), nil)
|
||||
t.AssertNE(j.GetJson("name1"), nil)
|
||||
t.Assert(j.GetJsons("name1"), nil)
|
||||
t.Assert(j.GetJsonMap("name1"), nil)
|
||||
t.Assert(j.Contains("name1"), false)
|
||||
t.Assert(j.GetVar("name1").IsNil(), true)
|
||||
t.Assert(j.GetVar("name").IsNil(), false)
|
||||
t.Assert(j.Get("name1").IsNil(), true)
|
||||
t.Assert(j.Get("name").IsNil(), false)
|
||||
t.Assert(j.Len("name1"), -1)
|
||||
t.Assert(j.GetTime("time").Format("2006-01-02"), "2019-06-12")
|
||||
t.Assert(j.GetGTime("time").Format("Y-m-d"), "2019-06-12")
|
||||
t.Assert(j.GetDuration("time").String(), "0s")
|
||||
t.Assert(j.Get("time").Time().Format("2006-01-02"), "2019-06-12")
|
||||
t.Assert(j.Get("time").GTime().Format("Y-m-d"), "2019-06-12")
|
||||
t.Assert(j.Get("time").Duration().String(), "0s")
|
||||
|
||||
err := j.Struct(&name)
|
||||
err := j.Var().Scan(&name)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(name.Name, "gf")
|
||||
//j.Dump()
|
||||
t.Assert(err, nil)
|
||||
|
||||
j = gjson.New(`{"person":{"name":"gf"}}`)
|
||||
err = j.GetStruct("person", &name)
|
||||
err = j.Get("person").Scan(&name)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(name.Name, "gf")
|
||||
|
||||
@ -385,7 +385,7 @@ func Test_Convert2(t *testing.T) {
|
||||
t.Assert(err, nil)
|
||||
|
||||
j = gjson.New(`[1,2,3]`)
|
||||
t.Assert(len(j.Array()), 3)
|
||||
t.Assert(len(j.Var().Array()), 3)
|
||||
})
|
||||
}
|
||||
|
||||
@ -394,10 +394,10 @@ func Test_Basic(t *testing.T) {
|
||||
j := gjson.New(`{"name":"gf","time":"2019-06-12"}`)
|
||||
j.SetViolenceCheck(true)
|
||||
t.Assert(j.Get(""), nil)
|
||||
t.Assert(j.Get(".").(g.Map)["name"], "gf")
|
||||
t.Assert(j.Get(".").(g.Map)["name1"], nil)
|
||||
t.Assert(j.Get(".").Interface().(g.Map)["name"], "gf")
|
||||
t.Assert(j.Get(".").Interface().(g.Map)["name1"], nil)
|
||||
j.SetViolenceCheck(false)
|
||||
t.Assert(j.Get(".").(g.Map)["name"], "gf")
|
||||
t.Assert(j.Get(".").Interface().(g.Map)["name"], "gf")
|
||||
|
||||
err := j.Set("name", "gf1")
|
||||
t.Assert(err, nil)
|
||||
@ -416,7 +416,7 @@ func Test_Basic(t *testing.T) {
|
||||
err = j.Remove("1")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("0"), 1)
|
||||
t.Assert(len(j.Array()), 2)
|
||||
t.Assert(len(j.Var().Array()), 2)
|
||||
|
||||
j = gjson.New(`[1,2,3]`)
|
||||
// If index 0 is delete, its next item will be at index 0.
|
||||
@ -424,13 +424,13 @@ func Test_Basic(t *testing.T) {
|
||||
t.Assert(j.Remove("0"), nil)
|
||||
t.Assert(j.Remove("0"), nil)
|
||||
t.Assert(j.Get("0"), nil)
|
||||
t.Assert(len(j.Array()), 0)
|
||||
t.Assert(len(j.Var().Array()), 0)
|
||||
|
||||
j = gjson.New(`[1,2,3]`)
|
||||
err = j.Remove("3")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("0"), 1)
|
||||
t.Assert(len(j.Array()), 3)
|
||||
t.Assert(len(j.Var().Array()), 3)
|
||||
|
||||
j = gjson.New(`[1,2,3]`)
|
||||
err = j.Remove("0.3")
|
||||
@ -464,20 +464,20 @@ func Test_Basic(t *testing.T) {
|
||||
t.Assert(j.Get("Name"), "gf")
|
||||
err = j.Set("Name1", g.Map{"Name": "gf1"})
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("Name1").(g.Map)["Name"], "gf1")
|
||||
t.Assert(j.Get("Name1").Interface().(g.Map)["Name"], "gf1")
|
||||
err = j.Set("Name2", g.Slice{1, 2, 3})
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("Name2").(g.Slice)[0], 1)
|
||||
t.Assert(j.Get("Name2").Interface().(g.Slice)[0], 1)
|
||||
err = j.Set("Name3", name)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("Name3").(g.Map)["Name"], "gf")
|
||||
t.Assert(j.Get("Name3").Interface().(g.Map)["Name"], "gf")
|
||||
err = j.Set("Name4", &name)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("Name4").(g.Map)["Name"], "gf")
|
||||
t.Assert(j.Get("Name4").Interface().(g.Map)["Name"], "gf")
|
||||
arr := [3]int{1, 2, 3}
|
||||
err = j.Set("Name5", arr)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("Name5").(g.Array)[0], 1)
|
||||
t.Assert(j.Get("Name5").Interface().(g.Array)[0], 1)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@ -22,11 +22,11 @@ func TestJson_UnmarshalJSON(t *testing.T) {
|
||||
j := gjson.New(nil)
|
||||
err := json.UnmarshalUseNumber(data, j)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("n"), "123456789")
|
||||
t.Assert(j.Get("m"), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m.k"), "v")
|
||||
t.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("a.1"), 2)
|
||||
t.Assert(j.Get("n").String(), "123456789")
|
||||
t.Assert(j.Get("m").Map(), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m.k").String(), "v")
|
||||
t.Assert(j.Get("a").Array(), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("a.1").Int(), 2)
|
||||
})
|
||||
}
|
||||
|
||||
@ -44,11 +44,11 @@ func TestJson_UnmarshalValue(t *testing.T) {
|
||||
}, &v)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(v.Name, "john")
|
||||
t.Assert(v.Json.Get("n"), "123456789")
|
||||
t.Assert(v.Json.Get("m"), g.Map{"k": "v"})
|
||||
t.Assert(v.Json.Get("m.k"), "v")
|
||||
t.Assert(v.Json.Get("a"), g.Slice{1, 2, 3})
|
||||
t.Assert(v.Json.Get("a.1"), 2)
|
||||
t.Assert(v.Json.Get("n").String(), "123456789")
|
||||
t.Assert(v.Json.Get("m").Map(), g.Map{"k": "v"})
|
||||
t.Assert(v.Json.Get("m.k").String(), "v")
|
||||
t.Assert(v.Json.Get("a").Slice(), g.Slice{1, 2, 3})
|
||||
t.Assert(v.Json.Get("a.1").Int(), 2)
|
||||
})
|
||||
// Map
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
@ -63,10 +63,10 @@ func TestJson_UnmarshalValue(t *testing.T) {
|
||||
}, &v)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(v.Name, "john")
|
||||
t.Assert(v.Json.Get("n"), "123456789")
|
||||
t.Assert(v.Json.Get("m"), g.Map{"k": "v"})
|
||||
t.Assert(v.Json.Get("m.k"), "v")
|
||||
t.Assert(v.Json.Get("a"), g.Slice{1, 2, 3})
|
||||
t.Assert(v.Json.Get("a.1"), 2)
|
||||
t.Assert(v.Json.Get("n").String(), "123456789")
|
||||
t.Assert(v.Json.Get("m").Map(), g.Map{"k": "v"})
|
||||
t.Assert(v.Json.Get("m.k").String(), "v")
|
||||
t.Assert(v.Json.Get("a").Slice(), g.Slice{1, 2, 3})
|
||||
t.Assert(v.Json.Get("a.1").Int(), 2)
|
||||
})
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ func Test_MapAttributeConvert(t *testing.T) {
|
||||
Title map[string]interface{}
|
||||
}{}
|
||||
|
||||
err = j.Struct(&tx)
|
||||
err = j.Var().Scan(&tx)
|
||||
gtest.Assert(err, nil)
|
||||
t.Assert(tx.Title, g.Map{
|
||||
"l1": "标签1", "l2": "标签2",
|
||||
@ -76,7 +76,7 @@ func Test_MapAttributeConvert(t *testing.T) {
|
||||
Title map[string]string
|
||||
}{}
|
||||
|
||||
err = j.Struct(&tx)
|
||||
err = j.Var().Scan(&tx)
|
||||
gtest.Assert(err, nil)
|
||||
t.Assert(tx.Title, g.Map{
|
||||
"l1": "标签1", "l2": "标签2",
|
||||
|
||||
@ -21,11 +21,11 @@ func Test_Load_JSON1(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j, err := gjson.LoadContent(data)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("n"), "123456789")
|
||||
t.Assert(j.Get("m"), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m.k"), "v")
|
||||
t.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("a.1"), 2)
|
||||
t.Assert(j.Get("n").String(), "123456789")
|
||||
t.Assert(j.Get("m").Map(), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m.k").String(), "v")
|
||||
t.Assert(j.Get("a").Slice(), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("a.1").Int(), 2)
|
||||
})
|
||||
// JSON
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
@ -34,11 +34,11 @@ func Test_Load_JSON1(t *testing.T) {
|
||||
defer gfile.Remove(path)
|
||||
j, err := gjson.Load(path)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("n"), "123456789")
|
||||
t.Assert(j.Get("m"), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m.k"), "v")
|
||||
t.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("a.1"), 2)
|
||||
t.Assert(j.Get("n").String(), "123456789")
|
||||
t.Assert(j.Get("m").Map(), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m.k").String(), "v")
|
||||
t.Assert(j.Get("a").Slice(), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("a.1").Int(), 2)
|
||||
})
|
||||
}
|
||||
|
||||
@ -47,11 +47,11 @@ func Test_Load_JSON2(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j, err := gjson.LoadContent(data)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("n"), "123456789000000000000")
|
||||
t.Assert(j.Get("m"), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m.k"), "v")
|
||||
t.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("a.1"), 2)
|
||||
t.Assert(j.Get("n").String(), "123456789000000000000")
|
||||
t.Assert(j.Get("m").Map(), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m.k").String(), "v")
|
||||
t.Assert(j.Get("a").Slice(), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("a.1").Int(), 2)
|
||||
})
|
||||
}
|
||||
|
||||
@ -61,11 +61,11 @@ func Test_Load_XML(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j, err := gjson.LoadContent(data)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("doc.n"), "123456789")
|
||||
t.Assert(j.Get("doc.m"), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("doc.m.k"), "v")
|
||||
t.Assert(j.Get("doc.a"), g.Slice{"1", "2", "3"})
|
||||
t.Assert(j.Get("doc.a.1"), 2)
|
||||
t.Assert(j.Get("doc.n").String(), "123456789")
|
||||
t.Assert(j.Get("doc.m").Map(), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("doc.m.k").String(), "v")
|
||||
t.Assert(j.Get("doc.a").Slice(), g.Slice{"1", "2", "3"})
|
||||
t.Assert(j.Get("doc.a.1").Int(), 2)
|
||||
})
|
||||
// XML
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
@ -74,11 +74,11 @@ func Test_Load_XML(t *testing.T) {
|
||||
defer gfile.Remove(path)
|
||||
j, err := gjson.Load(path)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("doc.n"), "123456789")
|
||||
t.Assert(j.Get("doc.m"), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("doc.m.k"), "v")
|
||||
t.Assert(j.Get("doc.a"), g.Slice{"1", "2", "3"})
|
||||
t.Assert(j.Get("doc.a.1"), 2)
|
||||
t.Assert(j.Get("doc.n").String(), "123456789")
|
||||
t.Assert(j.Get("doc.m").Map(), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("doc.m.k").String(), "v")
|
||||
t.Assert(j.Get("doc.a").Array(), g.Slice{"1", "2", "3"})
|
||||
t.Assert(j.Get("doc.a.1").Int(), 2)
|
||||
})
|
||||
|
||||
// XML
|
||||
@ -114,11 +114,11 @@ m:
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j, err := gjson.LoadContent(data)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("n"), "123456789")
|
||||
t.Assert(j.Get("m"), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m.k"), "v")
|
||||
t.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("a.1"), 2)
|
||||
t.Assert(j.Get("n").String(), "123456789")
|
||||
t.Assert(j.Get("m").Map(), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m.k").String(), "v")
|
||||
t.Assert(j.Get("a").Slice(), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("a.1").Int(), 2)
|
||||
})
|
||||
// YAML
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
@ -127,11 +127,11 @@ m:
|
||||
defer gfile.Remove(path)
|
||||
j, err := gjson.Load(path)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("n"), "123456789")
|
||||
t.Assert(j.Get("m"), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m.k"), "v")
|
||||
t.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("a.1"), 2)
|
||||
t.Assert(j.Get("n").String(), "123456789")
|
||||
t.Assert(j.Get("m").Map(), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m.k").String(), "v")
|
||||
t.Assert(j.Get("a").Slice(), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("a.1").Int(), 2)
|
||||
})
|
||||
}
|
||||
|
||||
@ -156,11 +156,11 @@ n = 123456789
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j, err := gjson.LoadContent(data)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("n"), "123456789")
|
||||
t.Assert(j.Get("m"), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m.k"), "v")
|
||||
t.Assert(j.Get("a"), g.Slice{"1", "2", "3"})
|
||||
t.Assert(j.Get("a.1"), 2)
|
||||
t.Assert(j.Get("n").String(), "123456789")
|
||||
t.Assert(j.Get("m").Map(), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m.k").String(), "v")
|
||||
t.Assert(j.Get("a").Slice(), g.Slice{"1", "2", "3"})
|
||||
t.Assert(j.Get("a.1").Int(), 2)
|
||||
})
|
||||
// TOML
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
@ -169,11 +169,11 @@ n = 123456789
|
||||
defer gfile.Remove(path)
|
||||
j, err := gjson.Load(path)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("n"), "123456789")
|
||||
t.Assert(j.Get("m"), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m.k"), "v")
|
||||
t.Assert(j.Get("a"), g.Slice{"1", "2", "3"})
|
||||
t.Assert(j.Get("a.1"), 2)
|
||||
t.Assert(j.Get("n").String(), "123456789")
|
||||
t.Assert(j.Get("m").Map(), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m.k").String(), "v")
|
||||
t.Assert(j.Get("a").Slice(), g.Slice{"1", "2", "3"})
|
||||
t.Assert(j.Get("a.1").Int(), 2)
|
||||
})
|
||||
}
|
||||
|
||||
@ -189,14 +189,14 @@ func Test_Load_TOML2(t *testing.T) {
|
||||
func Test_Load_Basic(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j := gjson.New(nil)
|
||||
t.Assert(j.Value(), nil)
|
||||
t.Assert(j.Interface(), nil)
|
||||
_, err := gjson.Decode(nil)
|
||||
t.AssertNE(err, nil)
|
||||
_, err = gjson.DecodeToJson(nil)
|
||||
t.AssertNE(err, nil)
|
||||
j, err = gjson.LoadContent(nil)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Value(), nil)
|
||||
t.Assert(j.Interface(), nil)
|
||||
|
||||
j, err = gjson.LoadContent(`{"name": "gf"}`)
|
||||
t.Assert(err, nil)
|
||||
@ -205,7 +205,7 @@ func Test_Load_Basic(t *testing.T) {
|
||||
t.AssertNE(err, nil)
|
||||
|
||||
j = gjson.New(&g.Map{"name": "gf"})
|
||||
t.Assert(j.GetString("name"), "gf")
|
||||
t.Assert(j.Get("name").String(), "gf")
|
||||
|
||||
})
|
||||
}
|
||||
@ -228,19 +228,19 @@ enable=true
|
||||
`
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
json, err := gjson.LoadContent(data)
|
||||
j, err := gjson.LoadContent(data)
|
||||
if err != nil {
|
||||
gtest.Fatal(err)
|
||||
}
|
||||
|
||||
t.Assert(json.GetString("addr.ip"), "127.0.0.1")
|
||||
t.Assert(json.GetString("addr.port"), "9001")
|
||||
t.Assert(json.GetString("addr.enable"), "true")
|
||||
t.Assert(json.GetString("DBINFO.type"), "mysql")
|
||||
t.Assert(json.GetString("DBINFO.user"), "root")
|
||||
t.Assert(json.GetString("DBINFO.password"), "password")
|
||||
t.Assert(j.Get("addr.ip").String(), "127.0.0.1")
|
||||
t.Assert(j.Get("addr.port").String(), "9001")
|
||||
t.Assert(j.Get("addr.enable").String(), "true")
|
||||
t.Assert(j.Get("DBINFO.type").String(), "mysql")
|
||||
t.Assert(j.Get("DBINFO.user").String(), "root")
|
||||
t.Assert(j.Get("DBINFO.password").String(), "password")
|
||||
|
||||
_, err = json.ToIni()
|
||||
_, err = j.ToIni()
|
||||
if err != nil {
|
||||
gtest.Fatal(err)
|
||||
}
|
||||
|
||||
@ -101,12 +101,12 @@ func Test_New_HierarchicalStruct(t *testing.T) {
|
||||
func Test_NewWithOptions(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
data := []byte("[9223372036854775807, 9223372036854775806]")
|
||||
array := gjson.New(data).Array()
|
||||
array := gjson.New(data).Var().Array()
|
||||
t.Assert(array, []uint64{9223372036854776000, 9223372036854776000})
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
data := []byte("[9223372036854775807, 9223372036854775806]")
|
||||
array := gjson.NewWithOptions(data, gjson.Options{StrNumber: true}).Array()
|
||||
array := gjson.NewWithOptions(data, gjson.Options{StrNumber: true}).Var().Array()
|
||||
t.Assert(array, []uint64{9223372036854775807, 9223372036854775806})
|
||||
})
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ func Test_GetScan(t *testing.T) {
|
||||
j := gjson.New(`[{"name":"john", "score":"100"},{"name":"smith", "score":"60"}]`)
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var user *User
|
||||
err := j.GetScan("1", &user)
|
||||
err := j.Get("1").Scan(&user)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(user, &User{
|
||||
Name: "smith",
|
||||
@ -29,7 +29,7 @@ func Test_GetScan(t *testing.T) {
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var users []User
|
||||
err := j.GetScan(".", &users)
|
||||
err := j.Get(".").Scan(&users)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(users, []User{
|
||||
{
|
||||
@ -52,7 +52,7 @@ func Test_GetScanDeep(t *testing.T) {
|
||||
j := gjson.New(`[{"name":"john", "score":"100"},{"name":"smith", "score":"60"}]`)
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var user *User
|
||||
err := j.GetScanDeep("1", &user)
|
||||
err := j.Get("1").Scan(&user)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(user, &User{
|
||||
Name: "smith",
|
||||
@ -61,7 +61,7 @@ func Test_GetScanDeep(t *testing.T) {
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var users []User
|
||||
err := j.GetScanDeep(".", &users)
|
||||
err := j.Get(".").Scan(&users)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(users, []User{
|
||||
{
|
||||
@ -84,7 +84,7 @@ func Test_Scan1(t *testing.T) {
|
||||
j := gjson.New(`[{"name":"john", "score":"100"},{"name":"smith", "score":"60"}]`)
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var users []User
|
||||
err := j.Scan(&users)
|
||||
err := j.Var().Scan(&users)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(users, []User{
|
||||
{
|
||||
@ -107,7 +107,7 @@ func Test_Scan2(t *testing.T) {
|
||||
j := gjson.New(`[{"name":"john", "score":"100"},{"name":"smith", "score":"60"}]`)
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var users []User
|
||||
err := j.Scan(&users)
|
||||
err := j.Var().Scan(&users)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(users, []User{
|
||||
{
|
||||
@ -198,7 +198,7 @@ func Test_Struct1(t *testing.T) {
|
||||
data := new(UserCollectionAddReq)
|
||||
j, err := gjson.LoadJson(jsonContent)
|
||||
t.Assert(err, nil)
|
||||
err = j.Struct(data)
|
||||
err = j.Scan(data)
|
||||
t.Assert(err, nil)
|
||||
})
|
||||
}
|
||||
@ -226,12 +226,12 @@ func Test_Struct(t *testing.T) {
|
||||
|
||||
j, err := gjson.LoadContent(txt)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.GetString("me.name"), "mikey")
|
||||
t.Assert(j.GetString("items"), "")
|
||||
t.Assert(j.GetBool("items"), false)
|
||||
t.Assert(j.GetArray("items"), nil)
|
||||
t.Assert(j.Get("me.name").String(), "mikey")
|
||||
t.Assert(j.Get("items").String(), "")
|
||||
t.Assert(j.Get("items").Bool(), false)
|
||||
t.Assert(j.Get("items").Array(), nil)
|
||||
m := new(M)
|
||||
err = j.Struct(m)
|
||||
err = j.Scan(m)
|
||||
t.Assert(err, nil)
|
||||
t.AssertNE(m.Me, nil)
|
||||
t.Assert(m.Me["day"], "20009")
|
||||
@ -290,7 +290,7 @@ func Test_Struct_Complicated(t *testing.T) {
|
||||
j, err := gjson.LoadContent(jsonContent)
|
||||
t.Assert(err, nil)
|
||||
var response = new(Response)
|
||||
err = j.Struct(response)
|
||||
err = j.Scan(response)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(len(response.CertList), 3)
|
||||
t.Assert(response.CertList[0].CertID, 2023313)
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). 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://gitee.com/johng/gp.
|
||||
|
||||
// Package gparser provides convenient API for accessing/converting variable and JSON/XML/YAML/TOML.
|
||||
package gparser
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/encoding/gjson"
|
||||
)
|
||||
|
||||
// Parser is actually alias of gjson.Json.
|
||||
type Parser = gjson.Json
|
||||
@ -1,139 +0,0 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). 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://gitee.com/johng/gp.
|
||||
|
||||
package gparser
|
||||
|
||||
// ========================================================================
|
||||
// JSON
|
||||
// ========================================================================
|
||||
|
||||
func VarToJson(value interface{}) ([]byte, error) {
|
||||
return New(value).ToJson()
|
||||
}
|
||||
|
||||
func VarToJsonString(value interface{}) (string, error) {
|
||||
return New(value).ToJsonString()
|
||||
}
|
||||
|
||||
func VarToJsonIndent(value interface{}) ([]byte, error) {
|
||||
return New(value).ToJsonIndent()
|
||||
}
|
||||
|
||||
func VarToJsonIndentString(value interface{}) (string, error) {
|
||||
return New(value).ToJsonIndentString()
|
||||
}
|
||||
|
||||
func MustToJson(value interface{}) []byte {
|
||||
return New(value).MustToJson()
|
||||
}
|
||||
|
||||
func MustToJsonString(value interface{}) string {
|
||||
return New(value).MustToJsonString()
|
||||
}
|
||||
|
||||
func MustToJsonIndent(value interface{}) []byte {
|
||||
return New(value).MustToJsonIndent()
|
||||
}
|
||||
|
||||
func MustToJsonIndentString(value interface{}) string {
|
||||
return New(value).MustToJsonIndentString()
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// XML
|
||||
// ========================================================================
|
||||
|
||||
func VarToXml(value interface{}, rootTag ...string) ([]byte, error) {
|
||||
return NewWithTag(value, "xml").ToXml(rootTag...)
|
||||
}
|
||||
|
||||
func VarToXmlString(value interface{}, rootTag ...string) (string, error) {
|
||||
return NewWithTag(value, "xml").ToXmlString(rootTag...)
|
||||
}
|
||||
|
||||
func VarToXmlIndent(value interface{}, rootTag ...string) ([]byte, error) {
|
||||
return NewWithTag(value, "xml").ToXmlIndent(rootTag...)
|
||||
}
|
||||
|
||||
func VarToXmlIndentString(value interface{}, rootTag ...string) (string, error) {
|
||||
return NewWithTag(value, "xml").ToXmlIndentString(rootTag...)
|
||||
}
|
||||
|
||||
func MustToXml(value interface{}, rootTag ...string) []byte {
|
||||
return NewWithTag(value, "xml").MustToXml(rootTag...)
|
||||
}
|
||||
|
||||
func MustToXmlString(value interface{}, rootTag ...string) string {
|
||||
return NewWithTag(value, "xml").MustToXmlString(rootTag...)
|
||||
}
|
||||
|
||||
func MustToXmlIndent(value interface{}, rootTag ...string) []byte {
|
||||
return NewWithTag(value, "xml").MustToXmlIndent(rootTag...)
|
||||
}
|
||||
|
||||
func MustToXmlIndentString(value interface{}, rootTag ...string) string {
|
||||
return NewWithTag(value, "xml").MustToXmlIndentString(rootTag...)
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// YAML
|
||||
// ========================================================================
|
||||
|
||||
func VarToYaml(value interface{}) ([]byte, error) {
|
||||
return NewWithTag(value, "yaml").ToYaml()
|
||||
}
|
||||
|
||||
func VarToYamlString(value interface{}) (string, error) {
|
||||
return NewWithTag(value, "yaml").ToYamlString()
|
||||
}
|
||||
|
||||
func MustToYaml(value interface{}) []byte {
|
||||
return NewWithTag(value, "yaml").MustToYaml()
|
||||
}
|
||||
|
||||
func MustToYamlString(value interface{}) string {
|
||||
return NewWithTag(value, "yaml").MustToYamlString()
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// TOML
|
||||
// ========================================================================
|
||||
|
||||
func VarToToml(value interface{}) ([]byte, error) {
|
||||
return NewWithTag(value, "toml").ToToml()
|
||||
}
|
||||
|
||||
func VarToTomlString(value interface{}) (string, error) {
|
||||
return NewWithTag(value, "toml").ToTomlString()
|
||||
}
|
||||
|
||||
func MustToToml(value interface{}) []byte {
|
||||
return NewWithTag(value, "toml").MustToToml()
|
||||
}
|
||||
|
||||
func MustToTomlString(value interface{}) string {
|
||||
return NewWithTag(value, "toml").MustToTomlString()
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// INI
|
||||
// ========================================================================
|
||||
|
||||
func VarToIni(value interface{}) ([]byte, error) {
|
||||
return NewWithTag(value, "ini").ToIni()
|
||||
}
|
||||
|
||||
func VarToIniString(value interface{}) (string, error) {
|
||||
return NewWithTag(value, "ini").ToIniString()
|
||||
}
|
||||
|
||||
func MustToIni(value interface{}) []byte {
|
||||
return NewWithTag(value, "ini").MustToIni()
|
||||
}
|
||||
|
||||
func MustToIniString(value interface{}) string {
|
||||
return NewWithTag(value, "ini").MustToIniString()
|
||||
}
|
||||
@ -1,65 +0,0 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). 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://gitee.com/johng/gp.
|
||||
|
||||
package gparser
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/encoding/gjson"
|
||||
)
|
||||
|
||||
// New creates a Parser object with any variable type of <data>, but <data> should be a map, struct or
|
||||
// slice for data access reason, or it will make no sense.
|
||||
//
|
||||
// The parameter <safe> specifies whether using this Json object in concurrent-safe context, which
|
||||
// is false in default.
|
||||
func New(data interface{}, safe ...bool) *Parser {
|
||||
return gjson.New(data, safe...)
|
||||
}
|
||||
|
||||
// NewWithTag 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 parameter <tags> specifies priority tags for struct conversion to map, multiple tags joined
|
||||
// with char ','.
|
||||
//
|
||||
// The parameter <safe> specifies whether using this Json object in concurrent-safe context, which
|
||||
// is false in default.
|
||||
func NewWithTag(data interface{}, tags string, safe ...bool) *Parser {
|
||||
return gjson.NewWithTag(data, tags, safe...)
|
||||
}
|
||||
|
||||
// Load loads content from specified file <path>,
|
||||
// and creates a Parser object from its content.
|
||||
func Load(path string, safe ...bool) (*Parser, error) {
|
||||
return gjson.Load(path, safe...)
|
||||
}
|
||||
|
||||
// LoadContent creates a Parser object from given content,
|
||||
// it checks the data type of <content> automatically,
|
||||
// supporting JSON, XML, INI, YAML and TOML types of data.
|
||||
func LoadContent(data interface{}, safe ...bool) (*Parser, error) {
|
||||
return gjson.LoadContent(data, safe...)
|
||||
}
|
||||
|
||||
func LoadJson(data interface{}, safe ...bool) (*Parser, error) {
|
||||
return gjson.LoadJson(data, safe...)
|
||||
}
|
||||
|
||||
func LoadXml(data interface{}, safe ...bool) (*Parser, error) {
|
||||
return gjson.LoadXml(data, safe...)
|
||||
}
|
||||
|
||||
func LoadYaml(data interface{}, safe ...bool) (*Parser, error) {
|
||||
return gjson.LoadYaml(data, safe...)
|
||||
}
|
||||
|
||||
func LoadToml(data interface{}, safe ...bool) (*Parser, error) {
|
||||
return gjson.LoadToml(data, safe...)
|
||||
}
|
||||
|
||||
func LoadIni(data interface{}, safe ...bool) (*Parser, error) {
|
||||
return gjson.LoadIni(data, safe...)
|
||||
}
|
||||
@ -1,306 +0,0 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). 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 (
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/encoding/gparser"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"github.com/gogf/gf/test/gtest"
|
||||
)
|
||||
|
||||
func Test_New(t *testing.T) {
|
||||
data := []byte(`{"n":123456789, "m":{"k":"v"}, "a":[1,2,3]}`)
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j := gparser.New(data)
|
||||
t.Assert(j.Get("n"), "123456789")
|
||||
t.Assert(j.Get("m"), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
v := j.Value().(g.Map)
|
||||
t.Assert(v["n"], 123456789)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_NewUnsafe(t *testing.T) {
|
||||
data := []byte(`{"n":123456789, "m":{"k":"v"}, "a":[1,2,3]}`)
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j := gparser.New(data)
|
||||
t.Assert(j.Get("n"), "123456789")
|
||||
t.Assert(j.Get("m"), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m.k"), "v")
|
||||
t.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("a.1"), 2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Encode(t *testing.T) {
|
||||
value := g.Slice{1, 2, 3}
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
b, err := gparser.VarToJson(value)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(b, []byte(`[1,2,3]`))
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Decode(t *testing.T) {
|
||||
data := []byte(`{"n":123456789, "m":{"k":"v"}, "a":[1,2,3]}`)
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j := gparser.New(data)
|
||||
t.AssertNE(j, nil)
|
||||
t.Assert(j.Get("n"), "123456789")
|
||||
t.Assert(j.Get("m"), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m.k"), "v")
|
||||
t.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("a.1"), 2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_SplitChar(t *testing.T) {
|
||||
data := []byte(`{"n":123456789, "m":{"k":"v"}, "a":[1,2,3]}`)
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j := gparser.New(data)
|
||||
j.SetSplitChar(byte('#'))
|
||||
t.AssertNE(j, nil)
|
||||
t.Assert(j.Get("n"), "123456789")
|
||||
t.Assert(j.Get("m"), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m#k"), "v")
|
||||
t.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("a#1"), 2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_ViolenceCheck(t *testing.T) {
|
||||
data := []byte(`{"m":{"a":[1,2,3], "v1.v2":"4"}}`)
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j := gparser.New(data)
|
||||
t.AssertNE(j, nil)
|
||||
t.Assert(j.Get("m.a.2"), 3)
|
||||
t.Assert(j.Get("m.v1.v2"), nil)
|
||||
j.SetViolenceCheck(true)
|
||||
t.Assert(j.Get("m.v1.v2"), 4)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_GetVar(t *testing.T) {
|
||||
data := []byte(`{"n":123456789, "m":{"k":"v"}, "a":[1,2,3]}`)
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j := gparser.New(data)
|
||||
t.AssertNE(j, nil)
|
||||
t.Assert(j.GetVar("n").String(), "123456789")
|
||||
t.Assert(j.GetVar("m").Map(), g.Map{"k": "v"})
|
||||
t.Assert(j.GetVar("a").Interfaces(), g.Slice{1, 2, 3})
|
||||
t.Assert(j.GetVar("a").Slice(), g.Slice{1, 2, 3})
|
||||
t.Assert(j.GetMap("a"), g.Map{"1": "2", "3": nil})
|
||||
})
|
||||
}
|
||||
|
||||
func Test_GetMap(t *testing.T) {
|
||||
data := []byte(`{"n":123456789, "m":{"k":"v"}, "a":[1,2,3]}`)
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j := gparser.New(data)
|
||||
t.AssertNE(j, nil)
|
||||
t.Assert(j.GetMap("n"), nil)
|
||||
t.Assert(j.GetMap("m"), g.Map{"k": "v"})
|
||||
t.Assert(j.GetMap("a"), g.Map{"1": "2", "3": nil})
|
||||
})
|
||||
}
|
||||
|
||||
func Test_GetArray(t *testing.T) {
|
||||
data := []byte(`{"n":123456789, "m":{"k":"v"}, "a":[1,2,3]}`)
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j := gparser.New(data)
|
||||
t.AssertNE(j, nil)
|
||||
t.Assert(j.GetArray("n"), g.Array{123456789})
|
||||
t.Assert(j.GetArray("m"), g.Array{g.Map{"k": "v"}})
|
||||
t.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.C(t, func(t *gtest.T) {
|
||||
j := gparser.New(data)
|
||||
t.AssertNE(j, nil)
|
||||
t.AssertEQ(j.GetString("n"), "123456789")
|
||||
t.AssertEQ(j.GetString("m"), `{"k":"v"}`)
|
||||
t.AssertEQ(j.GetString("a"), `[1,2,3]`)
|
||||
t.AssertEQ(j.GetString("i"), "")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_GetStrings(t *testing.T) {
|
||||
data := []byte(`{"n":123456789, "m":{"k":"v"}, "a":[1,2,3]}`)
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j := gparser.New(data)
|
||||
t.AssertNE(j, nil)
|
||||
t.AssertEQ(j.GetStrings("n"), g.SliceStr{"123456789"})
|
||||
t.AssertEQ(j.GetStrings("m"), g.SliceStr{`{"k":"v"}`})
|
||||
t.AssertEQ(j.GetStrings("a"), g.SliceStr{"1", "2", "3"})
|
||||
t.AssertEQ(j.GetStrings("i"), nil)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_GetInterfaces(t *testing.T) {
|
||||
data := []byte(`{"n":123456789, "m":{"k":"v"}, "a":[1,2,3]}`)
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j := gparser.New(data)
|
||||
t.AssertNE(j, nil)
|
||||
t.AssertEQ(j.GetInterfaces("n"), g.Array{123456789})
|
||||
t.AssertEQ(j.GetInterfaces("m"), g.Array{g.Map{"k": "v"}})
|
||||
t.AssertEQ(j.GetInterfaces("a"), g.Array{1, 2, 3})
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Len(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
p := gparser.New(nil)
|
||||
p.Append("a", 1)
|
||||
p.Append("a", 2)
|
||||
t.Assert(p.Len("a"), 2)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
p := gparser.New(nil)
|
||||
p.Append("a.b", 1)
|
||||
p.Append("a.c", 2)
|
||||
t.Assert(p.Len("a"), 2)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
p := gparser.New(nil)
|
||||
p.Set("a", 1)
|
||||
t.Assert(p.Len("a"), -1)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Append(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
p := gparser.New(nil)
|
||||
p.Append("a", 1)
|
||||
p.Append("a", 2)
|
||||
t.Assert(p.Get("a"), g.Slice{1, 2})
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
p := gparser.New(nil)
|
||||
p.Append("a.b", 1)
|
||||
p.Append("a.c", 2)
|
||||
t.Assert(p.Get("a"), g.Map{
|
||||
"b": g.Slice{1},
|
||||
"c": g.Slice{2},
|
||||
})
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
p := gparser.New(nil)
|
||||
p.Set("a", 1)
|
||||
err := p.Append("a", 2)
|
||||
t.AssertNE(err, nil)
|
||||
t.Assert(p.Get("a"), 1)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Convert(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
p := gparser.New(`{"name":"gf","bool":true,"int":1,"float":1,"ints":[1,2],"floats":[1,2],"time":"2019-06-12","person": {"name": "gf"}}`)
|
||||
t.Assert(p.GetVar("name").String(), "gf")
|
||||
t.Assert(p.GetString("name"), "gf")
|
||||
t.Assert(p.GetBool("bool"), true)
|
||||
t.Assert(p.GetInt("int"), 1)
|
||||
t.Assert(p.GetInt8("int"), 1)
|
||||
t.Assert(p.GetInt16("int"), 1)
|
||||
t.Assert(p.GetInt32("int"), 1)
|
||||
t.Assert(p.GetInt64("int"), 1)
|
||||
t.Assert(p.GetUint("int"), 1)
|
||||
t.Assert(p.GetUint8("int"), 1)
|
||||
t.Assert(p.GetUint16("int"), 1)
|
||||
t.Assert(p.GetUint32("int"), 1)
|
||||
t.Assert(p.GetUint64("int"), 1)
|
||||
t.Assert(p.GetInts("ints")[0], 1)
|
||||
t.Assert(p.GetFloat32("float"), 1)
|
||||
t.Assert(p.GetFloat64("float"), 1)
|
||||
t.Assert(p.GetFloats("floats")[0], 1)
|
||||
t.Assert(p.GetTime("time").Format("2006-01-02"), "2019-06-12")
|
||||
t.Assert(p.GetGTime("time").Format("Y-m-d"), "2019-06-12")
|
||||
t.Assert(p.GetDuration("time").String(), "0s")
|
||||
name := struct {
|
||||
Name string
|
||||
}{}
|
||||
err := p.GetStruct("person", &name)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(name.Name, "gf")
|
||||
t.Assert(p.Map()["name"], "gf")
|
||||
err = p.Struct(&name)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(name.Name, "gf")
|
||||
//p.Dump()
|
||||
|
||||
p = gparser.New(`[0,1,2]`)
|
||||
t.Assert(p.Array()[0], 0)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Convert2(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
xmlArr := []byte{60, 114, 111, 111, 116, 47, 62}
|
||||
p := gparser.New(`<root></root>`)
|
||||
arr, err := p.ToXml("root")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(arr, xmlArr)
|
||||
arr, err = gparser.VarToXml(`<root></root>`, "root")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(arr, xmlArr)
|
||||
|
||||
arr, err = p.ToXmlIndent("root")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(arr, xmlArr)
|
||||
arr, err = gparser.VarToXmlIndent(`<root></root>`, "root")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(arr, xmlArr)
|
||||
|
||||
p = gparser.New(`{"name":"gf"}`)
|
||||
str, err := p.ToJsonString()
|
||||
t.Assert(err, nil)
|
||||
t.Assert(str, `{"name":"gf"}`)
|
||||
str, err = gparser.VarToJsonString(`{"name":"gf"}`)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(str, `{"name":"gf"}`)
|
||||
|
||||
jsonIndentArr := []byte{123, 10, 9, 34, 110, 97, 109, 101, 34, 58, 32, 34, 103, 102, 34, 10, 125}
|
||||
arr, err = p.ToJsonIndent()
|
||||
t.Assert(err, nil)
|
||||
t.Assert(arr, jsonIndentArr)
|
||||
arr, err = gparser.VarToJsonIndent(`{"name":"gf"}`)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(arr, jsonIndentArr)
|
||||
|
||||
str, err = p.ToJsonIndentString()
|
||||
t.Assert(err, nil)
|
||||
t.Assert(str, "{\n\t\"name\": \"gf\"\n}")
|
||||
str, err = gparser.VarToJsonIndentString(`{"name":"gf"}`)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(str, "{\n\t\"name\": \"gf\"\n}")
|
||||
|
||||
p = gparser.New(g.Map{"name": "gf"})
|
||||
arr, err = p.ToYaml()
|
||||
t.Assert(err, nil)
|
||||
t.Assert(arr, "name: gf\n")
|
||||
arr, err = gparser.VarToYaml(g.Map{"name": "gf"})
|
||||
t.Assert(err, nil)
|
||||
t.Assert(arr, "name: gf\n")
|
||||
|
||||
tomlArr := []byte{110, 97, 109, 101, 32, 61, 32, 34, 103, 102, 34, 10}
|
||||
p = gparser.New(`
|
||||
name= "gf"
|
||||
`)
|
||||
arr, err = p.ToToml()
|
||||
t.Assert(err, nil)
|
||||
t.Assert(arr, tomlArr)
|
||||
arr, err = gparser.VarToToml(`
|
||||
name= "gf"
|
||||
`)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(arr, tomlArr)
|
||||
})
|
||||
}
|
||||
@ -1,190 +0,0 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). 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 (
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/encoding/gparser"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"github.com/gogf/gf/os/gfile"
|
||||
"github.com/gogf/gf/test/gtest"
|
||||
)
|
||||
|
||||
func Test_Load_JSON(t *testing.T) {
|
||||
data := []byte(`{"n":123456789, "m":{"k":"v"}, "a":[1,2,3]}`)
|
||||
// JSON
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j, err := gparser.LoadContent(data)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("n"), "123456789")
|
||||
t.Assert(j.Get("m"), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m.k"), "v")
|
||||
t.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("a.1"), 2)
|
||||
})
|
||||
// JSON
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
path := "test.json"
|
||||
gfile.PutBytes(path, data)
|
||||
defer gfile.Remove(path)
|
||||
j, err := gparser.Load(path)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("n"), "123456789")
|
||||
t.Assert(j.Get("m"), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m.k"), "v")
|
||||
t.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
t.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.C(t, func(t *gtest.T) {
|
||||
j, err := gparser.LoadContent(data)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("doc.n"), "123456789")
|
||||
t.Assert(j.Get("doc.m"), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("doc.m.k"), "v")
|
||||
t.Assert(j.Get("doc.a"), g.Slice{"1", "2", "3"})
|
||||
t.Assert(j.Get("doc.a.1"), 2)
|
||||
})
|
||||
// XML
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
path := "test.xml"
|
||||
gfile.PutBytes(path, data)
|
||||
defer gfile.Remove(path)
|
||||
j, err := gparser.Load(path)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("doc.n"), "123456789")
|
||||
t.Assert(j.Get("doc.m"), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("doc.m.k"), "v")
|
||||
t.Assert(j.Get("doc.a"), g.Slice{"1", "2", "3"})
|
||||
t.Assert(j.Get("doc.a.1"), 2)
|
||||
})
|
||||
|
||||
// XML
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
xml := `<?xml version="1.0"?>
|
||||
|
||||
<Output type="o">
|
||||
<itotalSize>0</itotalSize>
|
||||
<ipageSize>1</ipageSize>
|
||||
<ipageIndex>2</ipageIndex>
|
||||
<itotalRecords>GF框架</itotalRecords>
|
||||
<nworkOrderDtos/>
|
||||
<nworkOrderFrontXML/>
|
||||
</Output>`
|
||||
j, err := gparser.LoadContent(xml)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("Output.ipageIndex"), "2")
|
||||
t.Assert(j.Get("Output.itotalRecords"), "GF框架")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Load_YAML1(t *testing.T) {
|
||||
data := []byte(`
|
||||
a:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
m:
|
||||
k: v
|
||||
"n": 123456789
|
||||
`)
|
||||
// YAML
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j, err := gparser.LoadContent(data)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("n"), "123456789")
|
||||
t.Assert(j.Get("m"), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m.k"), "v")
|
||||
t.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("a.1"), 2)
|
||||
})
|
||||
// YAML
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
path := "test.yaml"
|
||||
gfile.PutBytes(path, data)
|
||||
defer gfile.Remove(path)
|
||||
j, err := gparser.Load(path)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("n"), "123456789")
|
||||
t.Assert(j.Get("m"), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m.k"), "v")
|
||||
t.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
t.Assert(j.Get("a.1"), 2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Load_YAML2(t *testing.T) {
|
||||
data := []byte("i : 123456789")
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j, err := gparser.LoadContent(data)
|
||||
t.Assert(err, nil)
|
||||
t.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.C(t, func(t *gtest.T) {
|
||||
j, err := gparser.LoadContent(data)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("n"), "123456789")
|
||||
t.Assert(j.Get("m"), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m.k"), "v")
|
||||
t.Assert(j.Get("a"), g.Slice{"1", "2", "3"})
|
||||
t.Assert(j.Get("a.1"), 2)
|
||||
})
|
||||
// TOML
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
path := "test.toml"
|
||||
gfile.PutBytes(path, data)
|
||||
defer gfile.Remove(path)
|
||||
j, err := gparser.Load(path)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("n"), "123456789")
|
||||
t.Assert(j.Get("m"), g.Map{"k": "v"})
|
||||
t.Assert(j.Get("m.k"), "v")
|
||||
t.Assert(j.Get("a"), g.Slice{"1", "2", "3"})
|
||||
t.Assert(j.Get("a.1"), 2)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Load_TOML2(t *testing.T) {
|
||||
data := []byte("i=123456789")
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j, err := gparser.LoadContent(data)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(j.Get("i"), "123456789")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Load_Nil(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
p := gparser.New(nil)
|
||||
t.Assert(p.Value(), nil)
|
||||
file := "test22222.json"
|
||||
filePath := gfile.Pwd() + gfile.Separator + file
|
||||
ioutil.WriteFile(filePath, []byte("{"), 0644)
|
||||
defer gfile.Remove(filePath)
|
||||
_, err := gparser.Load(file)
|
||||
t.AssertNE(err, nil)
|
||||
_, err = gparser.LoadContent("{")
|
||||
t.AssertNE(err, nil)
|
||||
})
|
||||
}
|
||||
@ -1,49 +0,0 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). 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/encoding/gparser"
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/test/gtest"
|
||||
)
|
||||
|
||||
func Test_Load_NewWithTag(t *testing.T) {
|
||||
type User struct {
|
||||
Age int `xml:"age-xml" json:"age-json"`
|
||||
Name string `xml:"name-xml" json:"name-json"`
|
||||
Addr string `xml:"addr-xml" json:"addr-json"`
|
||||
}
|
||||
data := User{
|
||||
Age: 18,
|
||||
Name: "john",
|
||||
Addr: "chengdu",
|
||||
}
|
||||
// JSON
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j := gparser.New(data)
|
||||
t.AssertNE(j, nil)
|
||||
t.Assert(j.Get("age-xml"), nil)
|
||||
t.Assert(j.Get("age-json"), data.Age)
|
||||
t.Assert(j.Get("name-xml"), nil)
|
||||
t.Assert(j.Get("name-json"), data.Name)
|
||||
t.Assert(j.Get("addr-xml"), nil)
|
||||
t.Assert(j.Get("addr-json"), data.Addr)
|
||||
})
|
||||
// XML
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
j := gparser.NewWithTag(data, "xml")
|
||||
t.AssertNE(j, nil)
|
||||
t.Assert(j.Get("age-xml"), data.Age)
|
||||
t.Assert(j.Get("age-json"), nil)
|
||||
t.Assert(j.Get("name-xml"), data.Name)
|
||||
t.Assert(j.Get("name-json"), nil)
|
||||
t.Assert(j.Get("addr-xml"), data.Addr)
|
||||
t.Assert(j.Get("addr-json"), nil)
|
||||
})
|
||||
}
|
||||
@ -1,215 +0,0 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). 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 (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/encoding/gparser"
|
||||
)
|
||||
|
||||
func Test_Set1(t *testing.T) {
|
||||
e := []byte(`{"k1":{"k11":[1,2,3]},"k2":"v2"}`)
|
||||
p := gparser.New(map[string]string{
|
||||
"k1": "v1",
|
||||
"k2": "v2",
|
||||
})
|
||||
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))
|
||||
}
|
||||
} else {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Set2(t *testing.T) {
|
||||
e := []byte(`[[null,1]]`)
|
||||
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))
|
||||
}
|
||||
} else {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Set3(t *testing.T) {
|
||||
e := []byte(`{"kv":{"k1":"v1"}}`)
|
||||
p := gparser.New([]string{"a"})
|
||||
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))
|
||||
}
|
||||
} else {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Set4(t *testing.T) {
|
||||
e := []byte(`["a",[{"k1":"v1"}]]`)
|
||||
p := gparser.New([]string{"a"})
|
||||
p.Set("1.0", map[string]string{
|
||||
"k1": "v1",
|
||||
})
|
||||
if c, err := p.ToJson(); err == nil {
|
||||
if bytes.Compare(c, e) != 0 {
|
||||
t.Error("expect:", string(e))
|
||||
}
|
||||
} else {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Set5(t *testing.T) {
|
||||
e := []byte(`[[[[[[[[[[[[[[[[[[[[[1,2,3]]]]]]]]]]]]]]]]]]]]]`)
|
||||
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))
|
||||
}
|
||||
} else {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Set6(t *testing.T) {
|
||||
e := []byte(`["a",[1,2,3]]`)
|
||||
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))
|
||||
}
|
||||
} else {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Set7(t *testing.T) {
|
||||
e := []byte(`{"0":[null,[1,2,3]],"k1":"v1","k2":"v2"}`)
|
||||
p := gparser.New(map[string]string{
|
||||
"k1": "v1",
|
||||
"k2": "v2",
|
||||
})
|
||||
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))
|
||||
}
|
||||
} else {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Set8(t *testing.T) {
|
||||
e := []byte(`{"0":[[[[[[null,[1,2,3]]]]]]],"k1":"v1","k2":"v2"}`)
|
||||
p := gparser.New(map[string]string{
|
||||
"k1": "v1",
|
||||
"k2": "v2",
|
||||
})
|
||||
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))
|
||||
}
|
||||
} else {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Set9(t *testing.T) {
|
||||
e := []byte(`{"k1":[null,[1,2,3]],"k2":"v2"}`)
|
||||
p := gparser.New(map[string]string{
|
||||
"k1": "v1",
|
||||
"k2": "v2",
|
||||
})
|
||||
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))
|
||||
}
|
||||
} else {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Set10(t *testing.T) {
|
||||
e := []byte(`{"a":{"b":{"c":1}}}`)
|
||||
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))
|
||||
}
|
||||
} else {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Set11(t *testing.T) {
|
||||
e := []byte(`{"a":{"b":{}}}`)
|
||||
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))
|
||||
}
|
||||
} else {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Set12(t *testing.T) {
|
||||
e := []byte(`[0,1]`)
|
||||
p := gparser.New(nil)
|
||||
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))
|
||||
}
|
||||
} else {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Set13(t *testing.T) {
|
||||
e := []byte(`{"array":[0,1]}`)
|
||||
p := gparser.New(nil)
|
||||
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))
|
||||
}
|
||||
} else {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). 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 g
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/os/glog"
|
||||
)
|
||||
|
||||
// SetLogLevel sets the logging level globally.
|
||||
// Deprecated, use functions of package glog or g.Log() instead.
|
||||
func SetLogLevel(level int) {
|
||||
glog.SetLevel(level)
|
||||
}
|
||||
|
||||
// GetLogLevel returns the global logging level.
|
||||
// Deprecated, use functions of package glog or g.Log() instead.
|
||||
func GetLogLevel() int {
|
||||
return glog.GetLevel()
|
||||
}
|
||||
@ -86,15 +86,6 @@ func DB(name ...string) gdb.DB {
|
||||
return gins.Database(name...)
|
||||
}
|
||||
|
||||
// Table is alias of Model.
|
||||
// The database component is designed not only for
|
||||
// relational databases but also for NoSQL databases in the future. The name
|
||||
// "Table" is not proper for that purpose anymore.
|
||||
// Deprecated, use Model instead.
|
||||
func Table(tableNameOrStruct ...interface{}) *gdb.Model {
|
||||
return DB().Model(tableNameOrStruct...)
|
||||
}
|
||||
|
||||
// Model creates and returns a model based on configuration of default database group.
|
||||
func Model(tableNameOrStruct ...interface{}) *gdb.Model {
|
||||
return DB().Model(tableNameOrStruct...)
|
||||
|
||||
@ -8,7 +8,6 @@ package g
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/internal/intlog"
|
||||
"github.com/gogf/gf/net/ghttp"
|
||||
)
|
||||
|
||||
// SetDebug enables/disables the GoFrame internal logging manually.
|
||||
@ -17,10 +16,3 @@ import (
|
||||
func SetDebug(enabled bool) {
|
||||
intlog.SetEnabled(enabled)
|
||||
}
|
||||
|
||||
// SetServerGraceful enables/disables graceful reload feature of http Web Server.
|
||||
// This feature is disabled in default.
|
||||
// Deprecated, use configuration of ghttp.Server for controlling this feature.
|
||||
func SetServerGraceful(enabled bool) {
|
||||
ghttp.SetGraceful(enabled)
|
||||
}
|
||||
|
||||
@ -52,11 +52,15 @@ func Redis(name ...string) *gredis.Redis {
|
||||
|
||||
if len(configMap) > 0 {
|
||||
if v, ok := configMap[group]; ok {
|
||||
redisConfig, err := gredis.ConfigFromStr(gconv.String(v))
|
||||
redisConfig, err := gredis.ConfigFromMap(gconv.Map(v))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return gredis.New(redisConfig)
|
||||
redisClient, err := gredis.New(redisConfig)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return redisClient
|
||||
} else {
|
||||
panic(fmt.Sprintf(`missing configuration for redis group "%s"`, group))
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ func Test_Config2(t *testing.T) {
|
||||
|
||||
t.Assert(gins.Config().MustGet(ctx, "test"), "v=1")
|
||||
t.Assert(gins.Config().MustGet(ctx, "database.default.1.host"), "127.0.0.1")
|
||||
t.Assert(gins.Config().MustGet(ctx, "redis.disk"), "127.0.0.1:6379,0")
|
||||
t.Assert(gins.Config().MustGet(ctx, "redis.disk"), `{"address":"127.0.0.1:6379","db":1}`)
|
||||
})
|
||||
// for gfsnotify callbacks to refresh cache of config file
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
@ -81,7 +81,7 @@ func Test_Config2(t *testing.T) {
|
||||
|
||||
t.Assert(gins.Config().MustGet(ctx, "test"), "v=1")
|
||||
t.Assert(gins.Config().MustGet(ctx, "database.default.1.host"), "127.0.0.1")
|
||||
t.Assert(gins.Config().MustGet(ctx, "redis.disk"), "127.0.0.1:6379,0")
|
||||
t.Assert(gins.Config().MustGet(ctx, "redis.disk"), `{"address":"127.0.0.1:6379","db":1}`)
|
||||
|
||||
// for gfsnotify callbacks to refresh cache of config file
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
@ -108,7 +108,7 @@ func Test_Config3(t *testing.T) {
|
||||
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "test"), "v=1")
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "database.default.1.host"), "127.0.0.1")
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "redis.disk"), "127.0.0.1:6379,0")
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "redis.disk"), `{"address":"127.0.0.1:6379","db":1}`)
|
||||
})
|
||||
// for gfsnotify callbacks to refresh cache of config file
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
@ -132,7 +132,7 @@ func Test_Config3(t *testing.T) {
|
||||
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "test"), "v=1")
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "database.default.1.host"), "127.0.0.1")
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "redis.disk"), "127.0.0.1:6379,0")
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "redis.disk"), `{"address":"127.0.0.1:6379","db":1}`)
|
||||
})
|
||||
// for gfsnotify callbacks to refresh cache of config file for next unit testing case.
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
@ -151,7 +151,7 @@ func Test_Config4(t *testing.T) {
|
||||
t.Assert(gins.Config().GetAdapter().(*gcfg.AdapterFile).AddPath(path), nil)
|
||||
t.Assert(gins.Config().MustGet(ctx, "test"), "v=1")
|
||||
t.Assert(gins.Config().MustGet(ctx, "database.default.1.host"), "127.0.0.1")
|
||||
t.Assert(gins.Config().MustGet(ctx, "redis.disk"), "127.0.0.1:6379,0")
|
||||
t.Assert(gins.Config().MustGet(ctx, "redis.disk"), `{"address":"127.0.0.1:6379","db":1}`)
|
||||
})
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
|
||||
@ -165,7 +165,7 @@ func Test_Config4(t *testing.T) {
|
||||
t.Assert(gins.Config().GetAdapter().(*gcfg.AdapterFile).AddPath(path), nil)
|
||||
t.Assert(gins.Config().MustGet(ctx, "test"), "v=1")
|
||||
t.Assert(gins.Config().MustGet(ctx, "database.default.1.host"), "127.0.0.1")
|
||||
t.Assert(gins.Config().MustGet(ctx, "redis.disk"), "127.0.0.1:6379,0")
|
||||
t.Assert(gins.Config().MustGet(ctx, "redis.disk"), `{"address":"127.0.0.1:6379","db":1}`)
|
||||
})
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
|
||||
@ -180,7 +180,7 @@ func Test_Config4(t *testing.T) {
|
||||
t.Assert(gins.Config("test").GetAdapter().(*gcfg.AdapterFile).AddPath(path), nil)
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "test"), "v=1")
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "database.default.1.host"), "127.0.0.1")
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "redis.disk"), "127.0.0.1:6379,0")
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "redis.disk"), `{"address":"127.0.0.1:6379","db":1}`)
|
||||
})
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
|
||||
@ -195,7 +195,7 @@ func Test_Config4(t *testing.T) {
|
||||
t.Assert(gins.Config("test").GetAdapter().(*gcfg.AdapterFile).AddPath(path), nil)
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "test"), "v=1")
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "database.default.1.host"), "127.0.0.1")
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "redis.disk"), "127.0.0.1:6379,0")
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "redis.disk"), `{"address":"127.0.0.1:6379","db":1}`)
|
||||
})
|
||||
}
|
||||
func Test_Basic2(t *testing.T) {
|
||||
|
||||
@ -44,24 +44,26 @@ func Test_Redis(t *testing.T) {
|
||||
|
||||
//fmt.Println("gins Test_Redis", Config().Get("test"))
|
||||
|
||||
redisDefault := gins.Redis()
|
||||
redisCache := gins.Redis("cache")
|
||||
redisDisk := gins.Redis("disk")
|
||||
var (
|
||||
redisDefault = gins.Redis()
|
||||
redisCache = gins.Redis("cache")
|
||||
redisDisk = gins.Redis("disk")
|
||||
)
|
||||
t.AssertNE(redisDefault, nil)
|
||||
t.AssertNE(redisCache, nil)
|
||||
t.AssertNE(redisDisk, nil)
|
||||
|
||||
r, err := redisDefault.Do("PING")
|
||||
r, err := redisDefault.Do(ctx, "PING")
|
||||
t.AssertNil(err)
|
||||
t.Assert(r, "PONG")
|
||||
|
||||
r, err = redisCache.Do(ctx, "PING")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(r, "PONG")
|
||||
|
||||
r, err = redisCache.Do("PING")
|
||||
_, err = redisDisk.Do(ctx, "SET", "k", "v")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(r, "PONG")
|
||||
|
||||
_, err = redisDisk.Do("SET", "k", "v")
|
||||
t.Assert(err, nil)
|
||||
r, err = redisDisk.Do("GET", "k")
|
||||
r, err = redisDisk.Do(ctx, "GET", "k")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(r, []byte("v"))
|
||||
})
|
||||
|
||||
8
frame/gins/testdata/config/config.toml
vendored
8
frame/gins/testdata/config/config.toml
vendored
@ -25,5 +25,9 @@ test = "v=1"
|
||||
priority = "1"
|
||||
# Redis数据库配置
|
||||
[redis]
|
||||
disk = "127.0.0.1:6379,0"
|
||||
cache = "127.0.0.1:6379,1"
|
||||
[redis.disk]
|
||||
address = "127.0.0.1:6379"
|
||||
db = 1
|
||||
[redis.cache]
|
||||
address = "127.0.0.1:6379"
|
||||
db = 1
|
||||
8
frame/gins/testdata/database/config.toml
vendored
8
frame/gins/testdata/database/config.toml
vendored
@ -25,5 +25,9 @@ test = "v=2"
|
||||
charset = "utf8"
|
||||
# Redis数据库配置
|
||||
[redis]
|
||||
default = "127.0.0.1:6379,0"
|
||||
cache = "127.0.0.1:6379,1"
|
||||
[redis.default]
|
||||
address = "127.0.0.1:6379"
|
||||
db = 1
|
||||
[redis.cache]
|
||||
address = "127.0.0.1:6379"
|
||||
db = 1
|
||||
17
frame/gins/testdata/redis/config.toml
vendored
17
frame/gins/testdata/redis/config.toml
vendored
@ -27,6 +27,17 @@ test = "v=3"
|
||||
priority = "1"
|
||||
# Redis数据库配置
|
||||
[redis]
|
||||
default = "127.0.0.1:6379,7"
|
||||
cache = "127.0.0.1:6379,8"
|
||||
disk = "127.0.0.1:6379,9,?maxIdle=1&maxActive=10&idleTimeout=10&maxConnLifetime=10"
|
||||
[redis.default]
|
||||
address = "127.0.0.1:6379"
|
||||
db = 7
|
||||
[redis.cache]
|
||||
address = "127.0.0.1:6379"
|
||||
db = 8
|
||||
[redis.disk]
|
||||
address = "127.0.0.1:6379"
|
||||
db = 9
|
||||
maxIdle = 1
|
||||
maxActive = 10
|
||||
idleTimeout = "10s"
|
||||
maxConnLifetime = "10s"
|
||||
|
||||
|
||||
@ -1,44 +0,0 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). 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 gmvc provides basic object classes for MVC.
|
||||
// Deprecated, no longer suggested.
|
||||
package gmvc
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/net/ghttp"
|
||||
)
|
||||
|
||||
// Controller is used for controller register of ghttp.Server.
|
||||
// Deprecated, no longer suggested.
|
||||
type Controller struct {
|
||||
Request *ghttp.Request
|
||||
Response *ghttp.Response
|
||||
Server *ghttp.Server
|
||||
Cookie *ghttp.Cookie
|
||||
Session *ghttp.Session
|
||||
View *View
|
||||
}
|
||||
|
||||
// Init is the callback function for each request initialization.
|
||||
func (c *Controller) Init(r *ghttp.Request) {
|
||||
c.Request = r
|
||||
c.Response = r.Response
|
||||
c.Server = r.Server
|
||||
c.View = NewView(r.Response)
|
||||
c.Cookie = r.Cookie
|
||||
c.Session = r.Session
|
||||
}
|
||||
|
||||
// Shut is the callback function for each request close.
|
||||
func (c *Controller) Shut() {
|
||||
|
||||
}
|
||||
|
||||
// Exit equals to function Request.Exit().
|
||||
func (c *Controller) Exit() {
|
||||
c.Request.Exit()
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). 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 gmvc
|
||||
|
||||
import "github.com/gogf/gf/database/gdb"
|
||||
|
||||
type (
|
||||
// M is alias for Model, just for short write purpose.
|
||||
// Deprecated, no longer suggested.
|
||||
M = *gdb.Model
|
||||
|
||||
// Model is alias for *gdb.Model.
|
||||
// Deprecated, no longer suggested.
|
||||
Model = *gdb.Model
|
||||
)
|
||||
@ -1,130 +0,0 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). 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 gmvc
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/frame/gins"
|
||||
"sync"
|
||||
|
||||
"github.com/gogf/gf/util/gmode"
|
||||
|
||||
"github.com/gogf/gf/net/ghttp"
|
||||
"github.com/gogf/gf/os/gview"
|
||||
)
|
||||
|
||||
// View is the view object for controller.
|
||||
// It's initialized when controller request initializes and destroyed
|
||||
// when the controller request closes.
|
||||
// Deprecated, no longer suggested.
|
||||
type View struct {
|
||||
mu sync.RWMutex
|
||||
view *gview.View
|
||||
data gview.Params
|
||||
response *ghttp.Response
|
||||
}
|
||||
|
||||
// NewView creates and returns a controller view object.
|
||||
// Deprecated, no longer suggested.
|
||||
func NewView(w *ghttp.Response) *View {
|
||||
return &View{
|
||||
view: gins.View(),
|
||||
data: make(gview.Params),
|
||||
response: w,
|
||||
}
|
||||
}
|
||||
|
||||
// Assigns assigns template variables to this view object.
|
||||
func (view *View) Assigns(data gview.Params) {
|
||||
view.mu.Lock()
|
||||
for k, v := range data {
|
||||
view.data[k] = v
|
||||
}
|
||||
view.mu.Unlock()
|
||||
}
|
||||
|
||||
// Assign assigns one template variable to this view object.
|
||||
func (view *View) Assign(key string, value interface{}) {
|
||||
view.mu.Lock()
|
||||
view.data[key] = value
|
||||
view.mu.Unlock()
|
||||
}
|
||||
|
||||
// Parse parses given template file `tpl` with assigned template variables
|
||||
// and returns the parsed template content.
|
||||
func (view *View) Parse(file string) (string, error) {
|
||||
view.mu.RLock()
|
||||
defer view.mu.RUnlock()
|
||||
buffer, err := view.response.ParseTpl(file, view.data)
|
||||
return buffer, err
|
||||
}
|
||||
|
||||
// ParseContent parses given template file `file` with assigned template variables
|
||||
// and returns the parsed template content.
|
||||
func (view *View) ParseContent(content string) (string, error) {
|
||||
view.mu.RLock()
|
||||
defer view.mu.RUnlock()
|
||||
buffer, err := view.response.ParseTplContent(content, view.data)
|
||||
return buffer, err
|
||||
}
|
||||
|
||||
// LockFunc locks writing for template variables by callback function `f`.
|
||||
func (view *View) LockFunc(f func(data gview.Params)) {
|
||||
view.mu.Lock()
|
||||
defer view.mu.Unlock()
|
||||
f(view.data)
|
||||
}
|
||||
|
||||
// RLockFunc locks reading for template variables by callback function `f`.
|
||||
func (view *View) RLockFunc(f func(data gview.Params)) {
|
||||
view.mu.RLock()
|
||||
defer view.mu.RUnlock()
|
||||
f(view.data)
|
||||
}
|
||||
|
||||
// BindFunc registers customized template function named `name`
|
||||
// with given function `function` to current view object.
|
||||
// The `name` is the function name which can be called in template content.
|
||||
func (view *View) BindFunc(name string, function interface{}) {
|
||||
view.view.BindFunc(name, function)
|
||||
}
|
||||
|
||||
// BindFuncMap registers customized template functions by map to current view object.
|
||||
// The key of map is the template function name
|
||||
// and the value of map is the address of customized function.
|
||||
func (view *View) BindFuncMap(funcMap gview.FuncMap) {
|
||||
view.view.BindFuncMap(funcMap)
|
||||
}
|
||||
|
||||
// Display parses and writes the parsed template file content to http response.
|
||||
func (view *View) Display(file ...string) error {
|
||||
name := view.view.GetDefaultFile()
|
||||
if len(file) > 0 {
|
||||
name = file[0]
|
||||
}
|
||||
if content, err := view.Parse(name); err != nil {
|
||||
if !gmode.IsProduct() {
|
||||
view.response.Write("Tpl Parsing Error: " + err.Error())
|
||||
}
|
||||
return err
|
||||
} else {
|
||||
view.response.Write(content)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DisplayContent parses and writes the parsed content to http response.
|
||||
func (view *View) DisplayContent(content string) error {
|
||||
if content, err := view.ParseContent(content); err != nil {
|
||||
if !gmode.IsProduct() {
|
||||
view.response.Write("Tpl Parsing Error: " + err.Error())
|
||||
}
|
||||
return err
|
||||
} else {
|
||||
view.response.Write(content)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
2
go.mod
2
go.mod
@ -7,8 +7,8 @@ require (
|
||||
github.com/clbanning/mxj/v2 v2.5.5
|
||||
github.com/fatih/color v1.12.0
|
||||
github.com/fsnotify/fsnotify v1.5.1
|
||||
github.com/go-redis/redis/v8 v8.11.3
|
||||
github.com/go-sql-driver/mysql v1.6.0
|
||||
github.com/gomodule/redigo v1.8.5
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/grokify/html-strip-tags-go v0.0.1
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
|
||||
74
go.sum
74
go.sum
@ -1,58 +1,132 @@
|
||||
github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw=
|
||||
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E=
|
||||
github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc=
|
||||
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
|
||||
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
||||
github.com/go-redis/redis/v8 v8.11.3 h1:GCjoYp8c+yQTJfc0n69iwSiHjvuAdruxl7elnZCxgt8=
|
||||
github.com/go-redis/redis/v8 v8.11.3/go.mod h1:xNJ9xDG09FsIPwh3bWdk+0oDWHbtF9rPN0F/oD9XeKc=
|
||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/gomodule/redigo v1.8.5 h1:nRAxCa+SVsyjSBrtZmG/cqb6VbTmuRzpg/PoTFlpumc=
|
||||
github.com/gomodule/redigo v1.8.5/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0=
|
||||
github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.opentelemetry.io/otel v1.0.0 h1:qTTn6x71GVBvoafHK/yaRUmFzI4LcONZD0/kXxl5PHI=
|
||||
go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
|
||||
go.opentelemetry.io/otel/trace v1.0.0 h1:TSBr8GTEtKevYMG/2d21M989r5WJYVimhTHBKVEZuh4=
|
||||
go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023 h1:ADo5wSpq2gqaCGQWzk7S5vd//0iyyLeAratkEoG5dLE=
|
||||
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
|
||||
@ -220,7 +220,7 @@ func (m *Manager) init(ctx context.Context) {
|
||||
m.data[lang] = make(map[string]string)
|
||||
}
|
||||
if j, err := gjson.LoadContent(file.Content()); err == nil {
|
||||
for k, v := range j.Map() {
|
||||
for k, v := range j.Var().Map() {
|
||||
m.data[lang][k] = gconv.String(v)
|
||||
}
|
||||
} else {
|
||||
@ -251,7 +251,7 @@ func (m *Manager) init(ctx context.Context) {
|
||||
m.data[lang] = make(map[string]string)
|
||||
}
|
||||
if j, err := gjson.LoadContent(gfile.GetBytes(file)); err == nil {
|
||||
for k, v := range j.Map() {
|
||||
for k, v := range j.Var().Map() {
|
||||
m.data[lang][k] = gconv.String(v)
|
||||
}
|
||||
} else {
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/container/gvar"
|
||||
"github.com/gogf/gf/net/ghttp/internal/client"
|
||||
)
|
||||
|
||||
@ -21,289 +20,3 @@ type (
|
||||
func NewClient() *Client {
|
||||
return client.New()
|
||||
}
|
||||
|
||||
// Get is a convenience method for sending GET request.
|
||||
// NOTE that remembers CLOSING the response object when it'll never be used.
|
||||
// Deprecated, please use g.Client().Get or NewClient().Get instead.
|
||||
func Get(url string, data ...interface{}) (*ClientResponse, error) {
|
||||
return DoRequest("GET", url, data...)
|
||||
}
|
||||
|
||||
// Put is a convenience method for sending PUT request.
|
||||
// NOTE that remembers CLOSING the response object when it'll never be used.
|
||||
// Deprecated, please use g.Client().Put or NewClient().Put instead.
|
||||
func Put(url string, data ...interface{}) (*ClientResponse, error) {
|
||||
return DoRequest("PUT", url, data...)
|
||||
}
|
||||
|
||||
// Post is a convenience method for sending POST request.
|
||||
// NOTE that remembers CLOSING the response object when it'll never be used.
|
||||
// Deprecated, please use g.Client().Post or NewClient().Post instead.
|
||||
func Post(url string, data ...interface{}) (*ClientResponse, error) {
|
||||
return DoRequest("POST", url, data...)
|
||||
}
|
||||
|
||||
// Delete is a convenience method for sending DELETE request.
|
||||
// NOTE that remembers CLOSING the response object when it'll never be used.
|
||||
// Deprecated, please use g.Client().Delete or NewClient().Delete instead.
|
||||
func Delete(url string, data ...interface{}) (*ClientResponse, error) {
|
||||
return DoRequest("DELETE", url, data...)
|
||||
}
|
||||
|
||||
// Head is a convenience method for sending HEAD request.
|
||||
// NOTE that remembers CLOSING the response object when it'll never be used.
|
||||
// Deprecated, please use g.Client().Head or NewClient().Head instead.
|
||||
func Head(url string, data ...interface{}) (*ClientResponse, error) {
|
||||
return DoRequest("HEAD", url, data...)
|
||||
}
|
||||
|
||||
// Patch is a convenience method for sending PATCH request.
|
||||
// NOTE that remembers CLOSING the response object when it'll never be used.
|
||||
// Deprecated, please use g.Client().Patch or NewClient().Patch instead.
|
||||
func Patch(url string, data ...interface{}) (*ClientResponse, error) {
|
||||
return DoRequest("PATCH", url, data...)
|
||||
}
|
||||
|
||||
// Connect is a convenience method for sending CONNECT request.
|
||||
// NOTE that remembers CLOSING the response object when it'll never be used.
|
||||
// Deprecated, please use g.Client().Connect or NewClient().Connect instead.
|
||||
func Connect(url string, data ...interface{}) (*ClientResponse, error) {
|
||||
return DoRequest("CONNECT", url, data...)
|
||||
}
|
||||
|
||||
// Options is a convenience method for sending OPTIONS request.
|
||||
// NOTE that remembers CLOSING the response object when it'll never be used.
|
||||
// Deprecated, please use g.Client().Options or NewClient().Options instead.
|
||||
func Options(url string, data ...interface{}) (*ClientResponse, error) {
|
||||
return DoRequest("OPTIONS", url, data...)
|
||||
}
|
||||
|
||||
// Trace is a convenience method for sending TRACE request.
|
||||
// NOTE that remembers CLOSING the response object when it'll never be used.
|
||||
// Deprecated, please use g.Client().Trace or NewClient().Trace instead.
|
||||
func Trace(url string, data ...interface{}) (*ClientResponse, error) {
|
||||
return DoRequest("TRACE", url, data...)
|
||||
}
|
||||
|
||||
// DoRequest is a convenience method for sending custom http method request.
|
||||
// NOTE that remembers CLOSING the response object when it'll never be used.
|
||||
// Deprecated, please use g.Client().DoRequest or NewClient().DoRequest instead.
|
||||
func DoRequest(method, url string, data ...interface{}) (*ClientResponse, error) {
|
||||
return client.New().DoRequest(method, url, data...)
|
||||
}
|
||||
|
||||
// GetContent is a convenience method for sending GET request, which retrieves and returns
|
||||
// the result content and automatically closes response object.
|
||||
// Deprecated, please use g.Client().GetContent or NewClient().GetContent instead.
|
||||
func GetContent(url string, data ...interface{}) string {
|
||||
return RequestContent("GET", url, data...)
|
||||
}
|
||||
|
||||
// PutContent is a convenience method for sending PUT request, which retrieves and returns
|
||||
// the result content and automatically closes response object.
|
||||
// Deprecated, please use g.Client().PutContent or NewClient().PutContent instead.
|
||||
func PutContent(url string, data ...interface{}) string {
|
||||
return RequestContent("PUT", url, data...)
|
||||
}
|
||||
|
||||
// PostContent is a convenience method for sending POST request, which retrieves and returns
|
||||
// the result content and automatically closes response object.
|
||||
// Deprecated, please use g.Client().PostContent or NewClient().PostContent instead.
|
||||
func PostContent(url string, data ...interface{}) string {
|
||||
return RequestContent("POST", url, data...)
|
||||
}
|
||||
|
||||
// DeleteContent is a convenience method for sending DELETE request, which retrieves and returns
|
||||
// the result content and automatically closes response object.
|
||||
// Deprecated, please use g.Client().DeleteContent or NewClient().DeleteContent instead.
|
||||
func DeleteContent(url string, data ...interface{}) string {
|
||||
return RequestContent("DELETE", url, data...)
|
||||
}
|
||||
|
||||
// HeadContent is a convenience method for sending HEAD request, which retrieves and returns
|
||||
// the result content and automatically closes response object.
|
||||
// Deprecated, please use g.Client().HeadContent or NewClient().HeadContent instead.
|
||||
func HeadContent(url string, data ...interface{}) string {
|
||||
return RequestContent("HEAD", url, data...)
|
||||
}
|
||||
|
||||
// PatchContent is a convenience method for sending PATCH request, which retrieves and returns
|
||||
// the result content and automatically closes response object.
|
||||
// Deprecated, please use g.Client().PatchContent or NewClient().PatchContent instead.
|
||||
func PatchContent(url string, data ...interface{}) string {
|
||||
return RequestContent("PATCH", url, data...)
|
||||
}
|
||||
|
||||
// ConnectContent is a convenience method for sending CONNECT request, which retrieves and returns
|
||||
// the result content and automatically closes response object.
|
||||
// Deprecated, please use g.Client().ConnectContent or NewClient().ConnectContent instead.
|
||||
func ConnectContent(url string, data ...interface{}) string {
|
||||
return RequestContent("CONNECT", url, data...)
|
||||
}
|
||||
|
||||
// OptionsContent is a convenience method for sending OPTIONS request, which retrieves and returns
|
||||
// the result content and automatically closes response object.
|
||||
// Deprecated, please use g.Client().OptionsContent or NewClient().OptionsContent instead.
|
||||
func OptionsContent(url string, data ...interface{}) string {
|
||||
return RequestContent("OPTIONS", url, data...)
|
||||
}
|
||||
|
||||
// TraceContent is a convenience method for sending TRACE request, which retrieves and returns
|
||||
// the result content and automatically closes response object.
|
||||
// Deprecated, please use g.Client().TraceContent or NewClient().TraceContent instead.
|
||||
func TraceContent(url string, data ...interface{}) string {
|
||||
return RequestContent("TRACE", url, data...)
|
||||
}
|
||||
|
||||
// RequestContent is a convenience method for sending custom http method request, which
|
||||
// retrieves and returns the result content and automatically closes response object.
|
||||
// Deprecated, please use g.Client().RequestContent or NewClient().RequestContent instead.
|
||||
func RequestContent(method string, url string, data ...interface{}) string {
|
||||
return client.New().RequestContent(method, url, data...)
|
||||
}
|
||||
|
||||
// GetBytes is a convenience method for sending GET request, which retrieves and returns
|
||||
// the result content as bytes and automatically closes response object.
|
||||
// Deprecated, please use g.Client().GetBytes or NewClient().GetBytes instead.
|
||||
func GetBytes(url string, data ...interface{}) []byte {
|
||||
return RequestBytes("GET", url, data...)
|
||||
}
|
||||
|
||||
// PutBytes is a convenience method for sending PUT request, which retrieves and returns
|
||||
// the result content as bytes and automatically closes response object.
|
||||
// Deprecated, please use g.Client().PutBytes or NewClient().PutBytes instead.
|
||||
func PutBytes(url string, data ...interface{}) []byte {
|
||||
return RequestBytes("PUT", url, data...)
|
||||
}
|
||||
|
||||
// PostBytes is a convenience method for sending POST request, which retrieves and returns
|
||||
// the result content as bytes and automatically closes response object.
|
||||
// Deprecated, please use g.Client().PostBytes or NewClient().PostBytes instead.
|
||||
func PostBytes(url string, data ...interface{}) []byte {
|
||||
return RequestBytes("POST", url, data...)
|
||||
}
|
||||
|
||||
// DeleteBytes is a convenience method for sending DELETE request, which retrieves and returns
|
||||
// the result content as bytes and automatically closes response object.
|
||||
// Deprecated, please use g.Client().DeleteBytes or NewClient().DeleteBytes instead.
|
||||
func DeleteBytes(url string, data ...interface{}) []byte {
|
||||
return RequestBytes("DELETE", url, data...)
|
||||
}
|
||||
|
||||
// HeadBytes is a convenience method for sending HEAD request, which retrieves and returns
|
||||
// the result content as bytes and automatically closes response object.
|
||||
// Deprecated, please use g.Client().HeadBytes or NewClient().HeadBytes instead.
|
||||
func HeadBytes(url string, data ...interface{}) []byte {
|
||||
return RequestBytes("HEAD", url, data...)
|
||||
}
|
||||
|
||||
// PatchBytes is a convenience method for sending PATCH request, which retrieves and returns
|
||||
// the result content as bytes and automatically closes response object.
|
||||
// Deprecated, please use g.Client().PatchBytes or NewClient().PatchBytes instead.
|
||||
func PatchBytes(url string, data ...interface{}) []byte {
|
||||
return RequestBytes("PATCH", url, data...)
|
||||
}
|
||||
|
||||
// ConnectBytes is a convenience method for sending CONNECT request, which retrieves and returns
|
||||
// the result content as bytes and automatically closes response object.
|
||||
// Deprecated, please use g.Client().ConnectBytes or NewClient().ConnectBytes instead.
|
||||
func ConnectBytes(url string, data ...interface{}) []byte {
|
||||
return RequestBytes("CONNECT", url, data...)
|
||||
}
|
||||
|
||||
// OptionsBytes is a convenience method for sending OPTIONS request, which retrieves and returns
|
||||
// the result content as bytes and automatically closes response object.
|
||||
// Deprecated, please use g.Client().OptionsBytes or NewClient().OptionsBytes instead.
|
||||
func OptionsBytes(url string, data ...interface{}) []byte {
|
||||
return RequestBytes("OPTIONS", url, data...)
|
||||
}
|
||||
|
||||
// TraceBytes is a convenience method for sending TRACE request, which retrieves and returns
|
||||
// the result content as bytes and automatically closes response object.
|
||||
// Deprecated, please use g.Client().TraceBytes or NewClient().TraceBytes instead.
|
||||
func TraceBytes(url string, data ...interface{}) []byte {
|
||||
return RequestBytes("TRACE", url, data...)
|
||||
}
|
||||
|
||||
// RequestBytes is a convenience method for sending custom http method request, which
|
||||
// retrieves and returns the result content as bytes and automatically closes response object.
|
||||
// Deprecated, please use g.Client().RequestBytes or NewClient().RequestBytes instead.
|
||||
func RequestBytes(method string, url string, data ...interface{}) []byte {
|
||||
return client.New().RequestBytes(method, url, data...)
|
||||
}
|
||||
|
||||
// GetVar sends a GET request, retrieves and converts the result content to specified pointer.
|
||||
// The parameter <pointer> can be type of: struct/*struct/**struct/[]struct/[]*struct/*[]struct, et
|
||||
// Deprecated, please use g.Client().GetVar or NewClient().GetVar instead.
|
||||
func GetVar(url string, data ...interface{}) *gvar.Var {
|
||||
return RequestVar("GET", url, data...)
|
||||
}
|
||||
|
||||
// PutVar sends a PUT request, retrieves and converts the result content to specified pointer.
|
||||
// The parameter <pointer> can be type of: struct/*struct/**struct/[]struct/[]*struct/*[]struct, et
|
||||
// Deprecated, please use g.Client().PutVar or NewClient().PutVar instead.
|
||||
func PutVar(url string, data ...interface{}) *gvar.Var {
|
||||
return RequestVar("PUT", url, data...)
|
||||
}
|
||||
|
||||
// PostVar sends a POST request, retrieves and converts the result content to specified pointer.
|
||||
// The parameter <pointer> can be type of: struct/*struct/**struct/[]struct/[]*struct/*[]struct, et
|
||||
// Deprecated, please use g.Client().PostVar or NewClient().PostVar instead.
|
||||
func PostVar(url string, data ...interface{}) *gvar.Var {
|
||||
return RequestVar("POST", url, data...)
|
||||
}
|
||||
|
||||
// DeleteVar sends a DELETE request, retrieves and converts the result content to specified pointer.
|
||||
// The parameter <pointer> can be type of: struct/*struct/**struct/[]struct/[]*struct/*[]struct, et
|
||||
// Deprecated, please use g.Client().DeleteVar or NewClient().DeleteVar instead.
|
||||
func DeleteVar(url string, data ...interface{}) *gvar.Var {
|
||||
return RequestVar("DELETE", url, data...)
|
||||
}
|
||||
|
||||
// HeadVar sends a HEAD request, retrieves and converts the result content to specified pointer.
|
||||
// The parameter <pointer> can be type of: struct/*struct/**struct/[]struct/[]*struct/*[]struct, et
|
||||
// Deprecated, please use g.Client().HeadVar or NewClient().HeadVar instead.
|
||||
func HeadVar(url string, data ...interface{}) *gvar.Var {
|
||||
return RequestVar("HEAD", url, data...)
|
||||
}
|
||||
|
||||
// PatchVar sends a PATCH request, retrieves and converts the result content to specified pointer.
|
||||
// The parameter <pointer> can be type of: struct/*struct/**struct/[]struct/[]*struct/*[]struct, et
|
||||
// Deprecated, please use g.Client().PatchVar or NewClient().PatchVar instead.
|
||||
func PatchVar(url string, data ...interface{}) *gvar.Var {
|
||||
return RequestVar("PATCH", url, data...)
|
||||
}
|
||||
|
||||
// ConnectVar sends a CONNECT request, retrieves and converts the result content to specified pointer.
|
||||
// The parameter <pointer> can be type of: struct/*struct/**struct/[]struct/[]*struct/*[]struct, et
|
||||
// Deprecated, please use g.Client().ConnectVar or NewClient().ConnectVar instead.
|
||||
func ConnectVar(url string, data ...interface{}) *gvar.Var {
|
||||
return RequestVar("CONNECT", url, data...)
|
||||
}
|
||||
|
||||
// OptionsVar sends a OPTIONS request, retrieves and converts the result content to specified pointer.
|
||||
// The parameter <pointer> can be type of: struct/*struct/**struct/[]struct/[]*struct/*[]struct, et
|
||||
// Deprecated, please use g.Client().OptionsVar or NewClient().OptionsVar instead.
|
||||
func OptionsVar(url string, data ...interface{}) *gvar.Var {
|
||||
return RequestVar("OPTIONS", url, data...)
|
||||
}
|
||||
|
||||
// TraceVar sends a TRACE request, retrieves and converts the result content to specified pointer.
|
||||
// The parameter <pointer> can be type of: struct/*struct/**struct/[]struct/[]*struct/*[]struct, et
|
||||
// Deprecated, please use g.Client().TraceVar or NewClient().TraceVar instead.
|
||||
func TraceVar(url string, data ...interface{}) *gvar.Var {
|
||||
return RequestVar("TRACE", url, data...)
|
||||
}
|
||||
|
||||
// RequestVar sends request using given HTTP method and data, retrieves converts the result
|
||||
// to specified pointer. It reads and closes the response object internally automatically.
|
||||
// The parameter <pointer> can be type of: struct/*struct/**struct/[]struct/[]*struct/*[]struct, et
|
||||
// Deprecated, please use g.Client().RequestVar or NewClient().RequestVar instead.
|
||||
func RequestVar(method string, url string, data ...interface{}) *gvar.Var {
|
||||
response, err := DoRequest(method, url, data...)
|
||||
if err != nil {
|
||||
return gvar.New(nil)
|
||||
}
|
||||
defer response.Close()
|
||||
return gvar.New(response.ReadAll())
|
||||
}
|
||||
|
||||
@ -118,14 +118,14 @@ func (r *Request) doParse(pointer interface{}, requestType int) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := j.GetStructs(".", pointer); err != nil {
|
||||
if err := j.Var().Scan(pointer); err != nil {
|
||||
return err
|
||||
}
|
||||
for i := 0; i < reflectVal2.Len(); i++ {
|
||||
if err := gvalid.CheckStructWithData(
|
||||
r.Context(),
|
||||
reflectVal2.Index(i),
|
||||
j.GetMap(gconv.String(i)),
|
||||
j.Get(gconv.String(i)).Map(),
|
||||
nil,
|
||||
); err != nil {
|
||||
return err
|
||||
@ -138,30 +138,10 @@ func (r *Request) doParse(pointer interface{}, requestType int) error {
|
||||
// Get is alias of GetRequest, which is one of the most commonly used functions for
|
||||
// retrieving parameter.
|
||||
// See r.GetRequest.
|
||||
func (r *Request) Get(key string, def ...interface{}) interface{} {
|
||||
func (r *Request) Get(key string, def ...interface{}) *gvar.Var {
|
||||
return r.GetRequest(key, def...)
|
||||
}
|
||||
|
||||
// GetVar is alis of GetRequestVar.
|
||||
// See GetRequestVar.
|
||||
func (r *Request) GetVar(key string, def ...interface{}) *gvar.Var {
|
||||
return r.GetRequestVar(key, def...)
|
||||
}
|
||||
|
||||
// GetRaw is alias of GetBody.
|
||||
// See GetBody.
|
||||
// Deprecated, use GetBody instead.
|
||||
func (r *Request) GetRaw() []byte {
|
||||
return r.GetBody()
|
||||
}
|
||||
|
||||
// GetRawString is alias of GetBodyString.
|
||||
// See GetBodyString.
|
||||
// Deprecated, use GetBodyString instead.
|
||||
func (r *Request) GetRawString() string {
|
||||
return r.GetBodyString()
|
||||
}
|
||||
|
||||
// GetBody retrieves and returns request body content as bytes.
|
||||
// It can be called multiple times retrieving the same body content.
|
||||
func (r *Request) GetBody() []byte {
|
||||
@ -184,96 +164,6 @@ func (r *Request) GetJson() (*gjson.Json, error) {
|
||||
return gjson.LoadJson(r.GetBody())
|
||||
}
|
||||
|
||||
// GetString is an alias and convenient function for GetRequestString.
|
||||
// See GetRequestString.
|
||||
func (r *Request) GetString(key string, def ...interface{}) string {
|
||||
return r.GetRequestString(key, def...)
|
||||
}
|
||||
|
||||
// GetBool is an alias and convenient function for GetRequestBool.
|
||||
// See GetRequestBool.
|
||||
func (r *Request) GetBool(key string, def ...interface{}) bool {
|
||||
return r.GetRequestBool(key, def...)
|
||||
}
|
||||
|
||||
// GetInt is an alias and convenient function for GetRequestInt.
|
||||
// See GetRequestInt.
|
||||
func (r *Request) GetInt(key string, def ...interface{}) int {
|
||||
return r.GetRequestInt(key, def...)
|
||||
}
|
||||
|
||||
// GetInt32 is an alias and convenient function for GetRequestInt32.
|
||||
// See GetRequestInt32.
|
||||
func (r *Request) GetInt32(key string, def ...interface{}) int32 {
|
||||
return r.GetRequestInt32(key, def...)
|
||||
}
|
||||
|
||||
// GetInt64 is an alias and convenient function for GetRequestInt64.
|
||||
// See GetRequestInt64.
|
||||
func (r *Request) GetInt64(key string, def ...interface{}) int64 {
|
||||
return r.GetRequestInt64(key, def...)
|
||||
}
|
||||
|
||||
// GetInts is an alias and convenient function for GetRequestInts.
|
||||
// See GetRequestInts.
|
||||
func (r *Request) GetInts(key string, def ...interface{}) []int {
|
||||
return r.GetRequestInts(key, def...)
|
||||
}
|
||||
|
||||
// GetUint is an alias and convenient function for GetRequestUint.
|
||||
// See GetRequestUint.
|
||||
func (r *Request) GetUint(key string, def ...interface{}) uint {
|
||||
return r.GetRequestUint(key, def...)
|
||||
}
|
||||
|
||||
// GetUint32 is an alias and convenient function for GetRequestUint32.
|
||||
// See GetRequestUint32.
|
||||
func (r *Request) GetUint32(key string, def ...interface{}) uint32 {
|
||||
return r.GetRequestUint32(key, def...)
|
||||
}
|
||||
|
||||
// GetUint64 is an alias and convenient function for GetRequestUint64.
|
||||
// See GetRequestUint64.
|
||||
func (r *Request) GetUint64(key string, def ...interface{}) uint64 {
|
||||
return r.GetRequestUint64(key, def...)
|
||||
}
|
||||
|
||||
// GetFloat32 is an alias and convenient function for GetRequestFloat32.
|
||||
// See GetRequestFloat32.
|
||||
func (r *Request) GetFloat32(key string, def ...interface{}) float32 {
|
||||
return r.GetRequestFloat32(key, def...)
|
||||
}
|
||||
|
||||
// GetFloat64 is an alias and convenient function for GetRequestFloat64.
|
||||
// See GetRequestFloat64.
|
||||
func (r *Request) GetFloat64(key string, def ...interface{}) float64 {
|
||||
return r.GetRequestFloat64(key, def...)
|
||||
}
|
||||
|
||||
// GetFloats is an alias and convenient function for GetRequestFloats.
|
||||
// See GetRequestFloats.
|
||||
func (r *Request) GetFloats(key string, def ...interface{}) []float64 {
|
||||
return r.GetRequestFloats(key, def...)
|
||||
}
|
||||
|
||||
// GetArray is an alias and convenient function for GetRequestArray.
|
||||
// See GetRequestArray.
|
||||
func (r *Request) GetArray(key string, def ...interface{}) []string {
|
||||
return r.GetRequestArray(key, def...)
|
||||
}
|
||||
|
||||
// GetStrings is an alias and convenient function for GetRequestStrings.
|
||||
// See GetRequestStrings.
|
||||
func (r *Request) GetStrings(key string, def ...interface{}) []string {
|
||||
return r.GetRequestStrings(key, def...)
|
||||
}
|
||||
|
||||
// GetInterfaces is an alias and convenient function for GetRequestInterfaces.
|
||||
// See GetRequestInterfaces.
|
||||
func (r *Request) GetInterfaces(key string, def ...interface{}) []interface{} {
|
||||
return r.GetRequestInterfaces(key, def...)
|
||||
}
|
||||
|
||||
// GetMap is an alias and convenient function for GetRequestMap.
|
||||
// See GetRequestMap.
|
||||
func (r *Request) GetMap(def ...map[string]interface{}) map[string]interface{} {
|
||||
|
||||
@ -22,115 +22,19 @@ func (r *Request) SetForm(key string, value interface{}) {
|
||||
|
||||
// GetForm retrieves and returns parameter <key> from form.
|
||||
// It returns <def> if <key> does not exist in the form and <def> is given, or else it returns nil.
|
||||
func (r *Request) GetForm(key string, def ...interface{}) interface{} {
|
||||
func (r *Request) GetForm(key string, def ...interface{}) *gvar.Var {
|
||||
r.parseForm()
|
||||
if len(r.formMap) > 0 {
|
||||
if v, ok := r.formMap[key]; ok {
|
||||
return v
|
||||
return gvar.New(v)
|
||||
}
|
||||
}
|
||||
if len(def) > 0 {
|
||||
return def[0]
|
||||
return gvar.New(def[0])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetFormVar retrieves and returns parameter <key> from form as Var.
|
||||
// It returns <def> if <key> does not exist in the form and <def> is given, or else it returns nil.
|
||||
func (r *Request) GetFormVar(key string, def ...interface{}) *gvar.Var {
|
||||
return gvar.New(r.GetForm(key, def...))
|
||||
}
|
||||
|
||||
// GetFormString retrieves and returns parameter <key> from form as string.
|
||||
// It returns <def> if <key> does not exist in the form and <def> is given, or else it returns nil.
|
||||
func (r *Request) GetFormString(key string, def ...interface{}) string {
|
||||
return r.GetFormVar(key, def...).String()
|
||||
}
|
||||
|
||||
// GetFormBool retrieves and returns parameter <key> from form as bool.
|
||||
// It returns <def> if <key> does not exist in the form and <def> is given, or else it returns nil.
|
||||
func (r *Request) GetFormBool(key string, def ...interface{}) bool {
|
||||
return r.GetFormVar(key, def...).Bool()
|
||||
}
|
||||
|
||||
// GetFormInt retrieves and returns parameter <key> from form as int.
|
||||
// It returns <def> if <key> does not exist in the form and <def> is given, or else it returns nil.
|
||||
func (r *Request) GetFormInt(key string, def ...interface{}) int {
|
||||
return r.GetFormVar(key, def...).Int()
|
||||
}
|
||||
|
||||
// GetFormInt32 retrieves and returns parameter <key> from form as int32.
|
||||
// It returns <def> if <key> does not exist in the form and <def> is given, or else it returns nil.
|
||||
func (r *Request) GetFormInt32(key string, def ...interface{}) int32 {
|
||||
return r.GetFormVar(key, def...).Int32()
|
||||
}
|
||||
|
||||
// GetFormInt64 retrieves and returns parameter <key> from form as int64.
|
||||
// It returns <def> if <key> does not exist in the form and <def> is given, or else it returns nil.
|
||||
func (r *Request) GetFormInt64(key string, def ...interface{}) int64 {
|
||||
return r.GetFormVar(key, def...).Int64()
|
||||
}
|
||||
|
||||
// GetFormInts retrieves and returns parameter <key> from form as []int.
|
||||
// It returns <def> if <key> does not exist in the form and <def> is given, or else it returns nil.
|
||||
func (r *Request) GetFormInts(key string, def ...interface{}) []int {
|
||||
return r.GetFormVar(key, def...).Ints()
|
||||
}
|
||||
|
||||
// GetFormUint retrieves and returns parameter <key> from form as uint.
|
||||
// It returns <def> if <key> does not exist in the form and <def> is given, or else it returns nil.
|
||||
func (r *Request) GetFormUint(key string, def ...interface{}) uint {
|
||||
return r.GetFormVar(key, def...).Uint()
|
||||
}
|
||||
|
||||
// GetFormUint32 retrieves and returns parameter <key> from form as uint32.
|
||||
// It returns <def> if <key> does not exist in the form and <def> is given, or else it returns nil.
|
||||
func (r *Request) GetFormUint32(key string, def ...interface{}) uint32 {
|
||||
return r.GetFormVar(key, def...).Uint32()
|
||||
}
|
||||
|
||||
// GetFormUint64 retrieves and returns parameter <key> from form as uint64.
|
||||
// It returns <def> if <key> does not exist in the form and <def> is given, or else it returns nil.
|
||||
func (r *Request) GetFormUint64(key string, def ...interface{}) uint64 {
|
||||
return r.GetFormVar(key, def...).Uint64()
|
||||
}
|
||||
|
||||
// GetFormFloat32 retrieves and returns parameter <key> from form as float32.
|
||||
// It returns <def> if <key> does not exist in the form and <def> is given, or else it returns nil.
|
||||
func (r *Request) GetFormFloat32(key string, def ...interface{}) float32 {
|
||||
return r.GetFormVar(key, def...).Float32()
|
||||
}
|
||||
|
||||
// GetFormFloat64 retrieves and returns parameter <key> from form as float64.
|
||||
// It returns <def> if <key> does not exist in the form and <def> is given, or else it returns nil.
|
||||
func (r *Request) GetFormFloat64(key string, def ...interface{}) float64 {
|
||||
return r.GetFormVar(key, def...).Float64()
|
||||
}
|
||||
|
||||
// GetFormFloats retrieves and returns parameter <key> from form as []float64.
|
||||
// It returns <def> if <key> does not exist in the form and <def> is given, or else it returns nil.
|
||||
func (r *Request) GetFormFloats(key string, def ...interface{}) []float64 {
|
||||
return r.GetFormVar(key, def...).Floats()
|
||||
}
|
||||
|
||||
// GetFormArray retrieves and returns parameter <key> from form as []string.
|
||||
// It returns <def> if <key> does not exist in the form and <def> is given, or else it returns nil.
|
||||
func (r *Request) GetFormArray(key string, def ...interface{}) []string {
|
||||
return r.GetFormVar(key, def...).Strings()
|
||||
}
|
||||
|
||||
// GetFormStrings retrieves and returns parameter <key> from form as []string.
|
||||
// It returns <def> if <key> does not exist in the form and <def> is given, or else it returns nil.
|
||||
func (r *Request) GetFormStrings(key string, def ...interface{}) []string {
|
||||
return r.GetFormVar(key, def...).Strings()
|
||||
}
|
||||
|
||||
// GetFormInterfaces retrieves and returns parameter <key> from form as []interface{}.
|
||||
// It returns <def> if <key> does not exist in the form and <def> is given, or else it returns nil.
|
||||
func (r *Request) GetFormInterfaces(key string, def ...interface{}) []interface{} {
|
||||
return r.GetFormVar(key, def...).Interfaces()
|
||||
}
|
||||
|
||||
// GetFormMap retrieves and returns all form parameters passed from client as map.
|
||||
// The parameter <kvMap> specifies the keys retrieving from client parameters,
|
||||
// the associated values are the default values if the client does not pass.
|
||||
@ -158,10 +62,10 @@ func (r *Request) GetFormMap(kvMap ...map[string]interface{}) map[string]interfa
|
||||
// The parameter <kvMap> specifies the keys retrieving from client parameters, the associated values
|
||||
// are the default values if the client does not pass.
|
||||
func (r *Request) GetFormMapStrStr(kvMap ...map[string]interface{}) map[string]string {
|
||||
postMap := r.GetFormMap(kvMap...)
|
||||
if len(postMap) > 0 {
|
||||
m := make(map[string]string, len(postMap))
|
||||
for k, v := range postMap {
|
||||
formMap := r.GetFormMap(kvMap...)
|
||||
if len(formMap) > 0 {
|
||||
m := make(map[string]string, len(formMap))
|
||||
for k, v := range formMap {
|
||||
m[k] = gconv.String(v)
|
||||
}
|
||||
return m
|
||||
@ -173,10 +77,10 @@ func (r *Request) GetFormMapStrStr(kvMap ...map[string]interface{}) map[string]s
|
||||
// The parameter <kvMap> specifies the keys retrieving from client parameters, the associated values
|
||||
// are the default values if the client does not pass.
|
||||
func (r *Request) GetFormMapStrVar(kvMap ...map[string]interface{}) map[string]*gvar.Var {
|
||||
postMap := r.GetFormMap(kvMap...)
|
||||
if len(postMap) > 0 {
|
||||
m := make(map[string]*gvar.Var, len(postMap))
|
||||
for k, v := range postMap {
|
||||
formMap := r.GetFormMap(kvMap...)
|
||||
if len(formMap) > 0 {
|
||||
m := make(map[string]*gvar.Var, len(formMap))
|
||||
for k, v := range formMap {
|
||||
m[k] = gvar.New(v)
|
||||
}
|
||||
return m
|
||||
|
||||
@ -67,5 +67,5 @@ func (r *Request) GetPage(totalSize, pageSize int) *gpage.Page {
|
||||
urlTemplate += "?" + url.RawQuery
|
||||
}
|
||||
|
||||
return gpage.New(totalSize, pageSize, r.GetInt(gpage.DefaultPageName), urlTemplate)
|
||||
return gpage.New(totalSize, pageSize, r.Get(gpage.DefaultPageName).Int(), urlTemplate)
|
||||
}
|
||||
|
||||
@ -19,19 +19,12 @@ func (r *Request) SetParam(key string, value interface{}) {
|
||||
// GetParam returns custom parameter with given name <key>.
|
||||
// It returns <def> if <key> does not exist.
|
||||
// It returns nil if <def> is not passed.
|
||||
func (r *Request) GetParam(key string, def ...interface{}) interface{} {
|
||||
func (r *Request) GetParam(key string, def ...interface{}) *gvar.Var {
|
||||
if r.paramsMap != nil {
|
||||
return r.paramsMap[key]
|
||||
return gvar.New(r.paramsMap[key])
|
||||
}
|
||||
if len(def) > 0 {
|
||||
return def[0]
|
||||
return gvar.New(def[0])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetParamVar returns custom parameter with given name <key> as gvar.Var.
|
||||
// It returns <def> if <key> does not exist.
|
||||
// It returns nil if <def> is not passed.
|
||||
func (r *Request) GetParamVar(key string, def ...interface{}) *gvar.Var {
|
||||
return gvar.New(r.GetParam(key, def...))
|
||||
}
|
||||
|
||||
@ -27,11 +27,11 @@ func (r *Request) SetQuery(key string, value interface{}) {
|
||||
//
|
||||
// Note that if there are multiple parameters with the same name, the parameters are retrieved
|
||||
// and overwrote in order of priority: query > body.
|
||||
func (r *Request) GetQuery(key string, def ...interface{}) interface{} {
|
||||
func (r *Request) GetQuery(key string, def ...interface{}) *gvar.Var {
|
||||
r.parseQuery()
|
||||
if len(r.queryMap) > 0 {
|
||||
if v, ok := r.queryMap[key]; ok {
|
||||
return v
|
||||
return gvar.New(v)
|
||||
}
|
||||
}
|
||||
if r.Method == "GET" {
|
||||
@ -39,79 +39,15 @@ func (r *Request) GetQuery(key string, def ...interface{}) interface{} {
|
||||
}
|
||||
if len(r.bodyMap) > 0 {
|
||||
if v, ok := r.bodyMap[key]; ok {
|
||||
return v
|
||||
return gvar.New(v)
|
||||
}
|
||||
}
|
||||
if len(def) > 0 {
|
||||
return def[0]
|
||||
return gvar.New(def[0])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Request) GetQueryVar(key string, def ...interface{}) *gvar.Var {
|
||||
return gvar.New(r.GetQuery(key, def...))
|
||||
}
|
||||
|
||||
func (r *Request) GetQueryString(key string, def ...interface{}) string {
|
||||
return r.GetQueryVar(key, def...).String()
|
||||
}
|
||||
|
||||
func (r *Request) GetQueryBool(key string, def ...interface{}) bool {
|
||||
return r.GetQueryVar(key, def...).Bool()
|
||||
}
|
||||
|
||||
func (r *Request) GetQueryInt(key string, def ...interface{}) int {
|
||||
return r.GetQueryVar(key, def...).Int()
|
||||
}
|
||||
|
||||
func (r *Request) GetQueryInt32(key string, def ...interface{}) int32 {
|
||||
return r.GetQueryVar(key, def...).Int32()
|
||||
}
|
||||
|
||||
func (r *Request) GetQueryInt64(key string, def ...interface{}) int64 {
|
||||
return r.GetQueryVar(key, def...).Int64()
|
||||
}
|
||||
|
||||
func (r *Request) GetQueryInts(key string, def ...interface{}) []int {
|
||||
return r.GetQueryVar(key, def...).Ints()
|
||||
}
|
||||
|
||||
func (r *Request) GetQueryUint(key string, def ...interface{}) uint {
|
||||
return r.GetQueryVar(key, def...).Uint()
|
||||
}
|
||||
|
||||
func (r *Request) GetQueryUint32(key string, def ...interface{}) uint32 {
|
||||
return r.GetQueryVar(key, def...).Uint32()
|
||||
}
|
||||
|
||||
func (r *Request) GetQueryUint64(key string, def ...interface{}) uint64 {
|
||||
return r.GetQueryVar(key, def...).Uint64()
|
||||
}
|
||||
|
||||
func (r *Request) GetQueryFloat32(key string, def ...interface{}) float32 {
|
||||
return r.GetQueryVar(key, def...).Float32()
|
||||
}
|
||||
|
||||
func (r *Request) GetQueryFloat64(key string, def ...interface{}) float64 {
|
||||
return r.GetQueryVar(key, def...).Float64()
|
||||
}
|
||||
|
||||
func (r *Request) GetQueryFloats(key string, def ...interface{}) []float64 {
|
||||
return r.GetQueryVar(key, def...).Floats()
|
||||
}
|
||||
|
||||
func (r *Request) GetQueryArray(key string, def ...interface{}) []string {
|
||||
return r.GetQueryVar(key, def...).Strings()
|
||||
}
|
||||
|
||||
func (r *Request) GetQueryStrings(key string, def ...interface{}) []string {
|
||||
return r.GetQueryVar(key, def...).Strings()
|
||||
}
|
||||
|
||||
func (r *Request) GetQueryInterfaces(key string, def ...interface{}) []interface{} {
|
||||
return r.GetQueryVar(key, def...).Interfaces()
|
||||
}
|
||||
|
||||
// GetQueryMap retrieves and returns all parameters passed from client using HTTP GET method
|
||||
// as map. The parameter <kvMap> specifies the keys retrieving from client parameters,
|
||||
// the associated values are the default values if the client does not pass.
|
||||
|
||||
@ -22,7 +22,7 @@ import (
|
||||
//
|
||||
// Note that if there are multiple parameters with the same name, the parameters are
|
||||
// retrieved and overwrote in order of priority: router < query < body < form < custom.
|
||||
func (r *Request) GetRequest(key string, def ...interface{}) interface{} {
|
||||
func (r *Request) GetRequest(key string, def ...interface{}) *gvar.Var {
|
||||
value := r.GetParam(key)
|
||||
if value == nil {
|
||||
value = r.GetForm(key)
|
||||
@ -30,134 +30,24 @@ func (r *Request) GetRequest(key string, def ...interface{}) interface{} {
|
||||
if value == nil {
|
||||
r.parseBody()
|
||||
if len(r.bodyMap) > 0 {
|
||||
value = r.bodyMap[key]
|
||||
if v := r.bodyMap[key]; v != nil {
|
||||
value = gvar.New(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
if value == nil {
|
||||
value = r.GetQuery(key)
|
||||
}
|
||||
if value == nil {
|
||||
value = r.GetRouterValue(key)
|
||||
value = r.GetRouter(key)
|
||||
}
|
||||
if value != nil {
|
||||
return value
|
||||
}
|
||||
if len(def) > 0 {
|
||||
return def[0]
|
||||
return gvar.New(def[0])
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
// GetRequestVar retrieves and returns the parameter named <key> passed from client and
|
||||
// custom params as gvar.Var, no matter what HTTP method the client is using. The parameter
|
||||
// <def> specifies the default value if the <key> does not exist.
|
||||
func (r *Request) GetRequestVar(key string, def ...interface{}) *gvar.Var {
|
||||
return gvar.New(r.GetRequest(key, def...))
|
||||
}
|
||||
|
||||
// GetRequestString retrieves and returns the parameter named <key> passed from client and
|
||||
// custom params as string, no matter what HTTP method the client is using. The parameter
|
||||
// <def> specifies the default value if the <key> does not exist.
|
||||
func (r *Request) GetRequestString(key string, def ...interface{}) string {
|
||||
return r.GetRequestVar(key, def...).String()
|
||||
}
|
||||
|
||||
// GetRequestBool retrieves and returns the parameter named <key> passed from client and
|
||||
// custom params as bool, no matter what HTTP method the client is using. The parameter
|
||||
// <def> specifies the default value if the <key> does not exist.
|
||||
func (r *Request) GetRequestBool(key string, def ...interface{}) bool {
|
||||
return r.GetRequestVar(key, def...).Bool()
|
||||
}
|
||||
|
||||
// GetRequestInt retrieves and returns the parameter named <key> passed from client and
|
||||
// custom params as int, no matter what HTTP method the client is using. The parameter
|
||||
// <def> specifies the default value if the <key> does not exist.
|
||||
func (r *Request) GetRequestInt(key string, def ...interface{}) int {
|
||||
return r.GetRequestVar(key, def...).Int()
|
||||
}
|
||||
|
||||
// GetRequestInt32 retrieves and returns the parameter named <key> passed from client and
|
||||
// custom params as int32, no matter what HTTP method the client is using. The parameter
|
||||
// <def> specifies the default value if the <key> does not exist.
|
||||
func (r *Request) GetRequestInt32(key string, def ...interface{}) int32 {
|
||||
return r.GetRequestVar(key, def...).Int32()
|
||||
}
|
||||
|
||||
// GetRequestInt64 retrieves and returns the parameter named <key> passed from client and
|
||||
// custom params as int64, no matter what HTTP method the client is using. The parameter
|
||||
// <def> specifies the default value if the <key> does not exist.
|
||||
func (r *Request) GetRequestInt64(key string, def ...interface{}) int64 {
|
||||
return r.GetRequestVar(key, def...).Int64()
|
||||
}
|
||||
|
||||
// GetRequestInts retrieves and returns the parameter named <key> passed from client and
|
||||
// custom params as []int, no matter what HTTP method the client is using. The parameter
|
||||
// <def> specifies the default value if the <key> does not exist.
|
||||
func (r *Request) GetRequestInts(key string, def ...interface{}) []int {
|
||||
return r.GetRequestVar(key, def...).Ints()
|
||||
}
|
||||
|
||||
// GetRequestUint retrieves and returns the parameter named <key> passed from client and
|
||||
// custom params as uint, no matter what HTTP method the client is using. The parameter
|
||||
// <def> specifies the default value if the <key> does not exist.
|
||||
func (r *Request) GetRequestUint(key string, def ...interface{}) uint {
|
||||
return r.GetRequestVar(key, def...).Uint()
|
||||
}
|
||||
|
||||
// GetRequestUint32 retrieves and returns the parameter named <key> passed from client and
|
||||
// custom params as uint32, no matter what HTTP method the client is using. The parameter
|
||||
// <def> specifies the default value if the <key> does not exist.
|
||||
func (r *Request) GetRequestUint32(key string, def ...interface{}) uint32 {
|
||||
return r.GetRequestVar(key, def...).Uint32()
|
||||
}
|
||||
|
||||
// GetRequestUint64 retrieves and returns the parameter named <key> passed from client and
|
||||
// custom params as uint64, no matter what HTTP method the client is using. The parameter
|
||||
// <def> specifies the default value if the <key> does not exist.
|
||||
func (r *Request) GetRequestUint64(key string, def ...interface{}) uint64 {
|
||||
return r.GetRequestVar(key, def...).Uint64()
|
||||
}
|
||||
|
||||
// GetRequestFloat32 retrieves and returns the parameter named <key> passed from client and
|
||||
// custom params as float32, no matter what HTTP method the client is using. The parameter
|
||||
// <def> specifies the default value if the <key> does not exist.
|
||||
func (r *Request) GetRequestFloat32(key string, def ...interface{}) float32 {
|
||||
return r.GetRequestVar(key, def...).Float32()
|
||||
}
|
||||
|
||||
// GetRequestFloat64 retrieves and returns the parameter named <key> passed from client and
|
||||
// custom params as float64, no matter what HTTP method the client is using. The parameter
|
||||
// <def> specifies the default value if the <key> does not exist.
|
||||
func (r *Request) GetRequestFloat64(key string, def ...interface{}) float64 {
|
||||
return r.GetRequestVar(key, def...).Float64()
|
||||
}
|
||||
|
||||
// GetRequestFloats retrieves and returns the parameter named <key> passed from client and
|
||||
// custom params as []float64, no matter what HTTP method the client is using. The parameter
|
||||
// <def> specifies the default value if the <key> does not exist.
|
||||
func (r *Request) GetRequestFloats(key string, def ...interface{}) []float64 {
|
||||
return r.GetRequestVar(key, def...).Floats()
|
||||
}
|
||||
|
||||
// GetRequestArray retrieves and returns the parameter named <key> passed from client and
|
||||
// custom params as []string, no matter what HTTP method the client is using. The parameter
|
||||
// <def> specifies the default value if the <key> does not exist.
|
||||
func (r *Request) GetRequestArray(key string, def ...interface{}) []string {
|
||||
return r.GetRequestVar(key, def...).Strings()
|
||||
}
|
||||
|
||||
// GetRequestStrings retrieves and returns the parameter named <key> passed from client and
|
||||
// custom params as []string, no matter what HTTP method the client is using. The parameter
|
||||
// <def> specifies the default value if the <key> does not exist.
|
||||
func (r *Request) GetRequestStrings(key string, def ...interface{}) []string {
|
||||
return r.GetRequestVar(key, def...).Strings()
|
||||
}
|
||||
|
||||
// GetRequestInterfaces retrieves and returns the parameter named <key> passed from client
|
||||
// and custom params as []interface{}, no matter what HTTP method the client is using. The
|
||||
// parameter <def> specifies the default value if the <key> does not exist.
|
||||
func (r *Request) GetRequestInterfaces(key string, def ...interface{}) []interface{} {
|
||||
return r.GetRequestVar(key, def...).Interfaces()
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetRequestMap retrieves and returns all parameters passed from client and custom params
|
||||
@ -173,7 +63,9 @@ func (r *Request) GetRequestMap(kvMap ...map[string]interface{}) map[string]inte
|
||||
r.parseQuery()
|
||||
r.parseForm()
|
||||
r.parseBody()
|
||||
var ok, filter bool
|
||||
var (
|
||||
ok, filter bool
|
||||
)
|
||||
var length int
|
||||
if len(kvMap) > 0 && kvMap[0] != nil {
|
||||
length = len(kvMap[0])
|
||||
|
||||
@ -20,28 +20,16 @@ func (r *Request) GetRouterMap() map[string]string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetRouterValue retrieves and returns the router value with given key name <key>.
|
||||
// GetRouter retrieves and returns the router value with given key name <key>.
|
||||
// It returns <def> if <key> does not exist.
|
||||
func (r *Request) GetRouterValue(key string, def ...interface{}) interface{} {
|
||||
func (r *Request) GetRouter(key string, def ...interface{}) *gvar.Var {
|
||||
if r.routerMap != nil {
|
||||
if v, ok := r.routerMap[key]; ok {
|
||||
return v
|
||||
return gvar.New(v)
|
||||
}
|
||||
}
|
||||
if len(def) > 0 {
|
||||
return def[0]
|
||||
return gvar.New(def[0])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetRouterVar retrieves and returns the router value as gvar.Var with given key name <key>.
|
||||
// It returns <def> if <key> does not exist.
|
||||
func (r *Request) GetRouterVar(key string, def ...interface{}) *gvar.Var {
|
||||
return gvar.New(r.GetRouterValue(key, def...))
|
||||
}
|
||||
|
||||
// GetRouterString retrieves and returns the router value as string with given key name <key>.
|
||||
// It returns <def> if <key> does not exist.
|
||||
func (r *Request) GetRouterString(key string, def ...interface{}) string {
|
||||
return r.GetRouterVar(key, def...).String()
|
||||
}
|
||||
|
||||
@ -82,7 +82,7 @@ func (r *Response) buildInVars(params ...map[string]interface{}) map[string]inte
|
||||
gutil.MapMerge(m, params[0])
|
||||
}
|
||||
// Retrieve custom template variables from request object.
|
||||
sessionMap := gconv.MapDeep(r.Request.Session.Map())
|
||||
sessionMap := gconv.MapDeep(r.Request.Session.MustData())
|
||||
gutil.MapMerge(m, map[string]interface{}{
|
||||
"Form": r.Request.GetFormMap(),
|
||||
"Query": r.Request.GetQueryMap(),
|
||||
|
||||
@ -9,11 +9,10 @@ package ghttp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/encoding/gjson"
|
||||
"github.com/gogf/gf/internal/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/gogf/gf/encoding/gparser"
|
||||
"github.com/gogf/gf/util/gconv"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Write writes <content> to the response buffer.
|
||||
@ -147,7 +146,7 @@ func (r *Response) WriteJsonP(content interface{}) error {
|
||||
return err
|
||||
} else {
|
||||
//r.Header().Set("Content-Type", "application/json")
|
||||
if callback := r.Request.GetString("callback"); callback != "" {
|
||||
if callback := r.Request.Get("callback").String(); callback != "" {
|
||||
buffer := []byte(callback)
|
||||
buffer = append(buffer, byte('('))
|
||||
buffer = append(buffer, b...)
|
||||
@ -183,7 +182,7 @@ func (r *Response) WriteXml(content interface{}, rootTag ...string) error {
|
||||
return nil
|
||||
}
|
||||
// Else use gparser.VarToXml function to encode the parameter.
|
||||
if b, err := gparser.VarToXml(content, rootTag...); err != nil {
|
||||
if b, err := gjson.New(content).ToXml(rootTag...); err != nil {
|
||||
return err
|
||||
} else {
|
||||
r.Header().Set("Content-Type", "application/xml")
|
||||
|
||||
@ -41,17 +41,11 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
// SetGraceful enables/disables the graceful reload feature for server,
|
||||
// which is false in default.
|
||||
//
|
||||
// Note that this feature switch is not for single server instance but for whole process.
|
||||
// Deprecated, use configuration of ghttp.Server for controlling this feature.
|
||||
func SetGraceful(enabled bool) {
|
||||
gracefulEnabled = enabled
|
||||
}
|
||||
|
||||
// serverProcessInit initializes some process configurations, which can only be done once.
|
||||
func serverProcessInit() {
|
||||
var (
|
||||
ctx = context.TODO()
|
||||
)
|
||||
if !serverProcessInitialized.Cas(false, true) {
|
||||
return
|
||||
}
|
||||
@ -62,7 +56,7 @@ func serverProcessInit() {
|
||||
p.Kill()
|
||||
p.Wait()
|
||||
} else {
|
||||
glog.Error(e)
|
||||
glog.Error(ctx, e)
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,10 +66,10 @@ func serverProcessInit() {
|
||||
// Process message handler.
|
||||
// It's enabled only graceful feature is enabled.
|
||||
if gracefulEnabled {
|
||||
intlog.Printf(context.TODO(), "%d: graceful reload feature is enabled", gproc.Pid())
|
||||
intlog.Printf(ctx, "%d: graceful reload feature is enabled", gproc.Pid())
|
||||
go handleProcessMessage()
|
||||
} else {
|
||||
intlog.Printf(context.TODO(), "%d: graceful reload feature is disabled", gproc.Pid())
|
||||
intlog.Printf(ctx, "%d: graceful reload feature is disabled", gproc.Pid())
|
||||
}
|
||||
|
||||
// It's an ugly calling for better initializing the main package path
|
||||
@ -118,8 +112,12 @@ func GetServer(name ...interface{}) *Server {
|
||||
// Start starts listening on configured port.
|
||||
// This function does not block the process, you can use function Wait blocking the process.
|
||||
func (s *Server) Start() error {
|
||||
var (
|
||||
ctx = context.TODO()
|
||||
)
|
||||
|
||||
// Register group routes.
|
||||
s.handlePreBindItems()
|
||||
s.handlePreBindItems(ctx)
|
||||
|
||||
// Server process initialization, which can only be initialized once.
|
||||
serverProcessInit()
|
||||
@ -167,11 +165,11 @@ func (s *Server) Start() error {
|
||||
// Install external plugins.
|
||||
for _, p := range s.plugins {
|
||||
if err := p.Install(s); err != nil {
|
||||
s.Logger().Fatal(err)
|
||||
s.Logger().Fatal(ctx, err)
|
||||
}
|
||||
}
|
||||
// Check the group routes again.
|
||||
s.handlePreBindItems()
|
||||
s.handlePreBindItems(ctx)
|
||||
|
||||
// If there's no route registered and no static service enabled,
|
||||
// it then returns an error of invalid usage of server.
|
||||
@ -210,6 +208,9 @@ func (s *Server) Start() error {
|
||||
|
||||
// DumpRouterMap dumps the router map to the log.
|
||||
func (s *Server) dumpRouterMap() {
|
||||
var (
|
||||
ctx = context.TODO()
|
||||
)
|
||||
if s.config.DumpRouterMap && len(s.routesMap) > 0 {
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
table := tablewriter.NewWriter(buffer)
|
||||
@ -230,7 +231,7 @@ func (s *Server) dumpRouterMap() {
|
||||
table.Append(data)
|
||||
}
|
||||
table.Render()
|
||||
s.config.Logger.Header(false).Printf("\n%s", buffer.String())
|
||||
s.config.Logger.Header(false).Printf(ctx, "\n%s", buffer.String())
|
||||
}
|
||||
}
|
||||
|
||||
@ -312,8 +313,11 @@ func (s *Server) GetRouterArray() []RouterItem {
|
||||
// Run starts server listening in blocking way.
|
||||
// It's commonly used for single server situation.
|
||||
func (s *Server) Run() {
|
||||
var (
|
||||
ctx = context.TODO()
|
||||
)
|
||||
if err := s.Start(); err != nil {
|
||||
s.Logger().Fatal(err)
|
||||
s.Logger().Fatal(ctx, err)
|
||||
}
|
||||
// Blocking using channel.
|
||||
<-s.closeChan
|
||||
@ -326,30 +330,38 @@ func (s *Server) Run() {
|
||||
}
|
||||
}
|
||||
}
|
||||
s.Logger().Printf("%d: all servers shutdown", gproc.Pid())
|
||||
s.Logger().Printf(ctx, "%d: all servers shutdown", gproc.Pid())
|
||||
}
|
||||
|
||||
// Wait blocks to wait for all servers done.
|
||||
// It's commonly used in multiple servers situation.
|
||||
func Wait() {
|
||||
var (
|
||||
ctx = context.TODO()
|
||||
)
|
||||
<-allDoneChan
|
||||
// Remove plugins.
|
||||
serverMapping.Iterator(func(k string, v interface{}) bool {
|
||||
s := v.(*Server)
|
||||
if len(s.plugins) > 0 {
|
||||
for _, p := range s.plugins {
|
||||
intlog.Printf(context.TODO(), `remove plugin: %s`, p.Name())
|
||||
p.Remove()
|
||||
intlog.Printf(ctx, `remove plugin: %s`, p.Name())
|
||||
if err := p.Remove(); err != nil {
|
||||
intlog.Error(ctx, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
glog.Printf("%d: all servers shutdown", gproc.Pid())
|
||||
glog.Printf(ctx, "%d: all servers shutdown", gproc.Pid())
|
||||
}
|
||||
|
||||
// startServer starts the underlying server listening.
|
||||
func (s *Server) startServer(fdMap listenerFdMap) {
|
||||
var httpsEnabled bool
|
||||
var (
|
||||
ctx = context.TODO()
|
||||
httpsEnabled bool
|
||||
)
|
||||
// HTTPS
|
||||
if s.config.TLSConfig != nil || (s.config.HTTPSCertPath != "" && s.config.HTTPSKeyPath != "") {
|
||||
if len(s.config.HTTPSAddr) == 0 {
|
||||
@ -376,7 +388,7 @@ func (s *Server) startServer(fdMap listenerFdMap) {
|
||||
array := strings.Split(v, "#")
|
||||
if len(array) > 1 {
|
||||
itemFunc = array[0]
|
||||
// The windows OS does not support socket file descriptor passing
|
||||
// The Windows OS does not support socket file descriptor passing
|
||||
// from parent process.
|
||||
if runtime.GOOS != "windows" {
|
||||
fd = gconv.Int(array[1])
|
||||
@ -409,7 +421,7 @@ func (s *Server) startServer(fdMap listenerFdMap) {
|
||||
array := strings.Split(v, "#")
|
||||
if len(array) > 1 {
|
||||
itemFunc = array[0]
|
||||
// The windows OS does not support socket file descriptor passing
|
||||
// The Windows OS does not support socket file descriptor passing
|
||||
// from parent process.
|
||||
if runtime.GOOS != "windows" {
|
||||
fd = gconv.Int(array[1])
|
||||
@ -434,7 +446,7 @@ func (s *Server) startServer(fdMap listenerFdMap) {
|
||||
}
|
||||
// The process exits if the server is closed with none closing error.
|
||||
if err != nil && !strings.EqualFold(http.ErrServerClosed.Error(), err.Error()) {
|
||||
s.Logger().Fatal(err)
|
||||
s.Logger().Fatal(ctx, err)
|
||||
}
|
||||
// If all the underlying servers shutdown, the process exits.
|
||||
if s.serverCount.Add(-1) < 1 {
|
||||
@ -485,16 +497,3 @@ func (s *Server) getListenerFdMap() map[string]string {
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// IsExitError checks if given error is an exit error of server.
|
||||
// This is used in old version of server for custom error handler.
|
||||
// Deprecated.
|
||||
func IsExitError(err interface{}) bool {
|
||||
errStr := gconv.String(err)
|
||||
if strings.EqualFold(errStr, exceptionExit) ||
|
||||
strings.EqualFold(errStr, exceptionExitAll) ||
|
||||
strings.EqualFold(errStr, exceptionExitHook) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/os/gfile"
|
||||
"strings"
|
||||
"time"
|
||||
@ -44,16 +45,19 @@ func (p *utilAdmin) Index(r *Request) {
|
||||
|
||||
// Restart restarts all the servers in the process.
|
||||
func (p *utilAdmin) Restart(r *Request) {
|
||||
var err error = nil
|
||||
var (
|
||||
ctx = r.Context()
|
||||
err error
|
||||
)
|
||||
// Custom start binary path when this process exits.
|
||||
path := r.GetQueryString("newExeFilePath")
|
||||
path := r.GetQuery("newExeFilePath").String()
|
||||
if path == "" {
|
||||
path = gfile.SelfPath()
|
||||
}
|
||||
if len(path) > 0 {
|
||||
err = RestartAllServer(path)
|
||||
err = RestartAllServer(ctx, path)
|
||||
} else {
|
||||
err = RestartAllServer()
|
||||
err = RestartAllServer(ctx)
|
||||
}
|
||||
if err == nil {
|
||||
r.Response.WriteExit("server restarted")
|
||||
@ -84,10 +88,13 @@ func (s *Server) EnableAdmin(pattern ...string) {
|
||||
|
||||
// Shutdown shuts down current server.
|
||||
func (s *Server) Shutdown() error {
|
||||
var (
|
||||
ctx = context.TODO()
|
||||
)
|
||||
// Only shut down current servers.
|
||||
// It may have multiple underlying http servers.
|
||||
for _, v := range s.servers {
|
||||
v.close()
|
||||
v.close(ctx)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -40,18 +40,20 @@ const (
|
||||
adminGProcCommGroup = "GF_GPROC_HTTP_SERVER"
|
||||
)
|
||||
|
||||
// serverActionLocker is the locker for server administration operations.
|
||||
var serverActionLocker sync.Mutex
|
||||
var (
|
||||
// serverActionLocker is the locker for server administration operations.
|
||||
serverActionLocker sync.Mutex
|
||||
|
||||
// serverActionLastTime is timestamp in milliseconds of last administration operation.
|
||||
var serverActionLastTime = gtype.NewInt64(gtime.TimestampMilli())
|
||||
// serverActionLastTime is timestamp in milliseconds of last administration operation.
|
||||
serverActionLastTime = gtype.NewInt64(gtime.TimestampMilli())
|
||||
|
||||
// serverProcessStatus is the server status for operation of current process.
|
||||
var serverProcessStatus = gtype.NewInt()
|
||||
// serverProcessStatus is the server status for operation of current process.
|
||||
serverProcessStatus = gtype.NewInt()
|
||||
)
|
||||
|
||||
// RestartAllServer restarts all the servers of the process.
|
||||
// The optional parameter <newExeFilePath> specifies the new binary file for creating process.
|
||||
func RestartAllServer(newExeFilePath ...string) error {
|
||||
func RestartAllServer(ctx context.Context, newExeFilePath ...string) error {
|
||||
if !gracefulEnabled {
|
||||
return gerror.NewCode(gcode.CodeInvalidOperation, "graceful reload feature is disabled")
|
||||
}
|
||||
@ -63,11 +65,11 @@ func RestartAllServer(newExeFilePath ...string) error {
|
||||
if err := checkActionFrequency(); err != nil {
|
||||
return err
|
||||
}
|
||||
return restartWebServers("", newExeFilePath...)
|
||||
return restartWebServers(ctx, "", newExeFilePath...)
|
||||
}
|
||||
|
||||
// ShutdownAllServer shuts down all servers of current process.
|
||||
func ShutdownAllServer() error {
|
||||
func ShutdownAllServer(ctx context.Context) error {
|
||||
serverActionLocker.Lock()
|
||||
defer serverActionLocker.Unlock()
|
||||
if err := checkProcessStatus(); err != nil {
|
||||
@ -76,7 +78,7 @@ func ShutdownAllServer() error {
|
||||
if err := checkActionFrequency(); err != nil {
|
||||
return err
|
||||
}
|
||||
shutdownWebServers()
|
||||
shutdownWebServers(ctx)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -111,8 +113,10 @@ func checkActionFrequency() error {
|
||||
}
|
||||
|
||||
// forkReloadProcess creates a new child process and copies the fd to child process.
|
||||
func forkReloadProcess(newExeFilePath ...string) error {
|
||||
path := os.Args[0]
|
||||
func forkReloadProcess(ctx context.Context, newExeFilePath ...string) error {
|
||||
var (
|
||||
path = os.Args[0]
|
||||
)
|
||||
if len(newExeFilePath) > 0 {
|
||||
path = newExeFilePath[0]
|
||||
}
|
||||
@ -141,24 +145,36 @@ func forkReloadProcess(newExeFilePath ...string) error {
|
||||
buffer, _ := gjson.Encode(sfm)
|
||||
p.Env = append(p.Env, adminActionReloadEnvKey+"="+string(buffer))
|
||||
if _, err := p.Start(); err != nil {
|
||||
glog.Errorf("%d: fork process failed, error:%s, %s", gproc.Pid(), err.Error(), string(buffer))
|
||||
glog.Errorf(
|
||||
ctx,
|
||||
"%d: fork process failed, error:%s, %s",
|
||||
gproc.Pid(), err.Error(), string(buffer),
|
||||
)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// forkRestartProcess creates a new server process.
|
||||
func forkRestartProcess(newExeFilePath ...string) error {
|
||||
path := os.Args[0]
|
||||
func forkRestartProcess(ctx context.Context, newExeFilePath ...string) error {
|
||||
var (
|
||||
path = os.Args[0]
|
||||
)
|
||||
if len(newExeFilePath) > 0 {
|
||||
path = newExeFilePath[0]
|
||||
}
|
||||
os.Unsetenv(adminActionReloadEnvKey)
|
||||
if err := os.Unsetenv(adminActionReloadEnvKey); err != nil {
|
||||
intlog.Error(ctx, err)
|
||||
}
|
||||
env := os.Environ()
|
||||
env = append(env, adminActionRestartEnvKey+"=1")
|
||||
p := gproc.NewProcess(path, os.Args, env)
|
||||
if _, err := p.Start(); err != nil {
|
||||
glog.Errorf(`%d: fork process failed, error:%s, are you running using "go run"?`, gproc.Pid(), err.Error())
|
||||
glog.Errorf(
|
||||
ctx,
|
||||
`%d: fork process failed, error:%s, are you running using "go run"?`,
|
||||
gproc.Pid(), err.Error(),
|
||||
)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@ -180,9 +196,9 @@ func bufferToServerFdMap(buffer []byte) map[string]listenerFdMap {
|
||||
sfm := make(map[string]listenerFdMap)
|
||||
if len(buffer) > 0 {
|
||||
j, _ := gjson.LoadContent(buffer)
|
||||
for k, _ := range j.Map() {
|
||||
for k, _ := range j.Var().Map() {
|
||||
m := make(map[string]string)
|
||||
for k, v := range j.GetMap(k) {
|
||||
for k, v := range j.Get(k).Map() {
|
||||
m[k] = gconv.String(v)
|
||||
}
|
||||
sfm[k] = m
|
||||
@ -192,76 +208,79 @@ func bufferToServerFdMap(buffer []byte) map[string]listenerFdMap {
|
||||
}
|
||||
|
||||
// restartWebServers restarts all servers.
|
||||
func restartWebServers(signal string, newExeFilePath ...string) error {
|
||||
func restartWebServers(ctx context.Context, signal string, newExeFilePath ...string) error {
|
||||
serverProcessStatus.Set(adminActionRestarting)
|
||||
if runtime.GOOS == "windows" {
|
||||
if len(signal) > 0 {
|
||||
// Controlled by signal.
|
||||
forceCloseWebServers()
|
||||
forkRestartProcess(newExeFilePath...)
|
||||
forceCloseWebServers(ctx)
|
||||
if err := forkRestartProcess(ctx, newExeFilePath...); err != nil {
|
||||
intlog.Error(ctx, err)
|
||||
}
|
||||
} else {
|
||||
// Controlled by web page.
|
||||
// It should ensure the response wrote to client and then close all servers gracefully.
|
||||
gtimer.SetTimeout(time.Second, func() {
|
||||
forceCloseWebServers()
|
||||
forkRestartProcess(newExeFilePath...)
|
||||
forceCloseWebServers(ctx)
|
||||
if err := forkRestartProcess(ctx, newExeFilePath...); err != nil {
|
||||
intlog.Error(ctx, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
if err := forkReloadProcess(newExeFilePath...); err != nil {
|
||||
glog.Printf("%d: server restarts failed", gproc.Pid())
|
||||
if err := forkReloadProcess(ctx, newExeFilePath...); err != nil {
|
||||
glog.Printf(ctx, "%d: server restarts failed", gproc.Pid())
|
||||
serverProcessStatus.Set(adminActionNone)
|
||||
return err
|
||||
} else {
|
||||
if len(signal) > 0 {
|
||||
glog.Printf("%d: server restarting by signal: %s", gproc.Pid(), signal)
|
||||
glog.Printf(ctx, "%d: server restarting by signal: %s", gproc.Pid(), signal)
|
||||
} else {
|
||||
glog.Printf("%d: server restarting by web admin", gproc.Pid())
|
||||
glog.Printf(ctx, "%d: server restarting by web admin", gproc.Pid())
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// shutdownWebServers shuts down all servers.
|
||||
func shutdownWebServers(signal ...string) {
|
||||
func shutdownWebServers(ctx context.Context, signal ...string) {
|
||||
serverProcessStatus.Set(adminActionShuttingDown)
|
||||
if len(signal) > 0 {
|
||||
glog.Printf("%d: server shutting down by signal: %s", gproc.Pid(), signal[0])
|
||||
forceCloseWebServers()
|
||||
glog.Printf(ctx, "%d: server shutting down by signal: %s", gproc.Pid(), signal[0])
|
||||
forceCloseWebServers(ctx)
|
||||
allDoneChan <- struct{}{}
|
||||
} else {
|
||||
glog.Printf("%d: server shutting down by api", gproc.Pid())
|
||||
glog.Printf(ctx, "%d: server shutting down by api", gproc.Pid())
|
||||
gtimer.SetTimeout(time.Second, func() {
|
||||
forceCloseWebServers()
|
||||
forceCloseWebServers(ctx)
|
||||
allDoneChan <- struct{}{}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// shutdownWebServersGracefully gracefully shuts down all servers.
|
||||
func shutdownWebServersGracefully(signal ...string) {
|
||||
func shutdownWebServersGracefully(ctx context.Context, signal ...string) {
|
||||
if len(signal) > 0 {
|
||||
glog.Printf("%d: server gracefully shutting down by signal: %s", gproc.Pid(), signal[0])
|
||||
glog.Printf(ctx, "%d: server gracefully shutting down by signal: %s", gproc.Pid(), signal[0])
|
||||
} else {
|
||||
glog.Printf("%d: server gracefully shutting down by api", gproc.Pid())
|
||||
glog.Printf(ctx, "%d: server gracefully shutting down by api", gproc.Pid())
|
||||
}
|
||||
serverMapping.RLockFunc(func(m map[string]interface{}) {
|
||||
for _, v := range m {
|
||||
for _, s := range v.(*Server).servers {
|
||||
s.shutdown()
|
||||
s.shutdown(ctx)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// forceCloseWebServers forced shuts down all servers.
|
||||
func forceCloseWebServers() {
|
||||
func forceCloseWebServers(ctx context.Context) {
|
||||
serverMapping.RLockFunc(func(m map[string]interface{}) {
|
||||
for _, v := range m {
|
||||
for _, s := range v.(*Server).servers {
|
||||
s.close()
|
||||
s.close(ctx)
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -270,13 +289,16 @@ func forceCloseWebServers() {
|
||||
// handleProcessMessage receives and handles the message from processes,
|
||||
// which are commonly used for graceful reloading feature.
|
||||
func handleProcessMessage() {
|
||||
var (
|
||||
ctx = context.TODO()
|
||||
)
|
||||
for {
|
||||
if msg := gproc.Receive(adminGProcCommGroup); msg != nil {
|
||||
if bytes.EqualFold(msg.Data, []byte("exit")) {
|
||||
intlog.Printf(context.TODO(), "%d: process message: exit", gproc.Pid())
|
||||
shutdownWebServersGracefully()
|
||||
intlog.Printf(ctx, "%d: process message: exit", gproc.Pid())
|
||||
shutdownWebServersGracefully(ctx)
|
||||
allDoneChan <- struct{}{}
|
||||
intlog.Printf(context.TODO(), "%d: process message: exit done", gproc.Pid())
|
||||
intlog.Printf(ctx, "%d: process message: exit done", gproc.Pid())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,7 +21,10 @@ var procSignalChan = make(chan os.Signal)
|
||||
|
||||
// handleProcessSignal handles all signal from system.
|
||||
func handleProcessSignal() {
|
||||
var sig os.Signal
|
||||
var (
|
||||
ctx = context.TODO()
|
||||
sig os.Signal
|
||||
)
|
||||
signal.Notify(
|
||||
procSignalChan,
|
||||
syscall.SIGINT,
|
||||
@ -34,23 +37,23 @@ func handleProcessSignal() {
|
||||
)
|
||||
for {
|
||||
sig = <-procSignalChan
|
||||
intlog.Printf(context.TODO(), `signal received: %s`, sig.String())
|
||||
intlog.Printf(ctx, `signal received: %s`, sig.String())
|
||||
switch sig {
|
||||
// Shutdown the servers.
|
||||
case syscall.SIGINT, syscall.SIGQUIT, syscall.SIGKILL, syscall.SIGABRT:
|
||||
shutdownWebServers(sig.String())
|
||||
shutdownWebServers(ctx, sig.String())
|
||||
return
|
||||
|
||||
// Shutdown the servers gracefully.
|
||||
// Especially from K8S when running server in POD.
|
||||
case syscall.SIGTERM:
|
||||
shutdownWebServersGracefully(sig.String())
|
||||
shutdownWebServersGracefully(ctx, sig.String())
|
||||
return
|
||||
|
||||
// Restart the servers.
|
||||
case syscall.SIGUSR1:
|
||||
if err := restartWebServers(sig.String()); err != nil {
|
||||
intlog.Error(context.TODO(), err)
|
||||
if err := restartWebServers(ctx, sig.String()); err != nil {
|
||||
intlog.Error(ctx, err)
|
||||
}
|
||||
return
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package ghttp
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/internal/intlog"
|
||||
"github.com/gogf/gf/os/gres"
|
||||
"github.com/gogf/gf/util/gutil"
|
||||
@ -28,16 +27,12 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
defaultHttpAddr = ":80" // Default listening port for HTTP.
|
||||
defaultHttpsAddr = ":443" // Default listening port for HTTPS.
|
||||
URI_TYPE_DEFAULT = 0 // Deprecated, please use UriTypeDefault instead.
|
||||
URI_TYPE_FULLNAME = 1 // Deprecated, please use UriTypeFullName instead.
|
||||
URI_TYPE_ALLLOWER = 2 // Deprecated, please use UriTypeAllLower instead.
|
||||
URI_TYPE_CAMEL = 3 // Deprecated, please use UriTypeCamel instead.
|
||||
UriTypeDefault = 0 // Method name to URI converting type, which converts name to its lower case and joins the words using char '-'.
|
||||
UriTypeFullName = 1 // Method name to URI converting type, which does no converting to the method name.
|
||||
UriTypeAllLower = 2 // Method name to URI converting type, which converts name to its lower case.
|
||||
UriTypeCamel = 3 // Method name to URI converting type, which converts name to its camel case.
|
||||
defaultHttpAddr = ":80" // Default listening port for HTTP.
|
||||
defaultHttpsAddr = ":443" // Default listening port for HTTPS.
|
||||
UriTypeDefault = 0 // Method names to URI converting type, which converts name to its lower case and joins the words using char '-'.
|
||||
UriTypeFullName = 1 // Method names to URI converting type, which does no converting to the method name.
|
||||
UriTypeAllLower = 2 // Method names to URI converting type, which converts name to its lower case.
|
||||
UriTypeCamel = 3 // Method names to URI converting type, which converts name to its camel case.
|
||||
)
|
||||
|
||||
// ServerConfig is the HTTP Server configuration manager.
|
||||
@ -228,12 +223,6 @@ type ServerConfig struct {
|
||||
GracefulTimeout uint8 `json:"gracefulTimeout"`
|
||||
}
|
||||
|
||||
// Config creates and returns a ServerConfig object with default configurations.
|
||||
// Deprecated. Use NewConfig instead.
|
||||
func Config() ServerConfig {
|
||||
return NewConfig()
|
||||
}
|
||||
|
||||
// NewConfig creates and returns a ServerConfig object with default configurations.
|
||||
// Note that, do not define this default configuration to local package variable, as there are
|
||||
// some pointer attributes that may be shared in different servers.
|
||||
@ -340,8 +329,7 @@ func (s *Server) SetConfig(c ServerConfig) error {
|
||||
if err := s.config.Logger.SetLevelStr(s.config.LogLevel); err != nil {
|
||||
intlog.Error(context.TODO(), err)
|
||||
}
|
||||
|
||||
SetGraceful(c.Graceful)
|
||||
gracefulEnabled = c.Graceful
|
||||
intlog.Printf(context.TODO(), "SetConfig: %+v", s.config)
|
||||
return nil
|
||||
}
|
||||
@ -388,6 +376,9 @@ func (s *Server) SetHTTPSPort(port ...int) {
|
||||
// EnableHTTPS enables HTTPS with given certification and key files for the server.
|
||||
// The optional parameter <tlsConfig> specifies custom TLS configuration.
|
||||
func (s *Server) EnableHTTPS(certFile, keyFile string, tlsConfig ...*tls.Config) {
|
||||
var (
|
||||
ctx = context.TODO()
|
||||
)
|
||||
certFileRealPath := gfile.RealPath(certFile)
|
||||
if certFileRealPath == "" {
|
||||
certFileRealPath = gfile.RealPath(gfile.Pwd() + gfile.Separator + certFile)
|
||||
@ -400,7 +391,7 @@ func (s *Server) EnableHTTPS(certFile, keyFile string, tlsConfig ...*tls.Config)
|
||||
certFileRealPath = certFile
|
||||
}
|
||||
if certFileRealPath == "" {
|
||||
s.Logger().Fatal(fmt.Sprintf(`EnableHTTPS failed: certFile "%s" does not exist`, certFile))
|
||||
s.Logger().Fatalf(ctx, `EnableHTTPS failed: certFile "%s" does not exist`, certFile)
|
||||
}
|
||||
keyFileRealPath := gfile.RealPath(keyFile)
|
||||
if keyFileRealPath == "" {
|
||||
@ -414,7 +405,7 @@ func (s *Server) EnableHTTPS(certFile, keyFile string, tlsConfig ...*tls.Config)
|
||||
keyFileRealPath = keyFile
|
||||
}
|
||||
if keyFileRealPath == "" {
|
||||
s.Logger().Fatal(fmt.Sprintf(`EnableHTTPS failed: keyFile "%s" does not exist`, keyFile))
|
||||
s.Logger().Fatal(ctx, `EnableHTTPS failed: keyFile "%s" does not exist`, keyFile)
|
||||
}
|
||||
s.config.HTTPSCertPath = certFileRealPath
|
||||
s.config.HTTPSKeyPath = keyFileRealPath
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/os/gres"
|
||||
@ -50,25 +50,31 @@ func (s *Server) SetFileServerEnabled(enabled bool) {
|
||||
|
||||
// SetServerRoot sets the document root for static service.
|
||||
func (s *Server) SetServerRoot(root string) {
|
||||
realPath := root
|
||||
var (
|
||||
ctx = context.TODO()
|
||||
realPath = root
|
||||
)
|
||||
if !gres.Contains(realPath) {
|
||||
if p, err := gfile.Search(root); err != nil {
|
||||
s.Logger().Fatal(fmt.Sprintf(`SetServerRoot failed: %v`, err))
|
||||
s.Logger().Fatal(ctx, `SetServerRoot failed: %v`, err)
|
||||
} else {
|
||||
realPath = p
|
||||
}
|
||||
}
|
||||
s.Logger().Debug("SetServerRoot path:", realPath)
|
||||
s.Logger().Debug(ctx, "SetServerRoot path:", realPath)
|
||||
s.config.SearchPaths = []string{strings.TrimRight(realPath, gfile.Separator)}
|
||||
s.config.FileServerEnabled = true
|
||||
}
|
||||
|
||||
// AddSearchPath add searching directory path for static file service.
|
||||
func (s *Server) AddSearchPath(path string) {
|
||||
realPath := path
|
||||
var (
|
||||
ctx = context.TODO()
|
||||
realPath = path
|
||||
)
|
||||
if !gres.Contains(realPath) {
|
||||
if p, err := gfile.Search(path); err != nil {
|
||||
s.Logger().Fatal(fmt.Sprintf(`AddSearchPath failed: %v`, err))
|
||||
s.Logger().Fatalf(ctx, `AddSearchPath failed: %v`, err)
|
||||
} else {
|
||||
realPath = p
|
||||
}
|
||||
@ -79,10 +85,13 @@ func (s *Server) AddSearchPath(path string) {
|
||||
|
||||
// AddStaticPath sets the uri to static directory path mapping for static file service.
|
||||
func (s *Server) AddStaticPath(prefix string, path string) {
|
||||
realPath := path
|
||||
var (
|
||||
ctx = context.TODO()
|
||||
realPath = path
|
||||
)
|
||||
if !gres.Contains(realPath) {
|
||||
if p, err := gfile.Search(path); err != nil {
|
||||
s.Logger().Fatal(fmt.Sprintf(`AddStaticPath failed: %v`, err))
|
||||
s.Logger().Fatalf(ctx, `AddStaticPath failed: %v`, err)
|
||||
} else {
|
||||
realPath = p
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/container/gvar"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
@ -89,7 +90,7 @@ func (c *Cookie) Set(key, value string) {
|
||||
)
|
||||
}
|
||||
|
||||
// SetCookie sets cookie item given given domain, path and expiration age.
|
||||
// SetCookie sets cookie item with given domain, path and expiration age.
|
||||
// The optional parameter <httpOnly> specifies if the cookie item is only available in HTTP,
|
||||
// which is usually empty.
|
||||
func (c *Cookie) SetCookie(key, value, domain, path string, maxAge time.Duration, httpOnly ...bool) {
|
||||
@ -123,7 +124,7 @@ func (c *Cookie) SetHttpCookie(httpCookie *http.Cookie) {
|
||||
|
||||
// GetSessionId retrieves and returns the session id from cookie.
|
||||
func (c *Cookie) GetSessionId() string {
|
||||
return c.Get(c.server.GetSessionIdName())
|
||||
return c.Get(c.server.GetSessionIdName()).String()
|
||||
}
|
||||
|
||||
// SetSessionId sets session id in the cookie.
|
||||
@ -139,17 +140,17 @@ func (c *Cookie) SetSessionId(id string) {
|
||||
|
||||
// Get retrieves and returns the value with specified key.
|
||||
// It returns <def> if specified key does not exist and <def> is given.
|
||||
func (c *Cookie) Get(key string, def ...string) string {
|
||||
func (c *Cookie) Get(key string, def ...string) *gvar.Var {
|
||||
c.init()
|
||||
if r, ok := c.data[key]; ok {
|
||||
if r.Expires.IsZero() || r.Expires.After(time.Now()) {
|
||||
return r.Value
|
||||
return gvar.New(r.Value)
|
||||
}
|
||||
}
|
||||
if len(def) > 0 {
|
||||
return def[0]
|
||||
return gvar.New(def[0])
|
||||
}
|
||||
return ""
|
||||
return nil
|
||||
}
|
||||
|
||||
// Remove deletes specified key and its value from cookie using default domain and path.
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@ -34,9 +35,9 @@ func (d *Domain) BindHandler(pattern string, handler interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Domain) doBindHandler(pattern string, funcInfo handlerFuncInfo, middleware []HandlerFunc, source string) {
|
||||
func (d *Domain) doBindHandler(ctx context.Context, pattern string, funcInfo handlerFuncInfo, middleware []HandlerFunc, source string) {
|
||||
for domain, _ := range d.domains {
|
||||
d.server.doBindHandler(pattern+"@"+domain, funcInfo, middleware, source)
|
||||
d.server.doBindHandler(ctx, pattern+"@"+domain, funcInfo, middleware, source)
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,9 +47,9 @@ func (d *Domain) BindObject(pattern string, obj interface{}, methods ...string)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Domain) doBindObject(pattern string, obj interface{}, methods string, middleware []HandlerFunc, source string) {
|
||||
func (d *Domain) doBindObject(ctx context.Context, pattern string, obj interface{}, methods string, middleware []HandlerFunc, source string) {
|
||||
for domain, _ := range d.domains {
|
||||
d.server.doBindObject(pattern+"@"+domain, obj, methods, middleware, source)
|
||||
d.server.doBindObject(ctx, pattern+"@"+domain, obj, methods, middleware, source)
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,11 +60,12 @@ func (d *Domain) BindObjectMethod(pattern string, obj interface{}, method string
|
||||
}
|
||||
|
||||
func (d *Domain) doBindObjectMethod(
|
||||
ctx context.Context,
|
||||
pattern string, obj interface{}, method string,
|
||||
middleware []HandlerFunc, source string,
|
||||
) {
|
||||
for domain, _ := range d.domains {
|
||||
d.server.doBindObjectMethod(pattern+"@"+domain, obj, method, middleware, source)
|
||||
d.server.doBindObjectMethod(ctx, pattern+"@"+domain, obj, method, middleware, source)
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,9 +75,9 @@ func (d *Domain) BindObjectRest(pattern string, obj interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Domain) doBindObjectRest(pattern string, obj interface{}, middleware []HandlerFunc, source string) {
|
||||
func (d *Domain) doBindObjectRest(ctx context.Context, pattern string, obj interface{}, middleware []HandlerFunc, source string) {
|
||||
for domain, _ := range d.domains {
|
||||
d.server.doBindObjectRest(pattern+"@"+domain, obj, middleware, source)
|
||||
d.server.doBindObjectRest(ctx, pattern+"@"+domain, obj, middleware, source)
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,9 +87,9 @@ func (d *Domain) BindHookHandler(pattern string, hook string, handler HandlerFun
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Domain) doBindHookHandler(pattern string, hook string, handler HandlerFunc, source string) {
|
||||
func (d *Domain) doBindHookHandler(ctx context.Context, pattern string, hook string, handler HandlerFunc, source string) {
|
||||
for domain, _ := range d.domains {
|
||||
d.server.doBindHookHandler(pattern+"@"+domain, hook, handler, source)
|
||||
d.server.doBindHookHandler(ctx, pattern+"@"+domain, hook, handler, source)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@ package ghttp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"github.com/gogf/gf/os/glog"
|
||||
)
|
||||
|
||||
@ -18,6 +19,6 @@ type errorLogger struct {
|
||||
|
||||
// Write implements the io.Writer interface.
|
||||
func (l *errorLogger) Write(p []byte) (n int, err error) {
|
||||
l.logger.Skip(1).Error(string(bytes.TrimRight(p, "\r\n")))
|
||||
l.logger.Skip(1).Error(context.TODO(), string(bytes.TrimRight(p, "\r\n")))
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ func (s *gracefulServer) ListenAndServe() error {
|
||||
}
|
||||
s.listener = ln
|
||||
s.rawListener = ln
|
||||
return s.doServe()
|
||||
return s.doServe(context.TODO())
|
||||
}
|
||||
|
||||
// Fd retrieves and returns the file descriptor of current server.
|
||||
@ -97,7 +97,10 @@ func (s *gracefulServer) setFd(fd int) {
|
||||
// The parameter <certFile> and <keyFile> specify the necessary certification and key files for HTTPS.
|
||||
// The optional parameter <tlsConfig> specifies the custom TLS configuration.
|
||||
func (s *gracefulServer) ListenAndServeTLS(certFile, keyFile string, tlsConfig ...*tls.Config) error {
|
||||
var config *tls.Config
|
||||
var (
|
||||
ctx = context.TODO()
|
||||
config *tls.Config
|
||||
)
|
||||
if len(tlsConfig) > 0 && tlsConfig[0] != nil {
|
||||
config = tlsConfig[0]
|
||||
} else if s.httpServer.TLSConfig != nil {
|
||||
@ -131,7 +134,7 @@ func (s *gracefulServer) ListenAndServeTLS(certFile, keyFile string, tlsConfig .
|
||||
|
||||
s.listener = tls.NewListener(ln, config)
|
||||
s.rawListener = ln
|
||||
return s.doServe()
|
||||
return s.doServe(ctx)
|
||||
}
|
||||
|
||||
// getProto retrieves and returns the proto string of current server.
|
||||
@ -143,13 +146,14 @@ func (s *gracefulServer) getProto() string {
|
||||
return proto
|
||||
}
|
||||
|
||||
// doServe does staring the serving.
|
||||
func (s *gracefulServer) doServe() error {
|
||||
// doServe starts the serving.
|
||||
func (s *gracefulServer) doServe(ctx context.Context) error {
|
||||
action := "started"
|
||||
if s.fd != 0 {
|
||||
action = "reloaded"
|
||||
}
|
||||
s.server.Logger().Printf(
|
||||
ctx,
|
||||
"%d: %s server %s listening on [%s]",
|
||||
gproc.Pid(), s.getProto(), action, s.address,
|
||||
)
|
||||
@ -182,12 +186,13 @@ func (s *gracefulServer) getNetListener() (net.Listener, error) {
|
||||
}
|
||||
|
||||
// shutdown shuts down the server gracefully.
|
||||
func (s *gracefulServer) shutdown() {
|
||||
func (s *gracefulServer) shutdown(ctx context.Context) {
|
||||
if s.status == ServerStatusStopped {
|
||||
return
|
||||
}
|
||||
if err := s.httpServer.Shutdown(context.Background()); err != nil {
|
||||
s.server.Logger().Errorf(
|
||||
ctx,
|
||||
"%d: %s server [%s] shutdown error: %v",
|
||||
gproc.Pid(), s.getProto(), s.address, err,
|
||||
)
|
||||
@ -195,12 +200,13 @@ func (s *gracefulServer) shutdown() {
|
||||
}
|
||||
|
||||
// close shuts down the server forcibly.
|
||||
func (s *gracefulServer) close() {
|
||||
func (s *gracefulServer) close(ctx context.Context) {
|
||||
if s.status == ServerStatusStopped {
|
||||
return
|
||||
}
|
||||
if err := s.httpServer.Close(); err != nil {
|
||||
s.server.Logger().Errorf(
|
||||
ctx,
|
||||
"%d: %s server [%s] closed error: %v",
|
||||
gproc.Pid(), s.getProto(), s.address, err,
|
||||
)
|
||||
|
||||
@ -184,8 +184,8 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
// and SessionCookieOutput is enabled.
|
||||
if s.config.SessionCookieOutput &&
|
||||
request.Session.IsDirty() &&
|
||||
request.Session.Id() != request.GetSessionId() {
|
||||
request.Cookie.SetSessionId(request.Session.Id())
|
||||
request.Session.MustId() != request.GetSessionId() {
|
||||
request.Cookie.SetSessionId(request.Session.MustId())
|
||||
}
|
||||
// Output the cookie content to client.
|
||||
request.Cookie.Flush()
|
||||
|
||||
@ -20,9 +20,10 @@ func (s *Server) handleAccessLog(r *Request) {
|
||||
if r.TLS != nil {
|
||||
scheme = "https"
|
||||
}
|
||||
s.Logger().Ctx(r.Context()).File(s.config.AccessLogPattern).
|
||||
s.Logger().File(s.config.AccessLogPattern).
|
||||
Stdout(s.config.LogStdout).
|
||||
Printf(
|
||||
r.Context(),
|
||||
`%d "%s %s %s %s %s" %.3f, %s, "%s", "%s"`,
|
||||
r.Response.Status,
|
||||
r.Method, scheme, r.Host, r.URL.String(), r.Proto,
|
||||
@ -57,8 +58,7 @@ func (s *Server) handleErrorLog(err error, r *Request) {
|
||||
} else {
|
||||
content += ", " + err.Error()
|
||||
}
|
||||
s.Logger().Ctx(r.Context()).
|
||||
File(s.config.ErrorLogPattern).
|
||||
s.Logger().File(s.config.ErrorLogPattern).
|
||||
Stdout(s.config.LogStdout).
|
||||
Print(content)
|
||||
Print(r.Context(), content)
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/internal/intlog"
|
||||
netpprof "net/http/pprof"
|
||||
runpprof "runtime/pprof"
|
||||
"strings"
|
||||
@ -55,12 +56,15 @@ func (d *Domain) EnablePProf(pattern ...string) {
|
||||
|
||||
// Index shows the PProf index page.
|
||||
func (p *utilPProf) Index(r *Request) {
|
||||
profiles := runpprof.Profiles()
|
||||
action := r.GetString("action")
|
||||
data := map[string]interface{}{
|
||||
"uri": strings.TrimRight(r.URL.Path, "/") + "/",
|
||||
"profiles": profiles,
|
||||
}
|
||||
var (
|
||||
ctx = r.Context()
|
||||
profiles = runpprof.Profiles()
|
||||
action = r.Get("action").String()
|
||||
data = map[string]interface{}{
|
||||
"uri": strings.TrimRight(r.URL.Path, "/") + "/",
|
||||
"profiles": profiles,
|
||||
}
|
||||
)
|
||||
if len(action) == 0 {
|
||||
buffer, _ := gview.ParseContent(r.Context(), `
|
||||
<html>
|
||||
@ -87,7 +91,9 @@ func (p *utilPProf) Index(r *Request) {
|
||||
}
|
||||
for _, p := range profiles {
|
||||
if p.Name() == action {
|
||||
p.WriteTo(r.Response.Writer, r.GetRequestInt("debug"))
|
||||
if err := p.WriteTo(r.Response.Writer, r.GetRequest("debug").Int()); err != nil {
|
||||
intlog.Error(ctx, err)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/container/gtype"
|
||||
"github.com/gogf/gf/errors/gcode"
|
||||
@ -65,8 +66,8 @@ func (s *Server) parsePattern(pattern string) (domain, method, path string, err
|
||||
// setHandler creates router item with given handler and pattern and registers the handler to the router tree.
|
||||
// The router tree can be treated as a multilayer hash table, please refer to the comment in following codes.
|
||||
// This function is called during server starts up, which cares little about the performance. What really cares
|
||||
// is the well designed router storage structure for router searching when the request is under serving.
|
||||
func (s *Server) setHandler(pattern string, handler *handlerItem) {
|
||||
// is the well-designed router storage structure for router searching when the request is under serving.
|
||||
func (s *Server) setHandler(ctx context.Context, pattern string, handler *handlerItem) {
|
||||
handler.Id = handlerIdGenerator.Add(1)
|
||||
if handler.Source == "" {
|
||||
_, file, line := gdebug.CallerWithFilter(stackFilterKey)
|
||||
@ -74,11 +75,11 @@ func (s *Server) setHandler(pattern string, handler *handlerItem) {
|
||||
}
|
||||
domain, method, uri, err := s.parsePattern(pattern)
|
||||
if err != nil {
|
||||
s.Logger().Fatal("invalid pattern:", pattern, err)
|
||||
s.Logger().Fatal(ctx, "invalid pattern:", pattern, err)
|
||||
return
|
||||
}
|
||||
if len(uri) == 0 || uri[0] != '/' {
|
||||
s.Logger().Fatal("invalid pattern:", pattern, "URI should lead with '/'")
|
||||
s.Logger().Fatal(ctx, "invalid pattern:", pattern, "URI should lead with '/'")
|
||||
return
|
||||
}
|
||||
|
||||
@ -89,6 +90,7 @@ func (s *Server) setHandler(pattern string, handler *handlerItem) {
|
||||
case handlerTypeHandler, handlerTypeObject, handlerTypeController:
|
||||
if item, ok := s.routesMap[routerKey]; ok {
|
||||
s.Logger().Fatalf(
|
||||
ctx,
|
||||
`duplicated route registry "%s" at %s , already registered at %s`,
|
||||
pattern, handler.Source, item[0].Source,
|
||||
)
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/debug/gdebug"
|
||||
"reflect"
|
||||
@ -55,7 +56,7 @@ var (
|
||||
)
|
||||
|
||||
// handlePreBindItems is called when server starts, which does really route registering to the server.
|
||||
func (s *Server) handlePreBindItems() {
|
||||
func (s *Server) handlePreBindItems(ctx context.Context) {
|
||||
if len(preBindItems) == 0 {
|
||||
return
|
||||
}
|
||||
@ -70,7 +71,7 @@ func (s *Server) handlePreBindItems() {
|
||||
if item.group.domain != nil && item.group.domain.server != s {
|
||||
continue
|
||||
}
|
||||
item.group.doBindRoutersToServer(item)
|
||||
item.group.doBindRoutersToServer(ctx, item)
|
||||
item.bound = true
|
||||
}
|
||||
}
|
||||
@ -153,10 +154,13 @@ func (g *RouterGroup) Clone() *RouterGroup {
|
||||
|
||||
// Bind does batch route registering feature for router group.
|
||||
func (g *RouterGroup) Bind(items []GroupItem) *RouterGroup {
|
||||
group := g.Clone()
|
||||
var (
|
||||
ctx = context.TODO()
|
||||
group = g.Clone()
|
||||
)
|
||||
for _, item := range items {
|
||||
if len(item) < 3 {
|
||||
g.server.Logger().Fatalf("invalid router item: %s", item)
|
||||
g.server.Logger().Fatalf(ctx, "invalid router item: %s", item)
|
||||
}
|
||||
bindType := gstr.ToUpper(gconv.String(item[0]))
|
||||
switch bindType {
|
||||
@ -288,7 +292,7 @@ func (g *RouterGroup) getPrefix() string {
|
||||
}
|
||||
|
||||
// doBindRoutersToServer does really register for the group.
|
||||
func (g *RouterGroup) doBindRoutersToServer(item *preBindItem) *RouterGroup {
|
||||
func (g *RouterGroup) doBindRoutersToServer(ctx context.Context, item *preBindItem) *RouterGroup {
|
||||
var (
|
||||
bindType = item.bindType
|
||||
pattern = item.pattern
|
||||
@ -301,7 +305,7 @@ func (g *RouterGroup) doBindRoutersToServer(item *preBindItem) *RouterGroup {
|
||||
if len(prefix) > 0 {
|
||||
domain, method, path, err := g.server.parsePattern(pattern)
|
||||
if err != nil {
|
||||
g.server.Logger().Fatalf("invalid pattern: %s", pattern)
|
||||
g.server.Logger().Fatalf(ctx, "invalid pattern: %s", pattern)
|
||||
}
|
||||
// If there is already a domain, unset the domain field in the pattern.
|
||||
if g.domain != nil {
|
||||
@ -330,63 +334,63 @@ func (g *RouterGroup) doBindRoutersToServer(item *preBindItem) *RouterGroup {
|
||||
if reflect.ValueOf(object).Kind() == reflect.Func {
|
||||
funcInfo, err := g.server.checkAndCreateFuncInfo(object, "", "", "")
|
||||
if err != nil {
|
||||
g.server.Logger().Error(err.Error())
|
||||
g.server.Logger().Error(ctx, err.Error())
|
||||
return g
|
||||
}
|
||||
if g.server != nil {
|
||||
g.server.doBindHandler(pattern, funcInfo, g.middleware, source)
|
||||
g.server.doBindHandler(ctx, pattern, funcInfo, g.middleware, source)
|
||||
} else {
|
||||
g.domain.doBindHandler(pattern, funcInfo, g.middleware, source)
|
||||
g.domain.doBindHandler(ctx, pattern, funcInfo, g.middleware, source)
|
||||
}
|
||||
} else {
|
||||
if len(extras) > 0 {
|
||||
if g.server != nil {
|
||||
if gstr.Contains(extras[0], ",") {
|
||||
g.server.doBindObject(
|
||||
pattern, object, extras[0], g.middleware, source,
|
||||
ctx, pattern, object, extras[0], g.middleware, source,
|
||||
)
|
||||
} else {
|
||||
g.server.doBindObjectMethod(
|
||||
pattern, object, extras[0], g.middleware, source,
|
||||
ctx, pattern, object, extras[0], g.middleware, source,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if gstr.Contains(extras[0], ",") {
|
||||
g.domain.doBindObject(
|
||||
pattern, object, extras[0], g.middleware, source,
|
||||
ctx, pattern, object, extras[0], g.middleware, source,
|
||||
)
|
||||
} else {
|
||||
g.domain.doBindObjectMethod(
|
||||
pattern, object, extras[0], g.middleware, source,
|
||||
ctx, pattern, object, extras[0], g.middleware, source,
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// At last, it treats the `object` as Object registering type.
|
||||
if g.server != nil {
|
||||
g.server.doBindObject(pattern, object, "", g.middleware, source)
|
||||
g.server.doBindObject(ctx, pattern, object, "", g.middleware, source)
|
||||
} else {
|
||||
g.domain.doBindObject(pattern, object, "", g.middleware, source)
|
||||
g.domain.doBindObject(ctx, pattern, object, "", g.middleware, source)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case groupBindTypeRest:
|
||||
if g.server != nil {
|
||||
g.server.doBindObjectRest(pattern, object, g.middleware, source)
|
||||
g.server.doBindObjectRest(ctx, pattern, object, g.middleware, source)
|
||||
} else {
|
||||
g.domain.doBindObjectRest(pattern, object, g.middleware, source)
|
||||
g.domain.doBindObjectRest(ctx, pattern, object, g.middleware, source)
|
||||
}
|
||||
|
||||
case groupBindTypeHook:
|
||||
if h, ok := object.(HandlerFunc); ok {
|
||||
if g.server != nil {
|
||||
g.server.doBindHookHandler(pattern, extras[0], h, source)
|
||||
g.server.doBindHookHandler(ctx, pattern, extras[0], h, source)
|
||||
} else {
|
||||
g.domain.doBindHookHandler(pattern, extras[0], h, source)
|
||||
g.domain.doBindHookHandler(ctx, pattern, extras[0], h, source)
|
||||
}
|
||||
} else {
|
||||
g.server.Logger().Fatalf("invalid hook handler for pattern: %s", pattern)
|
||||
g.server.Logger().Fatalf(ctx, "invalid hook handler for pattern: %s", pattern)
|
||||
}
|
||||
}
|
||||
return g
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/debug/gdebug"
|
||||
"net/http"
|
||||
"reflect"
|
||||
@ -14,11 +15,11 @@ import (
|
||||
|
||||
// BindHookHandler registers handler for specified hook.
|
||||
func (s *Server) BindHookHandler(pattern string, hook string, handler HandlerFunc) {
|
||||
s.doBindHookHandler(pattern, hook, handler, "")
|
||||
s.doBindHookHandler(context.TODO(), pattern, hook, handler, "")
|
||||
}
|
||||
|
||||
func (s *Server) doBindHookHandler(pattern string, hook string, handler HandlerFunc, source string) {
|
||||
s.setHandler(pattern, &handlerItem{
|
||||
func (s *Server) doBindHookHandler(ctx context.Context, pattern string, hook string, handler HandlerFunc, source string) {
|
||||
s.setHandler(ctx, pattern, &handlerItem{
|
||||
Type: handlerTypeHook,
|
||||
Name: gdebug.FuncPath(handler),
|
||||
Info: handlerFuncInfo{
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/debug/gdebug"
|
||||
"reflect"
|
||||
)
|
||||
@ -21,8 +22,11 @@ const (
|
||||
// before or after service handler. The parameter <pattern> specifies what route pattern the middleware intercepts,
|
||||
// which is usually a "fuzzy" pattern like "/:name", "/*any" or "/{field}".
|
||||
func (s *Server) BindMiddleware(pattern string, handlers ...HandlerFunc) {
|
||||
var (
|
||||
ctx = context.TODO()
|
||||
)
|
||||
for _, handler := range handlers {
|
||||
s.setHandler(pattern, &handlerItem{
|
||||
s.setHandler(ctx, pattern, &handlerItem{
|
||||
Type: handlerTypeMiddleware,
|
||||
Name: gdebug.FuncPath(handler),
|
||||
Info: handlerFuncInfo{
|
||||
@ -37,8 +41,11 @@ func (s *Server) BindMiddleware(pattern string, handlers ...HandlerFunc) {
|
||||
// Global middleware can be used standalone without service handler, which intercepts all dynamic requests
|
||||
// before or after service handler.
|
||||
func (s *Server) BindMiddlewareDefault(handlers ...HandlerFunc) {
|
||||
var (
|
||||
ctx = context.TODO()
|
||||
)
|
||||
for _, handler := range handlers {
|
||||
s.setHandler(defaultMiddlewarePattern, &handlerItem{
|
||||
s.setHandler(ctx, defaultMiddlewarePattern, &handlerItem{
|
||||
Type: handlerTypeMiddleware,
|
||||
Name: gdebug.FuncPath(handler),
|
||||
Info: handlerFuncInfo{
|
||||
|
||||
@ -8,6 +8,7 @@ package ghttp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"github.com/gogf/gf/debug/gdebug"
|
||||
"github.com/gogf/gf/errors/gcode"
|
||||
"github.com/gogf/gf/errors/gerror"
|
||||
@ -25,19 +26,22 @@ import (
|
||||
// func(context.Context,TypeRequest) error
|
||||
// func(context.Context,TypeRequest)(TypeResponse,error)
|
||||
func (s *Server) BindHandler(pattern string, handler interface{}) {
|
||||
var (
|
||||
ctx = context.TODO()
|
||||
)
|
||||
funcInfo, err := s.checkAndCreateFuncInfo(handler, "", "", "")
|
||||
if err != nil {
|
||||
s.Logger().Error(err.Error())
|
||||
s.Logger().Error(ctx, err.Error())
|
||||
return
|
||||
}
|
||||
s.doBindHandler(pattern, funcInfo, nil, "")
|
||||
s.doBindHandler(ctx, pattern, funcInfo, nil, "")
|
||||
}
|
||||
|
||||
// doBindHandler registers a handler function to server with given pattern.
|
||||
// The parameter <pattern> is like:
|
||||
// /user/list, put:/user, delete:/user, post:/user@goframe.org
|
||||
func (s *Server) doBindHandler(pattern string, funcInfo handlerFuncInfo, middleware []HandlerFunc, source string) {
|
||||
s.setHandler(pattern, &handlerItem{
|
||||
func (s *Server) doBindHandler(ctx context.Context, pattern string, funcInfo handlerFuncInfo, middleware []HandlerFunc, source string) {
|
||||
s.setHandler(ctx, pattern, &handlerItem{
|
||||
Name: gdebug.FuncPath(funcInfo.Func),
|
||||
Type: handlerTypeHandler,
|
||||
Info: funcInfo,
|
||||
@ -47,9 +51,9 @@ func (s *Server) doBindHandler(pattern string, funcInfo handlerFuncInfo, middlew
|
||||
}
|
||||
|
||||
// bindHandlerByMap registers handlers to server using map.
|
||||
func (s *Server) bindHandlerByMap(m map[string]*handlerItem) {
|
||||
func (s *Server) bindHandlerByMap(ctx context.Context, m map[string]*handlerItem) {
|
||||
for p, h := range m {
|
||||
s.setHandler(p, h)
|
||||
s.setHandler(ctx, p, h)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
@ -19,36 +20,40 @@ import (
|
||||
// BindObject registers object to server routes with given pattern.
|
||||
//
|
||||
// The optional parameter <method> is used to specify the method to be registered, which
|
||||
// supports multiple method names, multiple methods are separated by char ',', case sensitive.
|
||||
// supports multiple method names, multiple methods are separated by char ',', case-sensitive.
|
||||
//
|
||||
// Note that the route method should be defined as ghttp.HandlerFunc.
|
||||
func (s *Server) BindObject(pattern string, object interface{}, method ...string) {
|
||||
bindMethod := ""
|
||||
var (
|
||||
bindMethod = ""
|
||||
)
|
||||
if len(method) > 0 {
|
||||
bindMethod = method[0]
|
||||
}
|
||||
s.doBindObject(pattern, object, bindMethod, nil, "")
|
||||
s.doBindObject(context.TODO(), pattern, object, bindMethod, nil, "")
|
||||
}
|
||||
|
||||
// BindObjectMethod registers specified method of object to server routes with given pattern.
|
||||
//
|
||||
// The optional parameter <method> is used to specify the method to be registered, which
|
||||
// does not supports multiple method names but only one, case sensitive.
|
||||
// does not supports multiple method names but only one, case-sensitive.
|
||||
//
|
||||
// Note that the route method should be defined as ghttp.HandlerFunc.
|
||||
func (s *Server) BindObjectMethod(pattern string, object interface{}, method string) {
|
||||
s.doBindObjectMethod(pattern, object, method, nil, "")
|
||||
s.doBindObjectMethod(context.TODO(), pattern, object, method, nil, "")
|
||||
}
|
||||
|
||||
// BindObjectRest registers object in REST API style to server with specified pattern.
|
||||
// Note that the route method should be defined as ghttp.HandlerFunc.
|
||||
func (s *Server) BindObjectRest(pattern string, object interface{}) {
|
||||
s.doBindObjectRest(pattern, object, nil, "")
|
||||
s.doBindObjectRest(context.TODO(), pattern, object, nil, "")
|
||||
}
|
||||
|
||||
func (s *Server) doBindObject(pattern string, object interface{}, method string, middleware []HandlerFunc, source string) {
|
||||
func (s *Server) doBindObject(ctx context.Context, pattern string, object interface{}, method string, middleware []HandlerFunc, source string) {
|
||||
// Convert input method to map for convenience and high performance searching purpose.
|
||||
var methodMap map[string]bool
|
||||
var (
|
||||
methodMap map[string]bool
|
||||
)
|
||||
if len(method) > 0 {
|
||||
methodMap = make(map[string]bool)
|
||||
for _, v := range strings.Split(method, ",") {
|
||||
@ -59,7 +64,7 @@ func (s *Server) doBindObject(pattern string, object interface{}, method string,
|
||||
// it removes for convenience for next statement control.
|
||||
domain, method, path, err := s.parsePattern(pattern)
|
||||
if err != nil {
|
||||
s.Logger().Fatal(err)
|
||||
s.Logger().Fatal(ctx, err)
|
||||
return
|
||||
}
|
||||
if strings.EqualFold(method, defaultMethod) {
|
||||
@ -104,7 +109,7 @@ func (s *Server) doBindObject(pattern string, object interface{}, method string,
|
||||
|
||||
funcInfo, err := s.checkAndCreateFuncInfo(v.Method(i).Interface(), pkgPath, objName, methodName)
|
||||
if err != nil {
|
||||
s.Logger().Error(err.Error())
|
||||
s.Logger().Error(ctx, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@ -142,10 +147,10 @@ func (s *Server) doBindObject(pattern string, object interface{}, method string,
|
||||
}
|
||||
}
|
||||
}
|
||||
s.bindHandlerByMap(m)
|
||||
s.bindHandlerByMap(ctx, m)
|
||||
}
|
||||
|
||||
func (s *Server) doBindObjectMethod(pattern string, object interface{}, method string, middleware []HandlerFunc, source string) {
|
||||
func (s *Server) doBindObjectMethod(ctx context.Context, pattern string, object interface{}, method string, middleware []HandlerFunc, source string) {
|
||||
var (
|
||||
m = make(map[string]*handlerItem)
|
||||
v = reflect.ValueOf(object)
|
||||
@ -165,7 +170,7 @@ func (s *Server) doBindObjectMethod(pattern string, object interface{}, method s
|
||||
methodName := strings.TrimSpace(method)
|
||||
methodValue := v.MethodByName(methodName)
|
||||
if !methodValue.IsValid() {
|
||||
s.Logger().Fatal("invalid method name: " + methodName)
|
||||
s.Logger().Fatal(ctx, "invalid method name: "+methodName)
|
||||
return
|
||||
}
|
||||
if v.MethodByName("Init").IsValid() {
|
||||
@ -183,7 +188,7 @@ func (s *Server) doBindObjectMethod(pattern string, object interface{}, method s
|
||||
|
||||
funcInfo, err := s.checkAndCreateFuncInfo(methodValue.Interface(), pkgPath, objName, methodName)
|
||||
if err != nil {
|
||||
s.Logger().Error(err.Error())
|
||||
s.Logger().Error(ctx, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@ -198,10 +203,10 @@ func (s *Server) doBindObjectMethod(pattern string, object interface{}, method s
|
||||
Source: source,
|
||||
}
|
||||
|
||||
s.bindHandlerByMap(m)
|
||||
s.bindHandlerByMap(ctx, m)
|
||||
}
|
||||
|
||||
func (s *Server) doBindObjectRest(pattern string, object interface{}, middleware []HandlerFunc, source string) {
|
||||
func (s *Server) doBindObjectRest(ctx context.Context, pattern string, object interface{}, middleware []HandlerFunc, source string) {
|
||||
var (
|
||||
m = make(map[string]*handlerItem)
|
||||
v = reflect.ValueOf(object)
|
||||
@ -238,7 +243,7 @@ func (s *Server) doBindObjectRest(pattern string, object interface{}, middleware
|
||||
|
||||
funcInfo, err := s.checkAndCreateFuncInfo(v.Method(i).Interface(), pkgPath, objName, methodName)
|
||||
if err != nil {
|
||||
s.Logger().Error(err.Error())
|
||||
s.Logger().Error(ctx, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@ -253,5 +258,5 @@ func (s *Server) doBindObjectRest(pattern string, object interface{}, middleware
|
||||
Source: source,
|
||||
}
|
||||
}
|
||||
s.bindHandlerByMap(m)
|
||||
s.bindHandlerByMap(ctx, m)
|
||||
}
|
||||
|
||||
@ -42,10 +42,10 @@ func Test_Client_Basic(t *testing.T) {
|
||||
client := g.Client()
|
||||
client.SetPrefix(url)
|
||||
|
||||
t.Assert(ghttp.GetContent(""), ``)
|
||||
t.Assert(g.Client().GetContent(""), ``)
|
||||
t.Assert(client.GetContent("/hello"), `hello`)
|
||||
|
||||
_, err := ghttp.Post("")
|
||||
_, err := g.Client().Post("")
|
||||
t.AssertNE(err, nil)
|
||||
})
|
||||
}
|
||||
|
||||
@ -21,13 +21,13 @@ func Test_Cookie(t *testing.T) {
|
||||
p, _ := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.BindHandler("/set", func(r *ghttp.Request) {
|
||||
r.Cookie.Set(r.GetString("k"), r.GetString("v"))
|
||||
r.Cookie.Set(r.Get("k").String(), r.Get("v").String())
|
||||
})
|
||||
s.BindHandler("/get", func(r *ghttp.Request) {
|
||||
r.Response.Write(r.Cookie.Get(r.GetString("k")))
|
||||
r.Response.Write(r.Cookie.Get(r.Get("k").String()))
|
||||
})
|
||||
s.BindHandler("/remove", func(r *ghttp.Request) {
|
||||
r.Cookie.Remove(r.GetString("k"))
|
||||
r.Cookie.Remove(r.Get("k").String())
|
||||
})
|
||||
s.SetPort(p)
|
||||
s.SetDumpRouterMap(false)
|
||||
@ -65,15 +65,15 @@ func Test_SetHttpCookie(t *testing.T) {
|
||||
s := g.Server(p)
|
||||
s.BindHandler("/set", func(r *ghttp.Request) {
|
||||
r.Cookie.SetHttpCookie(&http.Cookie{
|
||||
Name: r.GetString("k"),
|
||||
Value: r.GetString("v"),
|
||||
Name: r.Get("k").String(),
|
||||
Value: r.Get("v").String(),
|
||||
})
|
||||
})
|
||||
s.BindHandler("/get", func(r *ghttp.Request) {
|
||||
r.Response.Write(r.Cookie.Get(r.GetString("k")))
|
||||
r.Response.Write(r.Cookie.Get(r.Get("k").String()))
|
||||
})
|
||||
s.BindHandler("/remove", func(r *ghttp.Request) {
|
||||
r.Cookie.Remove(r.GetString("k"))
|
||||
r.Cookie.Remove(r.Get("k").String())
|
||||
})
|
||||
s.SetPort(p)
|
||||
s.SetDumpRouterMap(false)
|
||||
|
||||
@ -577,7 +577,7 @@ func Test_Hook_Middleware_Basic1(t *testing.T) {
|
||||
}
|
||||
|
||||
func MiddlewareAuth(r *ghttp.Request) {
|
||||
token := r.Get("token")
|
||||
token := r.Get("token").String()
|
||||
if token == "123456" {
|
||||
r.Middleware.Next()
|
||||
} else {
|
||||
|
||||
@ -30,7 +30,7 @@ func Test_Params_File_Single(t *testing.T) {
|
||||
r.Response.WriteExit("upload file cannot be empty")
|
||||
}
|
||||
|
||||
if name, err := file.Save(dstDirPath, r.GetBool("randomlyRename")); err == nil {
|
||||
if name, err := file.Save(dstDirPath, r.Get("randomlyRename").Bool()); err == nil {
|
||||
r.Response.WriteExit(name)
|
||||
}
|
||||
r.Response.WriteExit("upload failed")
|
||||
@ -84,7 +84,7 @@ func Test_Params_File_CustomName(t *testing.T) {
|
||||
r.Response.WriteExit("upload file cannot be empty")
|
||||
}
|
||||
file.Filename = "my.txt"
|
||||
if name, err := file.Save(dstDirPath, r.GetBool("randomlyRename")); err == nil {
|
||||
if name, err := file.Save(dstDirPath, r.Get("randomlyRename").Bool()); err == nil {
|
||||
r.Response.WriteExit(name)
|
||||
}
|
||||
r.Response.WriteExit("upload failed")
|
||||
@ -120,7 +120,7 @@ func Test_Params_File_Batch(t *testing.T) {
|
||||
if files == nil {
|
||||
r.Response.WriteExit("upload file cannot be empty")
|
||||
}
|
||||
if names, err := files.Save(dstDirPath, r.GetBool("randomlyRename")); err == nil {
|
||||
if names, err := files.Save(dstDirPath, r.Get("randomlyRename").Bool()); err == nil {
|
||||
r.Response.WriteExit(gstr.Join(names, ","))
|
||||
}
|
||||
r.Response.WriteExit("upload failed")
|
||||
|
||||
@ -38,22 +38,22 @@ func Test_Params_Basic(t *testing.T) {
|
||||
r.Response.Write(r.GetQuery("slice"))
|
||||
}
|
||||
if r.GetQuery("bool") != nil {
|
||||
r.Response.Write(r.GetQueryBool("bool"))
|
||||
r.Response.Write(r.GetQuery("bool").Bool())
|
||||
}
|
||||
if r.GetQuery("float32") != nil {
|
||||
r.Response.Write(r.GetQueryFloat32("float32"))
|
||||
r.Response.Write(r.GetQuery("float32").Float32())
|
||||
}
|
||||
if r.GetQuery("float64") != nil {
|
||||
r.Response.Write(r.GetQueryFloat64("float64"))
|
||||
r.Response.Write(r.GetQuery("float64").Float64())
|
||||
}
|
||||
if r.GetQuery("int") != nil {
|
||||
r.Response.Write(r.GetQueryInt("int"))
|
||||
r.Response.Write(r.GetQuery("int").Int())
|
||||
}
|
||||
if r.GetQuery("uint") != nil {
|
||||
r.Response.Write(r.GetQueryUint("uint"))
|
||||
r.Response.Write(r.GetQuery("uint").Uint())
|
||||
}
|
||||
if r.GetQuery("string") != nil {
|
||||
r.Response.Write(r.GetQueryString("string"))
|
||||
r.Response.Write(r.GetQuery("string").String())
|
||||
}
|
||||
if r.GetQuery("map") != nil {
|
||||
r.Response.Write(r.GetQueryMap()["map"].(map[string]interface{})["b"])
|
||||
@ -71,22 +71,22 @@ func Test_Params_Basic(t *testing.T) {
|
||||
r.Response.Write(r.Get("slice"))
|
||||
}
|
||||
if r.Get("bool") != nil {
|
||||
r.Response.Write(r.GetBool("bool"))
|
||||
r.Response.Write(r.Get("bool").Bool())
|
||||
}
|
||||
if r.Get("float32") != nil {
|
||||
r.Response.Write(r.GetFloat32("float32"))
|
||||
r.Response.Write(r.Get("float32").Float32())
|
||||
}
|
||||
if r.Get("float64") != nil {
|
||||
r.Response.Write(r.GetFloat64("float64"))
|
||||
r.Response.Write(r.Get("float64").Float64())
|
||||
}
|
||||
if r.Get("int") != nil {
|
||||
r.Response.Write(r.GetInt("int"))
|
||||
r.Response.Write(r.Get("int").Int())
|
||||
}
|
||||
if r.Get("uint") != nil {
|
||||
r.Response.Write(r.GetUint("uint"))
|
||||
r.Response.Write(r.Get("uint").Uint())
|
||||
}
|
||||
if r.Get("string") != nil {
|
||||
r.Response.Write(r.GetString("string"))
|
||||
r.Response.Write(r.Get("string").String())
|
||||
}
|
||||
if r.Get("map") != nil {
|
||||
r.Response.Write(r.GetMap()["map"].(map[string]interface{})["b"])
|
||||
@ -105,22 +105,22 @@ func Test_Params_Basic(t *testing.T) {
|
||||
r.Response.Write(r.Get("slice"))
|
||||
}
|
||||
if r.Get("bool") != nil {
|
||||
r.Response.Write(r.GetBool("bool"))
|
||||
r.Response.Write(r.Get("bool").Bool())
|
||||
}
|
||||
if r.Get("float32") != nil {
|
||||
r.Response.Write(r.GetFloat32("float32"))
|
||||
r.Response.Write(r.Get("float32").Float32())
|
||||
}
|
||||
if r.Get("float64") != nil {
|
||||
r.Response.Write(r.GetFloat64("float64"))
|
||||
r.Response.Write(r.Get("float64").Float64())
|
||||
}
|
||||
if r.Get("int") != nil {
|
||||
r.Response.Write(r.GetInt("int"))
|
||||
r.Response.Write(r.Get("int").Int())
|
||||
}
|
||||
if r.Get("uint") != nil {
|
||||
r.Response.Write(r.GetUint("uint"))
|
||||
r.Response.Write(r.Get("uint").Uint())
|
||||
}
|
||||
if r.Get("string") != nil {
|
||||
r.Response.Write(r.GetString("string"))
|
||||
r.Response.Write(r.Get("string").String())
|
||||
}
|
||||
if r.Get("map") != nil {
|
||||
r.Response.Write(r.GetMap()["map"].(map[string]interface{})["b"])
|
||||
@ -138,22 +138,22 @@ func Test_Params_Basic(t *testing.T) {
|
||||
r.Response.Write(r.Get("slice"))
|
||||
}
|
||||
if r.Get("bool") != nil {
|
||||
r.Response.Write(r.GetBool("bool"))
|
||||
r.Response.Write(r.Get("bool").Bool())
|
||||
}
|
||||
if r.Get("float32") != nil {
|
||||
r.Response.Write(r.GetFloat32("float32"))
|
||||
r.Response.Write(r.Get("float32").Float32())
|
||||
}
|
||||
if r.Get("float64") != nil {
|
||||
r.Response.Write(r.GetFloat64("float64"))
|
||||
r.Response.Write(r.Get("float64").Float64())
|
||||
}
|
||||
if r.Get("int") != nil {
|
||||
r.Response.Write(r.GetInt("int"))
|
||||
r.Response.Write(r.Get("int").Int())
|
||||
}
|
||||
if r.Get("uint") != nil {
|
||||
r.Response.Write(r.GetUint("uint"))
|
||||
r.Response.Write(r.Get("uint").Uint())
|
||||
}
|
||||
if r.Get("string") != nil {
|
||||
r.Response.Write(r.GetString("string"))
|
||||
r.Response.Write(r.Get("string").String())
|
||||
}
|
||||
if r.Get("map") != nil {
|
||||
r.Response.Write(r.GetMap()["map"].(map[string]interface{})["b"])
|
||||
@ -171,22 +171,22 @@ func Test_Params_Basic(t *testing.T) {
|
||||
r.Response.Write(r.GetForm("slice"))
|
||||
}
|
||||
if r.Get("bool") != nil {
|
||||
r.Response.Write(r.GetFormBool("bool"))
|
||||
r.Response.Write(r.GetForm("bool").Bool())
|
||||
}
|
||||
if r.Get("float32") != nil {
|
||||
r.Response.Write(r.GetFormFloat32("float32"))
|
||||
r.Response.Write(r.GetForm("float32").Float32())
|
||||
}
|
||||
if r.Get("float64") != nil {
|
||||
r.Response.Write(r.GetFormFloat64("float64"))
|
||||
r.Response.Write(r.GetForm("float64").Float64())
|
||||
}
|
||||
if r.Get("int") != nil {
|
||||
r.Response.Write(r.GetFormInt("int"))
|
||||
r.Response.Write(r.GetForm("int").Int())
|
||||
}
|
||||
if r.Get("uint") != nil {
|
||||
r.Response.Write(r.GetFormUint("uint"))
|
||||
r.Response.Write(r.GetForm("uint").Uint())
|
||||
}
|
||||
if r.Get("string") != nil {
|
||||
r.Response.Write(r.GetFormString("string"))
|
||||
r.Response.Write(r.GetForm("string").String())
|
||||
}
|
||||
if r.Get("map") != nil {
|
||||
r.Response.Write(r.GetFormMap()["map"].(map[string]interface{})["b"])
|
||||
@ -206,7 +206,7 @@ func Test_Params_Basic(t *testing.T) {
|
||||
}
|
||||
})
|
||||
s.BindHandler("/raw", func(r *ghttp.Request) {
|
||||
r.Response.Write(r.GetRaw())
|
||||
r.Response.Write(r.GetBody())
|
||||
})
|
||||
s.BindHandler("/json", func(r *ghttp.Request) {
|
||||
j, err := r.GetJson()
|
||||
|
||||
@ -77,10 +77,10 @@ func Test_Router_Value(t *testing.T) {
|
||||
p, _ := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.BindHandler("/{hash}", func(r *ghttp.Request) {
|
||||
r.Response.Write(r.GetRouterString("hash"))
|
||||
r.Response.Write(r.GetRouter("hash").String())
|
||||
})
|
||||
s.BindHandler("/{hash}.{type}", func(r *ghttp.Request) {
|
||||
r.Response.Write(r.GetRouterString("type"))
|
||||
r.Response.Write(r.GetRouter("type").String())
|
||||
})
|
||||
s.BindHandler("/{hash}.{type}.map", func(r *ghttp.Request) {
|
||||
r.Response.Write(r.GetRouterMap()["type"])
|
||||
|
||||
@ -25,7 +25,7 @@ func (o *NamesObject) ShowName(r *ghttp.Request) {
|
||||
func Test_NameToUri_FullName(t *testing.T) {
|
||||
p, _ := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.SetNameToUriType(ghttp.URI_TYPE_FULLNAME)
|
||||
s.SetNameToUriType(ghttp.UriTypeFullName)
|
||||
s.BindObject("/{.struct}/{.method}", new(NamesObject))
|
||||
s.SetPort(p)
|
||||
s.SetDumpRouterMap(false)
|
||||
@ -46,7 +46,7 @@ func Test_NameToUri_FullName(t *testing.T) {
|
||||
func Test_NameToUri_AllLower(t *testing.T) {
|
||||
p, _ := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.SetNameToUriType(ghttp.URI_TYPE_ALLLOWER)
|
||||
s.SetNameToUriType(ghttp.UriTypeAllLower)
|
||||
s.BindObject("/{.struct}/{.method}", new(NamesObject))
|
||||
s.SetPort(p)
|
||||
s.SetDumpRouterMap(false)
|
||||
@ -67,7 +67,7 @@ func Test_NameToUri_AllLower(t *testing.T) {
|
||||
func Test_NameToUri_Camel(t *testing.T) {
|
||||
p, _ := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.SetNameToUriType(ghttp.URI_TYPE_CAMEL)
|
||||
s.SetNameToUriType(ghttp.UriTypeCamel)
|
||||
s.BindObject("/{.struct}/{.method}", new(NamesObject))
|
||||
s.SetPort(p)
|
||||
s.SetDumpRouterMap(false)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user