Merge branch 'v2_release' into develop

This commit is contained in:
John Guo
2021-09-27 22:52:28 +08:00
165 changed files with 2310 additions and 4292 deletions

View File

@ -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...)
}

View File

@ -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:

View File

@ -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)
}
}

View File

@ -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
}

View File

@ -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:

View File

@ -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`.
//

View File

@ -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.

View File

@ -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 {

View File

@ -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.

View File

@ -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{}.

View File

@ -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.

View File

@ -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)
}

View File

@ -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())

View File

@ -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)
})

View File

@ -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}
}

View 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)
}

View 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
}
}

View 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
}

View File

@ -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()
}

View File

@ -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
}

View File

@ -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

View 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
}

View 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)
}

View 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)
}

View File

@ -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)),
))

View 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)
}

View File

@ -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)
}

View 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)
})
}

View File

@ -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")
})
}

View File

@ -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

View File

@ -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.

View File

@ -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) {

View File

@ -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)

View File

@ -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:

View File

@ -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"))

View File

@ -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]

View File

@ -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)
})
}

View File

@ -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)
})
}

View File

@ -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",

View File

@ -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)
}

View File

@ -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})
})
}

View File

@ -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)

View File

@ -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

View File

@ -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()
}

View File

@ -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...)
}

View File

@ -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)
})
}

View File

@ -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)
})
}

View File

@ -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)
})
}

View File

@ -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)
}
}

View File

@ -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()
}

View File

@ -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...)

View File

@ -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)
}

View File

@ -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))
}

View File

@ -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) {

View File

@ -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"))
})

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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()
}

View File

@ -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
)

View File

@ -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
View File

@ -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
View File

@ -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=

View File

@ -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 {

View File

@ -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())
}

View File

@ -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{} {

View File

@ -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

View File

@ -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)
}

View File

@ -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...))
}

View File

@ -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.

View File

@ -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])

View File

@ -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()
}

View File

@ -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(),

View File

@ -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")

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}
}

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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.

View File

@ -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)
}
}

View File

@ -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
}

View File

@ -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,
)

View File

@ -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()

View File

@ -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)
}

View File

@ -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
}
}

View File

@ -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,
)

View File

@ -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

View File

@ -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{

View File

@ -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{

View File

@ -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)
}
}

View File

@ -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)
}

View File

@ -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)
})
}

View File

@ -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)

View File

@ -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 {

View File

@ -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")

View File

@ -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()

View File

@ -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"])

View File

@ -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