diff --git a/.example/database/gdb/driver/driver/driver.go b/.example/database/gdb/driver/driver/driver.go
index 97948b80c..71af8399d 100644
--- a/.example/database/gdb/driver/driver/driver.go
+++ b/.example/database/gdb/driver/driver/driver.go
@@ -1,12 +1,7 @@
-// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
-//
-// This Source Code Form is subject to the terms of the MIT License.
-// If a copy of the MIT was not distributed with this file,
-// You can obtain one at https://github.com/gogf/gf.
-
package driver
import (
+ "context"
"database/sql"
"github.com/gogf/gf/database/gdb"
"github.com/gogf/gf/os/gtime"
@@ -47,9 +42,9 @@ func (d *MyDriver) New(core *gdb.Core, node *gdb.ConfigNode) (gdb.DB, error) {
// DoQuery commits the sql string and its arguments to underlying driver
// through given link object and returns the execution result.
-func (d *MyDriver) DoQuery(link gdb.Link, sql string, args ...interface{}) (rows *sql.Rows, err error) {
+func (d *MyDriver) DoQuery(ctx context.Context, link gdb.Link, sql string, args ...interface{}) (rows *sql.Rows, err error) {
tsMilli := gtime.TimestampMilli()
- rows, err = d.DriverMysql.DoQuery(link, sql, args...)
+ rows, err = d.DriverMysql.DoQuery(ctx, link, sql, args...)
link.Exec(
"INSERT INTO `monitor`(`sql`,`cost`,`time`,`error`) VALUES(?,?,?,?)",
gdb.FormatSqlWithArgs(sql, args),
@@ -62,9 +57,9 @@ func (d *MyDriver) DoQuery(link gdb.Link, sql string, args ...interface{}) (rows
// DoExec commits the query string and its arguments to underlying driver
// through given link object and returns the execution result.
-func (d *MyDriver) DoExec(link gdb.Link, sql string, args ...interface{}) (result sql.Result, err error) {
+func (d *MyDriver) DoExec(ctx context.Context, link gdb.Link, sql string, args ...interface{}) (result sql.Result, err error) {
tsMilli := gtime.TimestampMilli()
- result, err = d.DriverMysql.DoExec(link, sql, args...)
+ result, err = d.DriverMysql.DoExec(ctx, link, sql, args...)
link.Exec(
"INSERT INTO `monitor`(`sql`,`cost`,`time`,`error`) VALUES(?,?,?,?)",
gdb.FormatSqlWithArgs(sql, args),
diff --git a/.example/database/gdb/mysql/config.toml b/.example/database/gdb/mysql/config.toml
index 48a479b62..beea9dcb5 100644
--- a/.example/database/gdb/mysql/config.toml
+++ b/.example/database/gdb/mysql/config.toml
@@ -1,9 +1,13 @@
# MySQL.
[database]
- debug = true
- link = "mysql:root:12345678@tcp(127.0.0.1:3306)/test?parseTime=true"
- MaxOpen = 100
+ [database.logger]
+ Level = "all"
+ Stdout = true
+ CtxKeys = ["Trace-Id"]
+ [database.default]
+ link = "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
+ debug = true
# Redis.
[redis]
diff --git a/.example/database/gdb/mysql/gdb_batch_insert.go b/.example/database/gdb/mysql/gdb_batch_insert.go
new file mode 100644
index 000000000..171bb9fb4
--- /dev/null
+++ b/.example/database/gdb/mysql/gdb_batch_insert.go
@@ -0,0 +1,24 @@
+package main
+
+import (
+ "fmt"
+ "github.com/gogf/gf/frame/g"
+)
+
+func main() {
+ db := g.DB()
+ db.SetDebug(true)
+ list := make(g.List, 0)
+ for i := 0; i < 100; i++ {
+ list = append(list, g.Map{
+ "name": fmt.Sprintf(`name_%d`, i),
+ })
+ }
+ r, e := db.Table("user").Data(list).Batch(2).Insert()
+ if e != nil {
+ panic(e)
+ }
+ if r != nil {
+ fmt.Println(r.LastInsertId())
+ }
+}
diff --git a/.example/database/gdb/mysql/gdb_ctx.go b/.example/database/gdb/mysql/gdb_ctx.go
new file mode 100644
index 000000000..c296b59ba
--- /dev/null
+++ b/.example/database/gdb/mysql/gdb_ctx.go
@@ -0,0 +1,14 @@
+package main
+
+import (
+ "context"
+ "github.com/gogf/gf/frame/g"
+)
+
+func main() {
+ ctx := context.WithValue(context.Background(), "Trace-Id", "123456789")
+ _, err := g.DB().Ctx(ctx).Query("SELECT 1")
+ if err != nil {
+ panic(err)
+ }
+}
diff --git a/.example/database/gdb/mysql/gdb_ctx_model.go b/.example/database/gdb/mysql/gdb_ctx_model.go
new file mode 100644
index 000000000..ba7b83c02
--- /dev/null
+++ b/.example/database/gdb/mysql/gdb_ctx_model.go
@@ -0,0 +1,14 @@
+package main
+
+import (
+ "context"
+ "github.com/gogf/gf/frame/g"
+)
+
+func main() {
+ ctx := context.WithValue(context.Background(), "Trace-Id", "123456789")
+ _, err := g.DB().Model("user").Ctx(ctx).All()
+ if err != nil {
+ panic(err)
+ }
+}
diff --git a/.example/database/gdb/mysql/gdb_distinct.go b/.example/database/gdb/mysql/gdb_distinct.go
new file mode 100644
index 000000000..189422f6b
--- /dev/null
+++ b/.example/database/gdb/mysql/gdb_distinct.go
@@ -0,0 +1,9 @@
+package main
+
+import (
+ "github.com/gogf/gf/frame/g"
+)
+
+func main() {
+ g.DB().Model("user").Distinct().CountColumn("uid,name")
+}
diff --git a/.example/database/gdb/mysql/gdb_insert.go b/.example/database/gdb/mysql/gdb_insert.go
index ee345b370..a6afa8491 100644
--- a/.example/database/gdb/mysql/gdb_insert.go
+++ b/.example/database/gdb/mysql/gdb_insert.go
@@ -10,9 +10,9 @@ func main() {
//db := g.DB()
gdb.AddDefaultConfigNode(gdb.ConfigNode{
- LinkInfo: "root:12345678@tcp(127.0.0.1:3306)/test?parseTime=true&loc=Local",
- Type: "mysql",
- Charset: "utf8",
+ Link: "root:12345678@tcp(127.0.0.1:3306)/test?parseTime=true&loc=Local",
+ Type: "mysql",
+ Charset: "utf8",
})
db, _ := gdb.New()
diff --git a/.example/database/gdb/mysql/gdb_transaction.go b/.example/database/gdb/mysql/gdb_transaction.go
new file mode 100644
index 000000000..fe5642ca2
--- /dev/null
+++ b/.example/database/gdb/mysql/gdb_transaction.go
@@ -0,0 +1,27 @@
+package main
+
+import (
+ "github.com/gogf/gf/frame/g"
+)
+
+func main() {
+ var (
+ db = g.DB()
+ table = "user"
+ )
+ tx, err := db.Begin()
+ if err != nil {
+ panic(err)
+ }
+ if err = tx.Begin(); err != nil {
+ panic(err)
+ }
+ _, err = tx.Model(table).Data(g.Map{"id": 1, "name": "john"}).Insert()
+ if err = tx.Rollback(); err != nil {
+ panic(err)
+ }
+ _, err = tx.Model(table).Data(g.Map{"id": 2, "name": "smith"}).Insert()
+ if err = tx.Commit(); err != nil {
+ panic(err)
+ }
+}
diff --git a/.example/database/gdb/mysql/gdb_transaction_closure.go b/.example/database/gdb/mysql/gdb_transaction_closure.go
new file mode 100644
index 000000000..aa05d48d4
--- /dev/null
+++ b/.example/database/gdb/mysql/gdb_transaction_closure.go
@@ -0,0 +1,34 @@
+package main
+
+import (
+ "github.com/gogf/gf/database/gdb"
+ "github.com/gogf/gf/frame/g"
+)
+
+func main() {
+ var (
+ err error
+ db = g.DB()
+ table = "user"
+ )
+ if err = db.Transaction(func(tx *gdb.TX) error {
+ // Nested transaction 1.
+ if err = tx.Transaction(func(tx *gdb.TX) error {
+ _, err = tx.Model(table).Data(g.Map{"id": 1, "name": "john"}).Insert()
+ return err
+ }); err != nil {
+ return err
+ }
+ // Nested transaction 2, panic.
+ if err = tx.Transaction(func(tx *gdb.TX) error {
+ _, err = tx.Model(table).Data(g.Map{"id": 2, "name": "smith"}).Insert()
+ // Create a panic that can make this transaction rollback automatically.
+ panic("error")
+ }); err != nil {
+ return err
+ }
+ return nil
+ }); err != nil {
+ panic(err)
+ }
+}
diff --git a/.example/database/gdb/mysql/gdb_transaction_savepoint.go b/.example/database/gdb/mysql/gdb_transaction_savepoint.go
new file mode 100644
index 000000000..e677f15ab
--- /dev/null
+++ b/.example/database/gdb/mysql/gdb_transaction_savepoint.go
@@ -0,0 +1,40 @@
+package main
+
+import (
+ "github.com/gogf/gf/frame/g"
+)
+
+func main() {
+ var (
+ err error
+ db = g.DB()
+ table = "user"
+ )
+ tx, err := db.Begin()
+ if err != nil {
+ panic(err)
+ }
+ defer func() {
+ if err := recover(); err != nil {
+ _ = tx.Rollback()
+ }
+ }()
+ if _, err = tx.Model(table).Data(g.Map{"id": 1, "name": "john"}).Insert(); err != nil {
+ panic(err)
+ }
+ if err = tx.SavePoint("MyPoint"); err != nil {
+ panic(err)
+ }
+ if _, err = tx.Model(table).Data(g.Map{"id": 2, "name": "smith"}).Insert(); err != nil {
+ panic(err)
+ }
+ if _, err = tx.Model(table).Data(g.Map{"id": 3, "name": "green"}).Insert(); err != nil {
+ panic(err)
+ }
+ if err = tx.RollbackTo("MyPoint"); err != nil {
+ panic(err)
+ }
+ if err = tx.Commit(); err != nil {
+ panic(err)
+ }
+}
diff --git a/.example/database/gdb/mysql/gdb_with_insert.go b/.example/database/gdb/mysql/gdb_with_insert.go
new file mode 100644
index 000000000..669ab3ce6
--- /dev/null
+++ b/.example/database/gdb/mysql/gdb_with_insert.go
@@ -0,0 +1,66 @@
+package main
+
+import (
+ "fmt"
+ "github.com/gogf/gf/database/gdb"
+ "github.com/gogf/gf/frame/g"
+ "github.com/gogf/gf/util/gmeta"
+)
+
+func main() {
+ type UserDetail struct {
+ gmeta.Meta `orm:"table:user_detail"`
+ Uid int `json:"uid"`
+ Address string `json:"address"`
+ }
+
+ type UserScore struct {
+ gmeta.Meta `orm:"table:user_score"`
+ Id int `json:"id"`
+ Uid int `json:"uid"`
+ Score int `json:"score"`
+ }
+
+ type User struct {
+ gmeta.Meta `orm:"table:user"`
+ Id int `json:"id"`
+ Name string `json:"name"`
+ UserDetail *UserDetail `orm:"with:uid=id"`
+ UserScores []*UserScore `orm:"with:uid=id"`
+ }
+
+ db := g.DB()
+ db.Transaction(func(tx *gdb.TX) error {
+ for i := 1; i <= 5; i++ {
+ // User.
+ user := User{
+ Name: fmt.Sprintf(`name_%d`, i),
+ }
+ lastInsertId, err := db.Model(user).Data(user).OmitEmpty().InsertAndGetId()
+ if err != nil {
+ return err
+ }
+ // Detail.
+ userDetail := UserDetail{
+ Uid: int(lastInsertId),
+ Address: fmt.Sprintf(`address_%d`, lastInsertId),
+ }
+ _, err = db.Model(userDetail).Data(userDetail).OmitEmpty().Insert()
+ if err != nil {
+ return err
+ }
+ // Scores.
+ for j := 1; j <= 5; j++ {
+ userScore := UserScore{
+ Uid: int(lastInsertId),
+ Score: j,
+ }
+ _, err = db.Model(userScore).Data(userScore).OmitEmpty().Insert()
+ if err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+ })
+}
diff --git a/.example/database/gdb/mysql/gdb_with_slect.go b/.example/database/gdb/mysql/gdb_with_slect.go
new file mode 100644
index 000000000..e15cf40f9
--- /dev/null
+++ b/.example/database/gdb/mysql/gdb_with_slect.go
@@ -0,0 +1,37 @@
+package main
+
+import (
+ "github.com/gogf/gf/frame/g"
+ "github.com/gogf/gf/util/gmeta"
+)
+
+func main() {
+ type UserDetail struct {
+ gmeta.Meta `orm:"table:user_detail"`
+ Uid int `json:"uid"`
+ Address string `json:"address"`
+ }
+
+ type UserScore struct {
+ gmeta.Meta `orm:"table:user_score"`
+ Id int `json:"id"`
+ Uid int `json:"uid"`
+ Score int `json:"score"`
+ }
+
+ type User struct {
+ gmeta.Meta `orm:"table:user"`
+ Id int `json:"id"`
+ Name string `json:"name"`
+ UserDetail *UserDetail `orm:"with:uid=id"`
+ UserScores []*UserScore `orm:"with:uid=id"`
+ }
+
+ db := g.DB()
+ var user *User
+ err := db.Model(user).WithAll().Where("id", 3).Scan(&user)
+ if err != nil {
+ panic(err)
+ }
+ g.Dump(user)
+}
diff --git a/.example/database/gredis/gredis.go b/.example/database/gredis/gredis.go
index 0ba2a4b2c..a276da6f9 100644
--- a/.example/database/gredis/gredis.go
+++ b/.example/database/gredis/gredis.go
@@ -9,10 +9,11 @@ import (
// 使用原生gredis.New操作redis,但是注意需要自己调用Close方法关闭redis链接池
func main() {
- redis := gredis.New(gredis.Config{
+ config := &gredis.Config{
Host: "127.0.0.1",
Port: 6379,
- })
+ }
+ redis := gredis.New(config)
defer redis.Close()
redis.Do("SET", "k", "v")
v, _ := redis.Do("GET", "k")
diff --git a/.example/i18n/gi18n/gi18n-dir.go b/.example/i18n/gi18n/gi18n-dir.go
index e9359c5ea..552298176 100644
--- a/.example/i18n/gi18n/gi18n-dir.go
+++ b/.example/i18n/gi18n/gi18n-dir.go
@@ -1,6 +1,7 @@
package main
import (
+ "context"
"fmt"
"github.com/gogf/gf/i18n/gi18n"
@@ -13,6 +14,6 @@ func main() {
if err != nil {
panic(err)
}
- fmt.Println(t.Translate(`hello`))
- fmt.Println(t.Translate(`{#hello}{#world}!`))
+ fmt.Println(t.Translate(context.TODO(), `hello`))
+ fmt.Println(t.Translate(context.TODO(), `{#hello}{#world}!`))
}
diff --git a/.example/i18n/gi18n/gi18n-file.go b/.example/i18n/gi18n/gi18n-file.go
index 1a6d337c3..f1a4423ee 100644
--- a/.example/i18n/gi18n/gi18n-file.go
+++ b/.example/i18n/gi18n/gi18n-file.go
@@ -1,6 +1,7 @@
package main
import (
+ "context"
"fmt"
"github.com/gogf/gf/i18n/gi18n"
@@ -13,6 +14,6 @@ func main() {
if err != nil {
panic(err)
}
- fmt.Println(t.Translate(`hello`))
- fmt.Println(t.Translate(`{#hello}{#world}!`))
+ fmt.Println(t.Translate(context.TODO(), `hello`))
+ fmt.Println(t.Translate(context.TODO(), `{#hello}{#world}!`))
}
diff --git a/.example/i18n/gi18n/gi18n.go b/.example/i18n/gi18n/gi18n.go
index 630d5a954..17d830c0d 100644
--- a/.example/i18n/gi18n/gi18n.go
+++ b/.example/i18n/gi18n/gi18n.go
@@ -1,8 +1,10 @@
package main
import (
+ "context"
"fmt"
"github.com/gogf/gf/frame/g"
+ "github.com/gogf/gf/i18n/gi18n"
)
func main() {
@@ -10,6 +12,12 @@ func main() {
orderId = 865271654
orderAmount = 99.8
)
- fmt.Println(g.I18n().Tfl(`en`, `{#OrderPaid}`, orderId, orderAmount))
- fmt.Println(g.I18n().Tfl(`zh-CN`, `{#OrderPaid}`, orderId, orderAmount))
+ fmt.Println(g.I18n().Tf(
+ gi18n.WithLanguage(context.TODO(), `en`),
+ `{#OrderPaid}`, orderId, orderAmount,
+ ))
+ fmt.Println(g.I18n().Tf(
+ gi18n.WithLanguage(context.TODO(), `zh-CN`),
+ `{#OrderPaid}`, orderId, orderAmount,
+ ))
}
diff --git a/.example/i18n/gi18n/http_view_i18n.go b/.example/i18n/gi18n/http_view_i18n.go
index ca5956c7b..cbf0b6e36 100644
--- a/.example/i18n/gi18n/http_view_i18n.go
+++ b/.example/i18n/gi18n/http_view_i18n.go
@@ -2,15 +2,19 @@ package main
import (
"github.com/gogf/gf/frame/g"
+ "github.com/gogf/gf/i18n/gi18n"
"github.com/gogf/gf/net/ghttp"
)
func main() {
- g.I18n().SetPath("/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/.example/i18n/gi18n/i18n")
s := g.Server()
- s.BindHandler("/", func(r *ghttp.Request) {
- r.Response.WriteTplContent(`{#hello}{#world}!`, g.Map{
- "I18nLanguage": r.Get("lang", "zh-CN"),
+ s.Group("/", func(group *ghttp.RouterGroup) {
+ group.Middleware(func(r *ghttp.Request) {
+ r.SetCtx(gi18n.WithLanguage(r.Context(), r.GetString("lang", "zh-CN")))
+ r.Middleware.Next()
+ })
+ group.ALL("/", func(r *ghttp.Request) {
+ r.Response.WriteTplContent(`{#hello}{#world}!`)
})
})
s.SetPort(8199)
diff --git a/.example/i18n/gi18n/i18n/zh-CN.toml b/.example/i18n/gi18n/i18n/zh-CN.toml
index 80acf06de..20406d93a 100644
--- a/.example/i18n/gi18n/i18n/zh-CN.toml
+++ b/.example/i18n/gi18n/i18n/zh-CN.toml
@@ -1 +1,3 @@
-OrderPaid = "您已成功完成订单号 #%d 支付,支付金额¥%.2f。"
\ No newline at end of file
+OrderPaid = "您已成功完成订单号 #%d 支付,支付金额¥%.2f。"
+hello = "你好"
+world = "世界"
\ No newline at end of file
diff --git a/.example/net/ghttp/client/middleware/client.go b/.example/net/ghttp/client/middleware/client.go
new file mode 100644
index 000000000..7ba07b4bf
--- /dev/null
+++ b/.example/net/ghttp/client/middleware/client.go
@@ -0,0 +1,64 @@
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "github.com/gogf/gf/container/garray"
+ "github.com/gogf/gf/crypto/gmd5"
+ "github.com/gogf/gf/frame/g"
+ "github.com/gogf/gf/internal/json"
+ "github.com/gogf/gf/net/ghttp"
+ "github.com/gogf/gf/os/gtime"
+ "github.com/gogf/gf/util/gconv"
+ "github.com/gogf/gf/util/guid"
+ "github.com/gogf/gf/util/gutil"
+ "io/ioutil"
+ "net/http"
+)
+
+const (
+ appId = "123"
+ appSecret = "456"
+)
+
+// 注入统一的接口签名参数
+func injectSignature(jsonContent []byte) []byte {
+ var m map[string]interface{}
+ _ = json.Unmarshal(jsonContent, &m)
+ if len(m) > 0 {
+ m["appid"] = appId
+ m["nonce"] = guid.S()
+ m["timestamp"] = gtime.Timestamp()
+ var (
+ keyArray = garray.NewSortedStrArrayFrom(gutil.Keys(m))
+ sigContent string
+ )
+ keyArray.Iterator(func(k int, v string) bool {
+ sigContent += v
+ sigContent += gconv.String(m[v])
+ return true
+ })
+ m["signature"] = gmd5.MustEncryptString(gmd5.MustEncryptString(sigContent) + appSecret)
+ jsonContent, _ = json.Marshal(m)
+ }
+ return jsonContent
+}
+
+func main() {
+ c := g.Client()
+ c.Use(func(c *ghttp.Client, r *http.Request) (resp *ghttp.ClientResponse, err error) {
+ bodyBytes, _ := ioutil.ReadAll(r.Body)
+ if len(bodyBytes) > 0 {
+ // 注入签名相关参数,修改Request原有的提交参数
+ bodyBytes = injectSignature(bodyBytes)
+ r.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
+ r.ContentLength = int64(len(bodyBytes))
+ }
+ return c.Next(r)
+ })
+ content := c.ContentJson().PostContent("http://127.0.0.1:8199/", g.Map{
+ "name": "goframe",
+ "site": "https://goframe.org",
+ })
+ fmt.Println(content)
+}
diff --git a/.example/net/ghttp/client/middleware/server.go b/.example/net/ghttp/client/middleware/server.go
new file mode 100644
index 000000000..8770dd634
--- /dev/null
+++ b/.example/net/ghttp/client/middleware/server.go
@@ -0,0 +1,17 @@
+package main
+
+import (
+ "github.com/gogf/gf/frame/g"
+ "github.com/gogf/gf/net/ghttp"
+)
+
+func main() {
+ s := g.Server()
+ s.Group("/", func(group *ghttp.RouterGroup) {
+ group.ALL("/", func(r *ghttp.Request) {
+ r.Response.Write(r.GetMap())
+ })
+ })
+ s.SetPort(8199)
+ s.Run()
+}
diff --git a/.example/net/ghttp/server/redirect/back.go b/.example/net/ghttp/server/redirect/redirect_back.go
similarity index 100%
rename from .example/net/ghttp/server/redirect/back.go
rename to .example/net/ghttp/server/redirect/redirect_back.go
diff --git a/.example/net/ghttp/server/redirect/redirect_to.go b/.example/net/ghttp/server/redirect/redirect_to.go
new file mode 100644
index 000000000..f7b8f859d
--- /dev/null
+++ b/.example/net/ghttp/server/redirect/redirect_to.go
@@ -0,0 +1,18 @@
+package main
+
+import (
+ "github.com/gogf/gf/frame/g"
+ "github.com/gogf/gf/net/ghttp"
+)
+
+func main() {
+ s := g.Server()
+ s.BindHandler("/", func(r *ghttp.Request) {
+ r.Response.RedirectTo("/login")
+ })
+ s.BindHandler("/login", func(r *ghttp.Request) {
+ r.Response.Writeln("Login First")
+ })
+ s.SetPort(8199)
+ s.Run()
+}
diff --git a/.example/net/ghttp/server/request/json-xml/test2.go b/.example/net/ghttp/server/request/json-xml/test2.go
index 5e3aed050..ced00e20d 100644
--- a/.example/net/ghttp/server/request/json-xml/test2.go
+++ b/.example/net/ghttp/server/request/json-xml/test2.go
@@ -25,7 +25,7 @@ func main() {
//fmt.Println(r.GetBody())
if err := r.Parse(&req); err != nil {
// Validation error.
- if v, ok := err.(*gvalid.Error); ok {
+ if v, ok := err.(gvalid.Error); ok {
r.Response.WriteJsonExit(RegisterRes{
Code: 1,
Error: v.FirstString(),
diff --git a/.example/net/ghttp/server/request/request_validation.go b/.example/net/ghttp/server/request/request_validation.go
index fa23190b2..2e180ad77 100644
--- a/.example/net/ghttp/server/request/request_validation.go
+++ b/.example/net/ghttp/server/request/request_validation.go
@@ -18,13 +18,13 @@ func main() {
s.Group("/", func(rgroup *ghttp.RouterGroup) {
rgroup.ALL("/user", func(r *ghttp.Request) {
user := new(User)
- if err := r.GetToStruct(user); err != nil {
+ if err := r.GetStruct(user); err != nil {
r.Response.WriteJsonExit(g.Map{
"message": err,
"errcode": 1,
})
}
- if err := gvalid.CheckStruct(user, nil); err != nil {
+ if err := gvalid.CheckStruct(r.Context(), user, nil); err != nil {
r.Response.WriteJsonExit(g.Map{
"message": err.Maps(),
"errcode": 1,
diff --git a/.example/net/ghttp/server/request/validation/validation1.go b/.example/net/ghttp/server/request/validation/validation1/validation1.go
similarity index 100%
rename from .example/net/ghttp/server/request/validation/validation1.go
rename to .example/net/ghttp/server/request/validation/validation1/validation1.go
diff --git a/.example/net/ghttp/server/request/validation/validation2.go b/.example/net/ghttp/server/request/validation/validation2/validation2.go
similarity index 96%
rename from .example/net/ghttp/server/request/validation/validation2.go
rename to .example/net/ghttp/server/request/validation/validation2/validation2.go
index ccee1e3f9..2800feab1 100644
--- a/.example/net/ghttp/server/request/validation/validation2.go
+++ b/.example/net/ghttp/server/request/validation/validation2/validation2.go
@@ -24,7 +24,7 @@ func main() {
var req *RegisterReq
if err := r.Parse(&req); err != nil {
// Validation error.
- if v, ok := err.(*gvalid.Error); ok {
+ if v, ok := err.(gvalid.Error); ok {
r.Response.WriteJsonExit(RegisterRes{
Code: 1,
Error: v.FirstString(),
diff --git a/.example/net/ghttp/server/router/duplicated/duplicated.go b/.example/net/ghttp/server/router/duplicated/duplicated.go
new file mode 100644
index 000000000..9402a2a4d
--- /dev/null
+++ b/.example/net/ghttp/server/router/duplicated/duplicated.go
@@ -0,0 +1,20 @@
+package main
+
+import (
+ "github.com/gogf/gf/frame/g"
+ "github.com/gogf/gf/net/ghttp"
+)
+
+func main() {
+ s := g.Server()
+ s.Group("/", func(group *ghttp.RouterGroup) {
+ group.ALL("/test", func(r *ghttp.Request) {
+ r.Response.Writeln(1)
+ })
+ group.ALL("/test", func(r *ghttp.Request) {
+ r.Response.Writeln(2)
+ })
+ })
+ s.SetPort(8199)
+ s.Run()
+}
diff --git a/.example/net/ghttp/server/servefile/servefile.go b/.example/net/ghttp/server/servefile/servefile.go
new file mode 100644
index 000000000..761cfbe03
--- /dev/null
+++ b/.example/net/ghttp/server/servefile/servefile.go
@@ -0,0 +1,15 @@
+package main
+
+import (
+ "github.com/gogf/gf/frame/g"
+ "github.com/gogf/gf/net/ghttp"
+)
+
+func main() {
+ s := g.Server()
+ s.BindHandler("/", func(r *ghttp.Request) {
+ r.Response.ServeFile("test.txt")
+ })
+ s.SetPort(8999)
+ s.Run()
+}
diff --git a/.example/net/ghttp/server/servefile/servefiledownload.go b/.example/net/ghttp/server/servefile/servefiledownload.go
new file mode 100644
index 000000000..a8e734b9b
--- /dev/null
+++ b/.example/net/ghttp/server/servefile/servefiledownload.go
@@ -0,0 +1,15 @@
+package main
+
+import (
+ "github.com/gogf/gf/frame/g"
+ "github.com/gogf/gf/net/ghttp"
+)
+
+func main() {
+ s := g.Server()
+ s.BindHandler("/", func(r *ghttp.Request) {
+ r.Response.ServeFileDownload("test.txt")
+ })
+ s.SetPort(8999)
+ s.Run()
+}
diff --git a/.example/net/ghttp/server/servefile/test.txt b/.example/net/ghttp/server/servefile/test.txt
new file mode 100644
index 000000000..30d74d258
--- /dev/null
+++ b/.example/net/ghttp/server/servefile/test.txt
@@ -0,0 +1 @@
+test
\ No newline at end of file
diff --git a/.example/net/ghttp/server/session/redis/redis_bigint.go b/.example/net/ghttp/server/session/redis/redis_bigint.go
new file mode 100644
index 000000000..b8a5b3460
--- /dev/null
+++ b/.example/net/ghttp/server/session/redis/redis_bigint.go
@@ -0,0 +1,36 @@
+package main
+
+import (
+ "github.com/gogf/gf/frame/g"
+ "github.com/gogf/gf/net/ghttp"
+ "github.com/gogf/gf/os/gsession"
+)
+
+func main() {
+ type User struct {
+ Id int64
+ Name string
+ }
+ s := g.Server()
+ s.SetSessionStorage(gsession.NewStorageRedis(g.Redis()))
+ s.Group("/", func(group *ghttp.RouterGroup) {
+ group.GET("/set", func(r *ghttp.Request) {
+ user := &User{
+ Id: 1265476890672672808,
+ Name: "john",
+ }
+ if err := r.Session.Set("user", user); err != nil {
+ panic(err)
+ }
+ r.Response.Write("ok")
+ })
+ group.GET("/get", func(r *ghttp.Request) {
+ r.Response.WriteJson(r.Session.Get("user"))
+ })
+ group.GET("/clear", func(r *ghttp.Request) {
+ r.Session.Clear()
+ })
+ })
+ s.SetPort(8199)
+ s.Run()
+}
diff --git a/.example/net/gsmtp/gsmtp_sendMail.go b/.example/net/gsmtp/gsmtp_sendMail.go
index 8496c43e9..f32cd7f38 100644
--- a/.example/net/gsmtp/gsmtp_sendMail.go
+++ b/.example/net/gsmtp/gsmtp_sendMail.go
@@ -1,4 +1,4 @@
-// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
+// 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,
diff --git a/.example/net/gtcp/gtcp_conn.go b/.example/net/gtcp/gtcp_conn.go
index a312c4ead..323595751 100644
--- a/.example/net/gtcp/gtcp_conn.go
+++ b/.example/net/gtcp/gtcp_conn.go
@@ -16,7 +16,7 @@ func main() {
}
defer conn.Close()
- if err := conn.Send([]byte("GET / HTTP/1.1\n\n")); err != nil {
+ if err := conn.Send([]byte("GET / HTTP/1.1\r\n\r\n")); err != nil {
panic(err)
}
@@ -30,13 +30,14 @@ func main() {
array := bytes.Split(data, []byte(": "))
// 获得页面内容长度
if contentLength == 0 && len(array) == 2 && bytes.EqualFold([]byte("Content-Length"), array[0]) {
- contentLength = gconv.Int(array[1])
+ // http 以\r\n换行,需要把\r也去掉
+ contentLength = gconv.Int(string(array[1][:len(array[1])-1]))
}
header = append(header, data...)
header = append(header, '\n')
}
- // header读取完毕,读取文本内容
- if contentLength > 0 && len(data) == 0 {
+ // header读取完毕,读取文本内容, 1为\r
+ if contentLength > 0 && len(data) == 1 {
content, _ = conn.Recv(contentLength)
break
}
diff --git a/.example/os/gcache/getorset_func_lock.go b/.example/os/gcache/getorset_func_lock.go
new file mode 100644
index 000000000..b5e3760bc
--- /dev/null
+++ b/.example/os/gcache/getorset_func_lock.go
@@ -0,0 +1,28 @@
+package main
+
+import (
+ "fmt"
+ "github.com/gogf/gf/os/gcache"
+ "github.com/gogf/gf/os/gctx"
+ "time"
+)
+
+func main() {
+ var (
+ ch = make(chan struct{}, 0)
+ ctx = gctx.New()
+ key = `key`
+ value = `value`
+ )
+ for i := 0; i < 10; i++ {
+ go func(index int) {
+ <-ch
+ _, _ = gcache.Ctx(ctx).GetOrSetFuncLock(key, func() (interface{}, error) {
+ fmt.Println(index, "entered")
+ return value, nil
+ }, 0)
+ }(i)
+ }
+ close(ch)
+ time.Sleep(time.Second)
+}
diff --git a/.example/os/gcache/note_interface_key.go b/.example/os/gcache/note_interface_key.go
new file mode 100644
index 000000000..4f5e1ee44
--- /dev/null
+++ b/.example/os/gcache/note_interface_key.go
@@ -0,0 +1,19 @@
+package main
+
+import (
+ "fmt"
+ "github.com/gogf/gf/os/gcache"
+ "github.com/gogf/gf/os/gctx"
+)
+
+func main() {
+ var (
+ ctx = gctx.New()
+ key1 int32 = 1
+ key2 float64 = 1
+ value = `value`
+ )
+ _ = gcache.Ctx(ctx).Set(key1, value, 0)
+ fmt.Println(gcache.Ctx(ctx).Get(key1))
+ fmt.Println(gcache.Ctx(ctx).Get(key2))
+}
diff --git a/.example/os/gcache/note_interface_value.go b/.example/os/gcache/note_interface_value.go
new file mode 100644
index 000000000..b102e86f0
--- /dev/null
+++ b/.example/os/gcache/note_interface_value.go
@@ -0,0 +1,29 @@
+package main
+
+import (
+ "fmt"
+ "github.com/gogf/gf/os/gcache"
+ "github.com/gogf/gf/os/gctx"
+)
+
+func main() {
+ type User struct {
+ Id int
+ Name string
+ Site string
+ }
+ var (
+ ctx = gctx.New()
+ user *User
+ key = `UserKey`
+ value = &User{
+ Id: 1,
+ Name: "GoFrame",
+ Site: "https://goframe.org",
+ }
+ )
+ _ = gcache.Ctx(ctx).Set(key, value, 0)
+ v, _ := gcache.Ctx(ctx).GetVar(key)
+ _ = v.Scan(&user)
+ fmt.Printf(`%#v`, user)
+}
diff --git a/.example/os/glog/glog_CtxKeys.go b/.example/os/glog/glog_CtxKeys.go
new file mode 100644
index 000000000..3eb6fcc13
--- /dev/null
+++ b/.example/os/glog/glog_CtxKeys.go
@@ -0,0 +1,14 @@
+package main
+
+import (
+ "context"
+ "github.com/gogf/gf/frame/g"
+)
+
+func main() {
+ g.Log().SetCtxKeys("TraceId", "SpanId", "Test")
+ ctx := context.WithValue(context.Background(), "TraceId", "1234567890")
+ ctx = context.WithValue(ctx, "SpanId", "abcdefg")
+
+ g.Log().Ctx(ctx).Print(1, 2, 3)
+}
diff --git a/.example/os/glog/glog_config1.go b/.example/os/glog/glog_SetConfigWithMap.go
similarity index 81%
rename from .example/os/glog/glog_config1.go
rename to .example/os/glog/glog_SetConfigWithMap.go
index fc3c5a3cb..06361b583 100644
--- a/.example/os/glog/glog_config1.go
+++ b/.example/os/glog/glog_SetConfigWithMap.go
@@ -6,7 +6,7 @@ import (
)
func main() {
- err := glog.SetConfigWithMap(g.Map{
+ err := g.Log().SetConfigWithMap(g.Map{
"prefix": "[TEST]",
})
if err != nil {
diff --git a/.example/os/glog/glog_async1.go b/.example/os/glog/glog_async_chaining.go
similarity index 60%
rename from .example/os/glog/glog_async1.go
rename to .example/os/glog/glog_async_chaining.go
index 1f17d1c25..a3dda3cd6 100644
--- a/.example/os/glog/glog_async1.go
+++ b/.example/os/glog/glog_async_chaining.go
@@ -1,14 +1,13 @@
package main
import (
+ "github.com/gogf/gf/frame/g"
"time"
-
- "github.com/gogf/gf/os/glog"
)
func main() {
for i := 0; i < 10; i++ {
- glog.Async().Print("async log", i)
+ g.Log().Async().Print("async log", i)
}
time.Sleep(time.Second)
}
diff --git a/.example/os/glog/glog_async2.go b/.example/os/glog/glog_async_configure.go
similarity index 54%
rename from .example/os/glog/glog_async2.go
rename to .example/os/glog/glog_async_configure.go
index 63d6f4278..e9cc86bd6 100644
--- a/.example/os/glog/glog_async2.go
+++ b/.example/os/glog/glog_async_configure.go
@@ -1,15 +1,14 @@
package main
import (
+ "github.com/gogf/gf/frame/g"
"time"
-
- "github.com/gogf/gf/os/glog"
)
func main() {
- glog.SetAsync(true)
+ g.Log().SetAsync(true)
for i := 0; i < 10; i++ {
- glog.Async().Print("async log", i)
+ g.Log().Print("async log", i)
}
time.Sleep(time.Second)
}
diff --git a/.example/os/glog/glog_category.go b/.example/os/glog/glog_category.go
index 47c56ccf4..2be6ee80b 100644
--- a/.example/os/glog/glog_category.go
+++ b/.example/os/glog/glog_category.go
@@ -3,13 +3,12 @@ package main
import (
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/os/gfile"
- "github.com/gogf/gf/os/glog"
)
func main() {
path := "/tmp/glog-cat"
- glog.SetPath(path)
- glog.Stdout(false).Cat("cat1").Cat("cat2").Println("test")
+ g.Log().SetPath(path)
+ g.Log().Stdout(false).Cat("cat1").Cat("cat2").Println("test")
list, err := gfile.ScanDir(path, "*", true)
g.Dump(err)
g.Dump(list)
diff --git a/.example/os/glog/glog_color.go b/.example/os/glog/glog_color.go
new file mode 100644
index 000000000..b178db5e0
--- /dev/null
+++ b/.example/os/glog/glog_color.go
@@ -0,0 +1,15 @@
+package main
+
+import (
+ "github.com/gogf/gf/frame/g"
+)
+
+func main() {
+ g.Log().Print("Print")
+ g.Log().Debug("Debug")
+ g.Log().Info("Info")
+ g.Log().Notice("Notice")
+ g.Log().Warning("Warning")
+ g.Log().Error("Error")
+ g.Log().Critical("Critical")
+}
diff --git a/.example/os/glog/glog_ctx.go b/.example/os/glog/glog_ctx.go
deleted file mode 100644
index b4ca21ea2..000000000
--- a/.example/os/glog/glog_ctx.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package main
-
-import (
- "context"
- "github.com/gogf/gf/os/glog"
-)
-
-func main() {
- glog.SetCtxKeys("Trace-Id", "Span-Id", "Test")
- ctx := context.WithValue(context.Background(), "Trace-Id", "1234567890")
- ctx = context.WithValue(ctx, "Span-Id", "abcdefg")
-
- glog.Ctx(ctx).Print(1, 2, 3)
-}
diff --git a/.example/os/glog/glog_debug.go b/.example/os/glog/glog_debug.go
index 64ec9c277..579aefe3b 100644
--- a/.example/os/glog/glog_debug.go
+++ b/.example/os/glog/glog_debug.go
@@ -1,19 +1,19 @@
package main
import (
+ "github.com/gogf/gf/frame/g"
"time"
- "github.com/gogf/gf/os/glog"
"github.com/gogf/gf/os/gtime"
"github.com/gogf/gf/os/gtimer"
)
func main() {
gtimer.SetTimeout(3*time.Second, func() {
- glog.SetDebug(false)
+ g.Log().SetDebug(false)
})
for {
- glog.Debug(gtime.Datetime())
+ g.Log().Debug(gtime.Datetime())
time.Sleep(time.Second)
}
}
diff --git a/.example/os/glog/glog_file.go b/.example/os/glog/glog_file.go
index 6a0843dac..9e4f6b858 100644
--- a/.example/os/glog/glog_file.go
+++ b/.example/os/glog/glog_file.go
@@ -3,24 +3,25 @@ package main
import (
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/os/gfile"
- "github.com/gogf/gf/os/glog"
)
// 设置日志等级
func main() {
- l := glog.New()
path := "/tmp/glog"
- l.SetPath(path)
- l.SetStdoutPrint(false)
+ g.Log().SetPath(path)
+ g.Log().SetStdoutPrint(false)
+
// 使用默认文件名称格式
- l.Println("标准文件名称格式,使用当前时间时期")
+ g.Log().Println("标准文件名称格式,使用当前时间时期")
+
// 通过SetFile设置文件名称格式
- l.SetFile("stdout.log")
- l.Println("设置日志输出文件名称格式为同一个文件")
+ g.Log().SetFile("stdout.log")
+ g.Log().Println("设置日志输出文件名称格式为同一个文件")
+
// 链式操作设置文件名称格式
- l.File("stderr.log").Println("支持链式操作")
- l.File("error-{Ymd}.log").Println("文件名称支持带gtime日期格式")
- l.File("access-{Ymd}.log").Println("文件名称支持带gtime日期格式")
+ g.Log().File("stderr.log").Println("支持链式操作")
+ g.Log().File("error-{Ymd}.log").Println("文件名称支持带gtime日期格式")
+ g.Log().File("access-{Ymd}.log").Println("文件名称支持带gtime日期格式")
list, err := gfile.ScanDir(path, "*")
g.Dump(err)
diff --git a/.example/os/glog/glog_flags.go b/.example/os/glog/glog_flags.go
index ebb3894c3..f3ed32ce3 100644
--- a/.example/os/glog/glog_flags.go
+++ b/.example/os/glog/glog_flags.go
@@ -1,15 +1,15 @@
package main
import (
+ "github.com/gogf/gf/frame/g"
"github.com/gogf/gf/os/glog"
)
func main() {
- l := glog.New()
- l.SetFlags(glog.F_TIME_TIME | glog.F_FILE_SHORT)
- l.Println("time and short line number")
- l.SetFlags(glog.F_TIME_MILLI | glog.F_FILE_LONG)
- l.Println("time with millisecond and long line number")
- l.SetFlags(glog.F_TIME_STD | glog.F_FILE_LONG)
- l.Println("standard time format and long line number")
+ g.Log().SetFlags(glog.F_TIME_TIME | glog.F_FILE_SHORT)
+ g.Log().Println("time and short line number")
+ g.Log().SetFlags(glog.F_TIME_MILLI | glog.F_FILE_LONG)
+ g.Log().Println("time with millisecond and long line number")
+ g.Log().SetFlags(glog.F_TIME_STD | glog.F_FILE_LONG)
+ g.Log().Println("standard time format and long line number")
}
diff --git a/.example/os/glog/glog_gerror.go b/.example/os/glog/glog_gerror.go
index cbcf405c0..6fb54f726 100644
--- a/.example/os/glog/glog_gerror.go
+++ b/.example/os/glog/glog_gerror.go
@@ -2,9 +2,9 @@ package main
import (
"errors"
+ "github.com/gogf/gf/frame/g"
"github.com/gogf/gf/errors/gerror"
- "github.com/gogf/gf/os/glog"
)
func MakeError() error {
@@ -18,8 +18,8 @@ func MakeGError() error {
func TestGError() {
err1 := MakeError()
err2 := MakeGError()
- glog.Error(err1)
- glog.Error(err2)
+ g.Log().Error(err1)
+ g.Log().Error(err2)
}
func main() {
diff --git a/.example/os/glog/glog_json.go b/.example/os/glog/glog_json.go
index f1e28944e..1075bf056 100644
--- a/.example/os/glog/glog_json.go
+++ b/.example/os/glog/glog_json.go
@@ -2,15 +2,14 @@ package main
import (
"github.com/gogf/gf/frame/g"
- "github.com/gogf/gf/os/glog"
)
func main() {
- glog.Debug(g.Map{"uid": 100, "name": "john"})
+ g.Log().Debug(g.Map{"uid": 100, "name": "john"})
type User struct {
Uid int `json:"uid"`
Name string `json:"name"`
}
- glog.Debug(User{100, "john"})
+ g.Log().Debug(User{100, "john"})
}
diff --git a/.example/os/glog/glog_level.go b/.example/os/glog/glog_level.go
index c1e07f736..e8c7b917b 100644
--- a/.example/os/glog/glog_level.go
+++ b/.example/os/glog/glog_level.go
@@ -1,13 +1,13 @@
package main
import (
+ "github.com/gogf/gf/frame/g"
"github.com/gogf/gf/os/glog"
)
// 设置日志等级,过滤掉Info日志信息
func main() {
- l := glog.New()
- l.Info("info1")
- l.SetLevel(glog.LEVEL_ALL ^ glog.LEVEL_INFO)
- l.Info("info2")
+ g.Log().Info("info1")
+ g.Log().SetLevel(glog.LEVEL_ALL ^ glog.LEVEL_INFO)
+ g.Log().Info("info2")
}
diff --git a/.example/os/glog/glog_level_prefix.go b/.example/os/glog/glog_level_prefix.go
index cd9a7e9f7..014c7c288 100644
--- a/.example/os/glog/glog_level_prefix.go
+++ b/.example/os/glog/glog_level_prefix.go
@@ -1,11 +1,11 @@
package main
import (
+ "github.com/gogf/gf/frame/g"
"github.com/gogf/gf/os/glog"
)
func main() {
- l := glog.New()
- l.SetLevelPrefix(glog.LEVEL_DEBU, "debug")
- l.Debug("test")
+ g.Log().SetLevelPrefix(glog.LEVEL_DEBU, "debug")
+ g.Log().Debug("test")
}
diff --git a/.example/os/glog/glog_line.go b/.example/os/glog/glog_line.go
index 4ee2ad1a1..5326cf867 100644
--- a/.example/os/glog/glog_line.go
+++ b/.example/os/glog/glog_line.go
@@ -1,10 +1,10 @@
package main
import (
- "github.com/gogf/gf/os/glog"
+ "github.com/gogf/gf/frame/g"
)
func main() {
- glog.Line().Debug("this is the short file name with its line number")
- glog.Line(true).Debug("lone file name with line number")
+ g.Log().Line().Debug("this is the short file name with its line number")
+ g.Log().Line(true).Debug("lone file name with line number")
}
diff --git a/.example/os/glog/glog_line2.go b/.example/os/glog/glog_line2.go
index b694f7b92..9fd8a60fc 100644
--- a/.example/os/glog/glog_line2.go
+++ b/.example/os/glog/glog_line2.go
@@ -1,12 +1,12 @@
package main
import (
- "github.com/gogf/gf/os/glog"
+ "github.com/gogf/gf/frame/g"
)
func PrintLog(content string) {
- glog.Skip(0).Line().Println("line number with skip:", content)
- glog.Line(true).Println("line number without skip:", content)
+ g.Log().Skip(0).Line().Println("line number with skip:", content)
+ g.Log().Line(true).Println("line number without skip:", content)
}
func main() {
diff --git a/.example/os/glog/glog_path.go b/.example/os/glog/glog_path.go
index 913a037ab..a7d0e4367 100644
--- a/.example/os/glog/glog_path.go
+++ b/.example/os/glog/glog_path.go
@@ -3,14 +3,13 @@ package main
import (
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/os/gfile"
- "github.com/gogf/gf/os/glog"
)
// 设置日志输出路径
func main() {
path := "/tmp/glog"
- glog.SetPath(path)
- glog.Println("日志内容")
+ g.Log().SetPath(path)
+ g.Log().Println("日志内容")
list, err := gfile.ScanDir(path, "*")
g.Dump(err)
g.Dump(list)
diff --git a/.example/os/glog/glog_pool.go b/.example/os/glog/glog_pool.go
index 383b74367..960e85557 100644
--- a/.example/os/glog/glog_pool.go
+++ b/.example/os/glog/glog_pool.go
@@ -1,18 +1,18 @@
package main
import (
+ "github.com/gogf/gf/frame/g"
"time"
- "github.com/gogf/gf/os/glog"
"github.com/gogf/gf/os/gtime"
)
// 测试删除日志文件是否会重建日志文件
func main() {
path := "/Users/john/Temp/test"
- glog.SetPath(path)
+ g.Log().SetPath(path)
for {
- glog.Println(gtime.Now().String())
+ g.Log().Println(gtime.Now().String())
time.Sleep(time.Second)
}
}
diff --git a/.example/os/glog/glog_prefix.go b/.example/os/glog/glog_prefix.go
index 502467128..b803b9a4e 100644
--- a/.example/os/glog/glog_prefix.go
+++ b/.example/os/glog/glog_prefix.go
@@ -1,12 +1,11 @@
package main
import (
- "github.com/gogf/gf/os/glog"
+ "github.com/gogf/gf/frame/g"
)
func main() {
- l := glog.New()
- l.SetPrefix("[API]")
- l.Println("hello world")
- l.Error("error occurred")
+ g.Log().SetPrefix("[API]")
+ g.Log().Println("hello world")
+ g.Log().Error("error occurred")
}
diff --git a/.example/os/glog/glog_stack.go b/.example/os/glog/glog_stack.go
index 1232c2bec..1dced6e69 100644
--- a/.example/os/glog/glog_stack.go
+++ b/.example/os/glog/glog_stack.go
@@ -2,15 +2,11 @@ package main
import (
"fmt"
-
- "github.com/gogf/gf/os/glog"
+ "github.com/gogf/gf/frame/g"
)
func main() {
+ g.Log().PrintStack()
- glog.PrintStack()
- glog.New().PrintStack()
-
- fmt.Println(glog.GetStack())
- fmt.Println(glog.New().GetStack())
+ fmt.Println(g.Log().GetStack())
}
diff --git a/.example/os/glog/glog_stdout.go b/.example/os/glog/glog_stdout.go
index 4d2200028..c4ae4d6ba 100644
--- a/.example/os/glog/glog_stdout.go
+++ b/.example/os/glog/glog_stdout.go
@@ -1,22 +1,23 @@
package main
import (
+ "github.com/gogf/gf/frame/g"
"sync"
-
- "github.com/gogf/gf/os/glog"
)
func main() {
- wg := sync.WaitGroup{}
- c := make(chan struct{})
+ var (
+ wg = sync.WaitGroup{}
+ ch = make(chan struct{})
+ )
wg.Add(3000)
for i := 0; i < 3000; i++ {
go func() {
- <-c
- glog.Println("abcdefghijklmnopqrstuvwxyz1234567890")
+ <-ch
+ g.Log().Println("abcdefghijklmnopqrstuvwxyz1234567890")
wg.Done()
}()
}
- close(c)
+ close(ch)
wg.Wait()
}
diff --git a/.example/os/glog/glog_writer_hook.go b/.example/os/glog/glog_writer_hook.go
index 67e8863ca..365ec28f0 100644
--- a/.example/os/glog/glog_writer_hook.go
+++ b/.example/os/glog/glog_writer_hook.go
@@ -2,8 +2,8 @@ package main
import (
"fmt"
+ "github.com/gogf/gf/frame/g"
- "github.com/gogf/gf/net/ghttp"
"github.com/gogf/gf/os/glog"
"github.com/gogf/gf/text/gregex"
)
@@ -16,7 +16,7 @@ func (w *MyWriter) Write(p []byte) (n int, err error) {
s := string(p)
if gregex.IsMatchString(`\[(PANI|FATA)\]`, s) {
fmt.Println("SERIOUS ISSUE OCCURRED!! I'd better tell monitor in first time!")
- ghttp.PostContent("http://monitor.mydomain.com", s)
+ g.Client().PostContent("http://monitor.mydomain.com", s)
}
return w.logger.Write(p)
}
diff --git a/.example/os/glog/handler/glog_handler_greylog.go b/.example/os/glog/handler/glog_handler_greylog.go
new file mode 100644
index 000000000..e690ac309
--- /dev/null
+++ b/.example/os/glog/handler/glog_handler_greylog.go
@@ -0,0 +1,31 @@
+package main
+
+//import (
+// "context"
+// "github.com/gogf/gf/frame/g"
+// "github.com/gogf/gf/os/glog"
+// "github.com/robertkowalski/graylog-golang"
+//)
+//
+//var greyLogClient = gelf.New(gelf.Config{
+// GraylogPort: 80,
+// GraylogHostname: "graylog-host.com",
+// Connection: "wan",
+// MaxChunkSizeWan: 42,
+// MaxChunkSizeLan: 1337,
+//})
+//
+//// LoggingGreyLogHandler is an example handler for logging content to remote GreyLog service.
+//var LoggingGreyLogHandler glog.Handler = func(ctx context.Context, in *glog.HandlerInput) {
+// in.Next()
+// greyLogClient.Log(in.Buffer.String())
+//}
+//
+//func main() {
+// g.Log().SetHandlers(LoggingGreyLogHandler)
+//
+// g.Log().Debug("Debugging...")
+// g.Log().Warning("It is warning info")
+// g.Log().Error("Error occurs, please have a check")
+// glog.Println("test log")
+//}
diff --git a/.example/os/glog/handler/glog_handler_json.go b/.example/os/glog/handler/glog_handler_json.go
new file mode 100644
index 000000000..49dc0750b
--- /dev/null
+++ b/.example/os/glog/handler/glog_handler_json.go
@@ -0,0 +1,42 @@
+package main
+
+import (
+ "context"
+ "github.com/gogf/gf/frame/g"
+ "github.com/gogf/gf/internal/json"
+ "github.com/gogf/gf/os/glog"
+ "github.com/gogf/gf/text/gstr"
+ "os"
+)
+
+// JsonOutputsForLogger is for JSON marshaling in sequence.
+type JsonOutputsForLogger struct {
+ Time string `json:"time"`
+ Level string `json:"level"`
+ Content string `json:"content"`
+}
+
+// LoggingJsonHandler is an example handler for logging JSON format content.
+var LoggingJsonHandler glog.Handler = func(ctx context.Context, in *glog.HandlerInput) {
+ jsonForLogger := JsonOutputsForLogger{
+ Time: in.TimeFormat,
+ Level: in.LevelFormat,
+ Content: gstr.Trim(in.String()),
+ }
+ jsonBytes, err := json.Marshal(jsonForLogger)
+ if err != nil {
+ _, _ = os.Stderr.WriteString(err.Error())
+ return
+ }
+ in.Buffer.Write(jsonBytes)
+ in.Buffer.WriteString("\n")
+ in.Next()
+}
+
+func main() {
+ g.Log().SetHandlers(LoggingJsonHandler)
+
+ g.Log().Debug("Debugging...")
+ g.Log().Warning("It is warning info")
+ g.Log().Error("Error occurs, please have a check")
+}
diff --git a/.example/os/gmlock/locker1.go b/.example/os/gmlock/1.lock&unlock.go
similarity index 86%
rename from .example/os/gmlock/locker1.go
rename to .example/os/gmlock/1.lock&unlock.go
index 946ae72b4..71a4d3534 100644
--- a/.example/os/gmlock/locker1.go
+++ b/.example/os/gmlock/1.lock&unlock.go
@@ -10,8 +10,10 @@ import (
// 内存锁基本使用
func main() {
- key := "lock"
- wg := sync.WaitGroup{}
+ var (
+ key = "lock"
+ wg = sync.WaitGroup{}
+ )
for i := 0; i < 10; i++ {
wg.Add(1)
go func(i int) {
diff --git a/.example/os/gmlock/locker3.go b/.example/os/gmlock/2.trylock.go
similarity index 100%
rename from .example/os/gmlock/locker3.go
rename to .example/os/gmlock/2.trylock.go
diff --git a/.example/os/gmlock/locker4.go b/.example/os/gmlock/3.lock_conflicts.go
similarity index 100%
rename from .example/os/gmlock/locker4.go
rename to .example/os/gmlock/3.lock_conflicts.go
diff --git a/.example/os/gmlock/test_locker.go b/.example/os/gmlock/4.test_deadlock.go
similarity index 91%
rename from .example/os/gmlock/test_locker.go
rename to .example/os/gmlock/4.test_deadlock.go
index 3600e36b6..b67cf7ddd 100644
--- a/.example/os/gmlock/test_locker.go
+++ b/.example/os/gmlock/4.test_deadlock.go
@@ -11,12 +11,13 @@ import (
// 测试Locker是否会产生死锁
func main() {
- l := gmlock.New()
- wg := sync.WaitGroup{}
- key := "test"
- event := make(chan int)
- number := 100000
-
+ var (
+ l = gmlock.New()
+ wg = sync.WaitGroup{}
+ key = "test"
+ event = make(chan int)
+ number = 100000
+ )
for i := 0; i < number; i++ {
wg.Add(1)
go func() {
diff --git a/.example/os/gmlock/locker2.go b/.example/os/gmlock/locker2.go
deleted file mode 100644
index f340a25c9..000000000
--- a/.example/os/gmlock/locker2.go
+++ /dev/null
@@ -1,23 +0,0 @@
-package main
-
-import (
- "sync"
-
- "github.com/gogf/gf/os/glog"
- "github.com/gogf/gf/os/gmlock"
-)
-
-// 内存锁 - 给定过期时间
-func main() {
- key := "lock"
- wg := sync.WaitGroup{}
- for i := 0; i < 10; i++ {
- wg.Add(1)
- go func(i int) {
- gmlock.Lock(key, 1000)
- glog.Println(i)
- wg.Done()
- }(i)
- }
- wg.Wait()
-}
diff --git a/.example/os/gmlock/test_mutex.go b/.example/os/gmlock/test_mutex.go
deleted file mode 100644
index c03874e70..000000000
--- a/.example/os/gmlock/test_mutex.go
+++ /dev/null
@@ -1,95 +0,0 @@
-package main
-
-import (
- "fmt"
- "math/rand"
- "sync"
- "time"
-
- "github.com/gogf/gf/os/gmlock"
-)
-
-// 测试是否会产生死锁
-func main() {
- mu := gmlock.NewMutex()
- wg := sync.WaitGroup{}
- event := make(chan int)
- number := 100000
-
- for i := 0; i < number; i++ {
- wg.Add(1)
- go func() {
- <-event
- mu.Lock()
- //fmt.Println("get lock")
- mu.Unlock()
- wg.Done()
- }()
- }
-
- for i := 0; i < number; i++ {
- wg.Add(1)
- go func() {
- <-event
- mu.RLock()
- //fmt.Println("get rlock")
- mu.RUnlock()
- wg.Done()
- }()
- }
-
- for i := 0; i < number; i++ {
- wg.Add(1)
- go func() {
- <-event
- if mu.TryLock() {
- //fmt.Println("get lock")
- mu.Unlock()
- }
- wg.Done()
- }()
- }
-
- for i := 0; i < number; i++ {
- wg.Add(1)
- go func() {
- <-event
- if mu.TryRLock() {
- //fmt.Println("get rlock")
- mu.RUnlock()
- }
- wg.Done()
- }()
- }
-
- for i := 0; i < number; i++ {
- wg.Add(1)
- go func() {
- <-event
- if mu.TryLock() {
- // 模拟业务逻辑的随机处理间隔
- time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)
- mu.Unlock()
- }
- wg.Done()
- }()
- }
-
- for i := 0; i < number; i++ {
- wg.Add(1)
- go func() {
- <-event
- if mu.TryRLock() {
- // 模拟业务逻辑的随机处理间隔
- time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)
- mu.RUnlock()
- }
- wg.Done()
- }()
- }
- // 使用chan作为事件发送测试指令,让所有的goroutine同时执行
- close(event)
- wg.Wait()
-
- fmt.Println("done!")
-}
diff --git a/.example/os/gproc/signal/signal_handler.go b/.example/os/gproc/signal/signal_handler.go
new file mode 100644
index 000000000..a1d495347
--- /dev/null
+++ b/.example/os/gproc/signal/signal_handler.go
@@ -0,0 +1,54 @@
+package main
+
+import (
+ "fmt"
+ "os"
+ "os/signal"
+ "syscall"
+ "time"
+)
+
+func signalHandlerForMQ() {
+ var (
+ sig os.Signal
+ receivedChan = make(chan os.Signal)
+ )
+ signal.Notify(
+ receivedChan,
+ syscall.SIGINT,
+ syscall.SIGQUIT,
+ syscall.SIGKILL,
+ syscall.SIGTERM,
+ syscall.SIGABRT,
+ )
+ for {
+ sig = <-receivedChan
+ fmt.Println("MQ is shutting down due to signal:", sig.String())
+ time.Sleep(time.Second)
+ fmt.Println("MQ is shut down smoothly")
+ return
+ }
+}
+
+func main() {
+ fmt.Println("Process start, pid:", os.Getpid())
+ go signalHandlerForMQ()
+
+ var (
+ sig os.Signal
+ receivedChan = make(chan os.Signal)
+ )
+ signal.Notify(
+ receivedChan,
+ syscall.SIGINT,
+ syscall.SIGQUIT,
+ syscall.SIGKILL,
+ syscall.SIGTERM,
+ syscall.SIGABRT,
+ )
+ for {
+ sig = <-receivedChan
+ fmt.Println("MainProcess is shutting down due to signal:", sig.String())
+ return
+ }
+}
diff --git a/.example/os/gproc/signal/signal_handler_gproc.go b/.example/os/gproc/signal/signal_handler_gproc.go
new file mode 100644
index 000000000..e8e473484
--- /dev/null
+++ b/.example/os/gproc/signal/signal_handler_gproc.go
@@ -0,0 +1,27 @@
+package main
+
+import (
+ "fmt"
+ "github.com/gogf/gf/os/gproc"
+ "os"
+ "time"
+)
+
+func signalHandlerForMQ(sig os.Signal) {
+ fmt.Println("MQ is shutting down due to signal:", sig.String())
+ time.Sleep(time.Second)
+ fmt.Println("MQ is shut down smoothly")
+}
+
+func signalHandlerForMain(sig os.Signal) {
+ fmt.Println("MainProcess is shutting down due to signal:", sig.String())
+}
+
+func main() {
+ fmt.Println("Process start, pid:", os.Getpid())
+ gproc.AddSigHandlerShutdown(
+ signalHandlerForMQ,
+ signalHandlerForMain,
+ )
+ gproc.Listen()
+}
diff --git a/.example/util/gvalid/config.toml b/.example/util/gvalid/config.toml
new file mode 100644
index 000000000..26beac3a7
--- /dev/null
+++ b/.example/util/gvalid/config.toml
@@ -0,0 +1,14 @@
+
+
+
+# MySQL.
+[database]
+ [database.default]
+ link = "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
+ debug = true
+
+
+
+
+
+
diff --git a/.example/util/gvalid/gvalid.go b/.example/util/gvalid/gvalid.go
index 9975bd443..4d6212876 100644
--- a/.example/util/gvalid/gvalid.go
+++ b/.example/util/gvalid/gvalid.go
@@ -1,31 +1,32 @@
package main
import (
+ "context"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/util/gvalid"
)
func main() {
//rule := "length:6,16"
- //if m := gvalid.Check("123456", rule, nil); m != nil {
+ //if m := gvalid.Check(context.TODO(), "123456", rule, nil); m != nil {
// fmt.Println(m)
//}
- //if m := gvalid.Check("12345", rule, nil); m != nil {
+ //if m := gvalid.Check(context.TODO(), "12345", rule, nil); m != nil {
// fmt.Println(m)
// // map[length:字段长度为6到16个字符]
//}
//rule := "integer|between:6,16"
//msgs := "请输入一个整数|参数大小不对啊老铁"
- //fmt.Println(gvalid.Check("5.66", rule, msgs))
+ //fmt.Println(gvalid.Check(context.TODO(), "5.66", rule, msgs))
//// map[integer:请输入一个整数 between:参数大小不对啊老铁]
//// 参数长度至少为6个数字或者6个字母,但是总长度不能超过16个字符
//rule := `regex:\d{6,}|\D{6,}|max-length:16`
- //if m := gvalid.Check("123456", rule, nil); m != nil {
+ //if m := gvalid.Check(context.TODO(), "123456", rule, nil); m != nil {
// fmt.Println(m)
//}
- //if m := gvalid.Check("abcde6", rule, nil); m != nil {
+ //if m := gvalid.Check(context.TODO(), "abcde6", rule, nil); m != nil {
// fmt.Println(m)
// // map[regex:字段值不合法]
//}
@@ -40,18 +41,20 @@ func main() {
// "password" : "required|length:6,16|same:password2",
// "password2" : "required|length:6,16",
//}
- //fmt.Println(gvalid.CheckMap(params, rules))
+ //fmt.Println(gvalid.CheckMap(context.TODO(), params, rules))
//// map[passport:map[length:字段长度为6到16个字符] password:map[same:字段值不合法]]
params := map[string]interface{}{
"passport": "john",
"password": "123456",
"password2": "1234567",
+ "name": "gf",
}
rules := map[string]string{
"passport": "required|length:6,16",
"password": "required|length:6,16|same:password2",
"password2": "required|length:6,16",
+ "name": "size:5",
}
msgs := map[string]interface{}{
"passport": "账号不能为空|账号长度应当在:min到:max之间",
@@ -59,8 +62,9 @@ func main() {
"required": "密码不能为空",
"same": "两次密码输入不相等",
},
+ "name": "名字长度必须为:size",
}
- if e := gvalid.CheckMap(params, rules, msgs); e != nil {
+ if e := gvalid.CheckMap(context.TODO(), params, rules, msgs); e != nil {
g.Dump(e.Maps())
}
// map[passport:map[length:账号长度应当在6到16之间] password:map[same:两次密码输入不相等]]
diff --git a/.example/util/gvalid/gvalid_checkstructwithdata.go b/.example/util/gvalid/gvalid_checkstructwithdata.go
new file mode 100644
index 000000000..7e1636f88
--- /dev/null
+++ b/.example/util/gvalid/gvalid_checkstructwithdata.go
@@ -0,0 +1,28 @@
+package main
+
+import (
+ "context"
+ "github.com/gogf/gf/frame/g"
+ "github.com/gogf/gf/util/gconv"
+ "github.com/gogf/gf/util/gvalid"
+)
+
+func main() {
+ type User struct {
+ Name string `v:"required#请输入用户姓名"`
+ Type int `v:"required#请选择用户类型"`
+ }
+ data := g.Map{
+ "name": "john",
+ }
+ user := User{}
+ if err := gconv.Scan(data, &user); err != nil {
+ panic(err)
+ }
+ err := gvalid.CheckStructWithData(context.TODO(), user, data, nil)
+ // 也可以使用
+ // err := g.Validator().Data(data).CheckStruct(user)
+ if err != nil {
+ g.Dump(err.Items())
+ }
+}
diff --git a/.example/util/gvalid/gvalid_custom_message.go b/.example/util/gvalid/gvalid_custom_message.go
index 816749f10..3c8798693 100644
--- a/.example/util/gvalid/gvalid_custom_message.go
+++ b/.example/util/gvalid/gvalid_custom_message.go
@@ -1,6 +1,7 @@
package main
import (
+ "context"
"fmt"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/util/gvalid"
@@ -8,6 +9,6 @@ import (
func main() {
g.I18n().SetLanguage("cn")
- err := gvalid.Check("", "required", nil)
+ err := gvalid.Check(context.TODO(), "", "required", nil)
fmt.Println(err.String())
}
diff --git a/.example/util/gvalid/gvalid_error.go b/.example/util/gvalid/gvalid_error.go
index fe5c0a2f2..1f5d350d4 100644
--- a/.example/util/gvalid/gvalid_error.go
+++ b/.example/util/gvalid/gvalid_error.go
@@ -1,6 +1,7 @@
package main
import (
+ "context"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/util/gvalid"
)
@@ -17,7 +18,7 @@ func main() {
ConfiemPassword: "",
}
- e := gvalid.CheckStruct(user, nil)
+ e := gvalid.CheckStruct(context.TODO(), user, nil)
g.Dump(e.Map())
g.Dump(e.Maps())
g.Dump(e.String())
diff --git a/.example/util/gvalid/gvalid_i18n.go b/.example/util/gvalid/gvalid_i18n.go
new file mode 100644
index 000000000..cb2a5e905
--- /dev/null
+++ b/.example/util/gvalid/gvalid_i18n.go
@@ -0,0 +1,38 @@
+package main
+
+import (
+ "context"
+
+ "github.com/gogf/gf/frame/g"
+ "github.com/gogf/gf/i18n/gi18n"
+ "github.com/gogf/gf/util/gconv"
+)
+
+func main() {
+ type User struct {
+ Name string `v:"required#ReuiredUserName"`
+ Type int `v:"required#ReuiredUserType"`
+ Project string `v:"size:10#MustSize"`
+ }
+ var (
+ data = g.Map{
+ "name": "john",
+ "project": "gf",
+ }
+ user = User{}
+ ctxEn = gi18n.WithLanguage(context.TODO(), "en")
+ ctxCh = gi18n.WithLanguage(context.TODO(), "zh-CN")
+ )
+
+ if err := gconv.Scan(data, &user); err != nil {
+ panic(err)
+ }
+ // 英文
+ if err := g.Validator().Ctx(ctxEn).Data(data).CheckStruct(user); err != nil {
+ g.Dump(err.String())
+ }
+ // 中文
+ if err := g.Validator().Ctx(ctxCh).Data(data).CheckStruct(user); err != nil {
+ g.Dump(err.String())
+ }
+}
diff --git a/.example/util/gvalid/gvalid_i18n_http.go b/.example/util/gvalid/gvalid_i18n_http.go
new file mode 100644
index 000000000..cba5062fc
--- /dev/null
+++ b/.example/util/gvalid/gvalid_i18n_http.go
@@ -0,0 +1,35 @@
+package main
+
+import (
+ "github.com/gogf/gf/net/ghttp"
+
+ "github.com/gogf/gf/frame/g"
+ "github.com/gogf/gf/i18n/gi18n"
+)
+
+func main() {
+ type User struct {
+ Name string `v:"required#ReuiredUserName"`
+ Type int `v:"required#ReuiredUserType"`
+ Project string `v:"size:10#MustSize"`
+ }
+ s := g.Server()
+ s.Group("/", func(group *ghttp.RouterGroup) {
+ group.Middleware(func(r *ghttp.Request) {
+ lang := r.GetString("lang", "zh-CN")
+ r.SetCtx(gi18n.WithLanguage(r.Context(), lang))
+ r.Middleware.Next()
+ })
+ group.GET("/validate", func(r *ghttp.Request) {
+ var (
+ err error
+ user = User{}
+ )
+ if err = r.Parse(&user); err != nil {
+ r.Response.WriteExit(err)
+ }
+ r.Response.WriteExit(user)
+ })
+ })
+ s.SetPort(8199)
+}
diff --git a/.example/util/gvalid/gvalid_result.go b/.example/util/gvalid/gvalid_result.go
index 0190f0df4..ff9e01e6d 100644
--- a/.example/util/gvalid/gvalid_result.go
+++ b/.example/util/gvalid/gvalid_result.go
@@ -1,6 +1,7 @@
package main
import (
+ "context"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/util/gvalid"
)
@@ -18,7 +19,7 @@ func main() {
Pass2: "123",
}
- e := gvalid.CheckStruct(user, nil)
+ e := gvalid.CheckStruct(context.TODO(), user, nil)
g.Dump(e.String())
g.Dump(e.FirstString())
}
diff --git a/.example/util/gvalid/gvalid_sequence.go b/.example/util/gvalid/gvalid_sequence.go
index 8274cd1c9..0296a4ab5 100644
--- a/.example/util/gvalid/gvalid_sequence.go
+++ b/.example/util/gvalid/gvalid_sequence.go
@@ -1,6 +1,7 @@
package main
import (
+ "context"
"fmt"
"github.com/gogf/gf/util/gvalid"
@@ -17,7 +18,7 @@ func main() {
"password@required|length:6,16|same:password2#密码不能为空}|两次密码输入不相等",
"password2@required|length:6,16#",
}
- if e := gvalid.CheckMap(params, rules); e != nil {
+ if e := gvalid.CheckMap(context.TODO(), params, rules); e != nil {
fmt.Println(e.Map())
fmt.Println(e.FirstItem())
fmt.Println(e.FirstString())
diff --git a/.example/util/gvalid/gvalid_struct1.go b/.example/util/gvalid/gvalid_struct1.go
index d992860ee..6995ec2be 100644
--- a/.example/util/gvalid/gvalid_struct1.go
+++ b/.example/util/gvalid/gvalid_struct1.go
@@ -1,6 +1,7 @@
package main
import (
+ "context"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/util/gvalid"
)
@@ -20,7 +21,7 @@ func main() {
}
// 使用结构体定义的校验规则和错误提示进行校验
- g.Dump(gvalid.CheckStruct(user, nil).Map())
+ g.Dump(gvalid.CheckStruct(context.TODO(), user, nil).Map())
// 自定义校验规则和错误提示,对定义的特定校验规则和错误提示进行覆盖
rules := map[string]string{
@@ -31,5 +32,5 @@ func main() {
"password3": "名称不能为空",
},
}
- g.Dump(gvalid.CheckStruct(user, rules, msgs).Map())
+ g.Dump(gvalid.CheckStruct(context.TODO(), user, rules, msgs).Map())
}
diff --git a/.example/util/gvalid/gvalid_struct2.go b/.example/util/gvalid/gvalid_struct2.go
index a4c9442fb..8e6c11601 100644
--- a/.example/util/gvalid/gvalid_struct2.go
+++ b/.example/util/gvalid/gvalid_struct2.go
@@ -1,6 +1,7 @@
package main
import (
+ "context"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/util/gvalid"
)
@@ -13,5 +14,5 @@ func main() {
user := &User{}
- g.Dump(gvalid.CheckStruct(user, nil))
+ g.Dump(gvalid.CheckStruct(context.TODO(), user, nil))
}
diff --git a/.example/util/gvalid/gvalid_struct3.go b/.example/util/gvalid/gvalid_struct3.go
index de9980ca3..fdd0ea965 100644
--- a/.example/util/gvalid/gvalid_struct3.go
+++ b/.example/util/gvalid/gvalid_struct3.go
@@ -1,6 +1,7 @@
package main
import (
+ "context"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/util/gvalid"
)
@@ -15,5 +16,5 @@ func main() {
Pass: "1",
}
- g.Dump(gvalid.CheckStruct(user, nil).Maps())
+ g.Dump(gvalid.CheckStruct(context.TODO(), user, nil).Maps())
}
diff --git a/.example/util/gvalid/gvalid_struct_meta.go b/.example/util/gvalid/gvalid_struct_meta.go
new file mode 100644
index 000000000..a08e8d8ca
--- /dev/null
+++ b/.example/util/gvalid/gvalid_struct_meta.go
@@ -0,0 +1,40 @@
+package main
+
+import (
+ "context"
+ "fmt"
+ "github.com/gogf/gf/errors/gerror"
+ "github.com/gogf/gf/frame/g"
+ "github.com/gogf/gf/util/gmeta"
+)
+
+type UserCreateReq struct {
+ gmeta.Meta `v:"UserCreateReq"`
+ Name string
+ Pass string
+}
+
+func UserCreateReqChecker(ctx context.Context, rule string, value interface{}, message string, data interface{}) error {
+ user := &UserCreateReq{}
+ if v, ok := data.(*UserCreateReq); ok {
+ user = v
+ }
+ // SELECT COUNT(*) FROM `user` WHERE `name` = xxx
+ count, err := g.Model("user").Ctx(ctx).Where("name", user.Name).Count()
+ if err != nil {
+ return err
+ }
+ if count > 0 {
+ return gerror.Newf(`The name "%s" is already token`, user.Name)
+ }
+ return nil
+}
+
+func main() {
+ user := &UserCreateReq{
+ Name: "john",
+ Pass: "123456",
+ }
+ err := g.Validator().RuleFunc("UserCreateReq", UserCreateReqChecker).CheckStruct(user)
+ fmt.Println(err)
+}
diff --git a/.example/util/gvalid/i18n/cn.toml b/.example/util/gvalid/i18n/cn.toml
deleted file mode 100644
index 498f60e24..000000000
--- a/.example/util/gvalid/i18n/cn.toml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-"gf.gvalid.required" = "字段不能为空"
-
-
-
-
-
-
-
-
-
-
-
diff --git a/.example/util/gvalid/i18n/en.toml b/.example/util/gvalid/i18n/en.toml
new file mode 100644
index 000000000..7574fd595
--- /dev/null
+++ b/.example/util/gvalid/i18n/en.toml
@@ -0,0 +1,7 @@
+"gf.gvalid.required" = "字段不能为空"
+
+
+"ReuiredUserName" = "Please input user name"
+"ReuiredUserType" = "Please select user type"
+"MustSize" = "Size of :attribute must be :size"
+
diff --git a/.example/util/gvalid/i18n/zh-CN.toml b/.example/util/gvalid/i18n/zh-CN.toml
new file mode 100644
index 000000000..3db393e20
--- /dev/null
+++ b/.example/util/gvalid/i18n/zh-CN.toml
@@ -0,0 +1,16 @@
+
+
+"gf.gvalid.required" = "字段不能为空"
+
+"ReuiredUserName" = "请输入用户名称"
+"ReuiredUserType" = "请选择用户类型"
+"MustSize" = ":attribute长度必须为:size"
+
+
+
+
+
+
+
+
+
diff --git a/.gitee/ISSUE_TEMPLATE.MD b/.gitee/ISSUE_TEMPLATE.MD
index 1197badda..4d24425c3 100644
--- a/.gitee/ISSUE_TEMPLATE.MD
+++ b/.gitee/ISSUE_TEMPLATE.MD
@@ -1,4 +1,7 @@
-
+
+
+
+
### 1. 您当前使用的`Go`版本,及系统版本、系统架构?
diff --git a/.github/ISSUE_TEMPLATE.MD b/.github/ISSUE_TEMPLATE.MD
index 09e907f4e..364044d16 100644
--- a/.github/ISSUE_TEMPLATE.MD
+++ b/.github/ISSUE_TEMPLATE.MD
@@ -1,5 +1,10 @@
+
+
+
+
+
### 1. What version of `Go` and system type/arch are you using?
-### 3. Can this issue be reproduced with the latest release?
+### 3. Can this issue be re-produced with the latest release?
diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
new file mode 100644
index 000000000..86fb55226
--- /dev/null
+++ b/.github/workflows/go.yml
@@ -0,0 +1,71 @@
+name: GoFrame CI
+
+on:
+ push:
+ branches:
+ - master
+ - develop
+ pull_request:
+ branches: [master, develop]
+env:
+ GF_DEBUG: 1
+
+jobs:
+ code-test:
+ runs-on: ubuntu-latest
+ # Service containers to run with `code-test`
+ services:
+ redis:
+ image : redis
+ options: >-
+ --health-cmd "redis-cli ping"
+ --health-interval 10s
+ --health-timeout 5s
+ --health-retries 5
+ ports:
+ # Maps tcp port 6379 on service container to the host
+ - 6379:6379
+ mysql:
+ image: mysql:5.7
+ env:
+ MYSQL_DATABASE : test
+ MYSQL_ROOT_PASSWORD: 12345678
+ ports:
+ # Maps tcp port 3306 on service container to the host
+ - 3306:3306
+
+ # strategy set
+ strategy:
+ matrix:
+ go: ["1.14", "1.15", "1.16"]
+
+ steps:
+ - name: Set Up Timezone
+ uses: szenius/set-timezone@v1.0
+ with:
+ timezoneLinux: "Asia/Shanghai"
+
+ - name: Checkout Repositary
+ uses: actions/checkout@v2
+
+ - name: Set Up Go
+ uses: actions/setup-go@v2
+ with:
+ go-version: ${{ matrix.go }}
+
+ - name: Before Script
+ run: |
+ date
+ find . -name "*.go" | xargs gofmt -w
+ git diff --name-only --exit-code || exit 1
+ sudo echo "127.0.0.1 local" | sudo tee -a /etc/hosts
+
+ - name: Run i386 Arch Test
+ run: GOARCH=386 go test -v ./... || exit 1
+
+ - name: Run amd64 Arch Test
+ run: GOARCH=amd64 go test -v ./... -race -coverprofile=coverage.txt -covermode=atomic
+
+ - name: Report Coverage
+ run: bash <(curl -s https://codecov.io/bash)
+
diff --git a/.gitignore b/.gitignore
index a21ea7259..fdb500de8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,5 +14,6 @@ bin/
cbuild
**/.DS_Store
.vscode/
-go.sum
.example/other/
+main
+gf
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
index ee2f52ac1..d11a3c960 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,11 +1,12 @@
+os: linux
+arch: arm64-graviton2
+
language: go
go:
- - "1.11.x"
- - "1.12.x"
- - "1.13.x"
- "1.14.x"
- "1.15.x"
+ - "1.16.x"
branches:
only:
@@ -14,7 +15,7 @@ branches:
- staging
env:
-- GF_DEBUG=1 GO111MODULE=on
+- TZ=Asia/Shanghai GF_DEBUG=1 GO111MODULE=on
services:
- mysql
diff --git a/README.MD b/README.MD
index cdc2e6ac1..dda9ad1a5 100644
--- a/README.MD
+++ b/README.MD
@@ -1,7 +1,7 @@
# GoFrame
[](https://godoc.org/github.com/gogf/gf)
-[](https://travis-ci.org/gogf/gf)
+[](https://github.com/gogf/gf/actions/workflows/go.yml)
[](https://goreportcard.com/report/github.com/gogf/gf)
[](https://codecov.io/gh/gogf/gf/branch/master)
[](https://github.com/gogf/gf)
@@ -9,11 +9,8 @@
English | [简体中文](README_ZH.MD)
-`GF(GoFrame)` is a modular, powerful, high-performance and enterprise-class application development framework
-of Golang. Providing a series of core components and dozens of practical modules, such as:
-cache, logging, containers, timer, resource, validator, database orm, etc.
-Supporting web server integrated with router, cookie, session, middleware, logger, configure,
-template, https, hooks, rewrites and many more features.
+`GoFrame` is a modular, powerful, high-performance and enterprise-class application development framework
+of Golang.
> If you're a newbie to `Go`, you may consider `GoFrame` easy and great as `Laravel` in `PHP`, `SpringBoot` in `Java` or `Django` in `Python`.
@@ -33,7 +30,7 @@ golang version >= 1.11
# Architecture
-

+
# Packages
@@ -53,17 +50,10 @@ The `Web` component performance of `GoFrame`, please refer to third-party projec
# Documentation
-* 中文官网: https://goframe.org
-* GoDoc API: https://godoc.org/github.com/gogf/gf
+* 中文官网: [https://goframe.org](https://goframe.org/display/gf)
+* GoDoc API: [https://pkg.go.dev/github.com/gogf/gf](https://pkg.go.dev/github.com/gogf/gf)
-# Discussion
-- QQ Group:[116707870](//shang.qq.com/wpa/qunwpa?idkey=195f91eceeb5d7fa76009b7cd5a4641f70bf4897b7f5a520635eb26ff17adfe7)
-- WX Group:Add friend`389961817` in WeChat, commenting `GF`
-- Issues:https://github.com/gogf/gf/issues
-
-> It's recommended learning `GoFrame` through its awesome source codes and API reference.
-
# License
`GF` is licensed under the [MIT License](LICENSE), 100% free and open-source, forever.
@@ -80,7 +70,7 @@ The `Web` component performance of `GoFrame`, please refer to third-party projec
- [XiMaLaYa](https://www.ximalaya.com)
- [ZYBang](https://www.zybang.com/)
-> We list part of the users here, if your company or products are using `GoFrame`, please let us know [here](https://github.com/gogf/gf/issues/168).
+> We list part of the users here, if your company or products are using `GoFrame`, please let us know [here](https://goframe.org/pages/viewpage.action?pageId=1114415).
# Contributors
@@ -90,7 +80,7 @@ This project exists thanks to all the people who contribute. [[Contributors](htt
# Donators
-If you love `GF`, why not [buy developer a cup of coffee](https://itician.org/pages/viewpage.action?pageId=1115633)?
+If you love `GF`, why not [buy developer a cup of coffee](https://goframe.org/pages/viewpage.action?pageId=1115633)?
# Sponsors
We appreciate any kind of sponsorship for `GF` development. If you've got some interesting, please contact WeChat `389961817` / Email `john@goframe.org`.
@@ -98,8 +88,8 @@ We appreciate any kind of sponsorship for `GF` development. If you've got some i
# Thanks
-
-
+
+
diff --git a/README_ZH.MD b/README_ZH.MD
index 77f472620..79b22cfde 100644
--- a/README_ZH.MD
+++ b/README_ZH.MD
@@ -1,6 +1,6 @@
# GoFrame
[](https://godoc.org/github.com/gogf/gf)
-[](https://travis-ci.org/gogf/gf)
+[](https://travis-ci.org/gogf/gf)
[](https://goreportcard.com/report/github.com/gogf/gf)
[](https://codecov.io/gh/gogf/gf/branch/master)
[](https://github.com/gogf/gf)
@@ -8,24 +8,21 @@
[English](README.MD) | 简体中文
-`GF(Go Frame)`是一款模块化、高性能、企业级的Go基础开发框架。
-实现了比较完善的基础设施建设以及开发工具链,提供了常用的基础开发模块,
-如:缓存、日志、队列、数组、集合、容器、定时器、命令行、内存锁、对象池、
-配置管理、资源管理、数据校验、数据编码、定时任务、数据库ORM、TCP/UDP组件、进程管理/通信等等。
-并提供了Web服务开发的系列核心组件,如:Router、Cookie、Session、Middleware、服务注册、模板引擎等等,
-支持热重启、热更新、域名绑定、TLS/HTTPS、Rewrite等特性。
+`GoFrame`是一款模块化、高性能、企业级的Go基础开发框架。
> 如果您初识`Go`语言,您可以将`GoFrame`类似于`PHP`中的`Laravel`, `Java`中的`SpringBoot`或者`Python`中的`Django`。
# 特点
-* 模块化、松耦合设计;
-* 模块丰富、开箱即用;
-* 简便易用、易于维护;
-* 高代码质量、高单元测试覆盖率;
-* 社区活跃,大牛谦逊低调脾气好;
-* 详尽的开发文档及示例;
-* 完善的本地中文化支持;
-* 设计为团队及企业使用;
+* 模块化、松耦合
+* 模块丰富、开箱即用
+* 简洁易用、快速接入
+* 文档详尽、易于维护
+* 自顶向下、体系化设计
+* 统一框架、统一组件、降低选择成本
+* 开发规范、设计模式、代码分层模型
+* 强大便捷的开发工具链
+* 完善的本地中文化支持
+* 设计为团队及企业使用
# 地址
- **主库**:https://github.com/gogf/gf
@@ -49,7 +46,7 @@ golang版本 >= 1.11
# 架构
-

+
# 模块
@@ -64,21 +61,14 @@ golang版本 >= 1.11
# 性能
-
-`Web`组件的性能测试,请参考第三方性能测试评估:https://github.com/the-benchmarker/web-frameworks
+大家较为感兴趣的`Web`组件性能测试,请参考第三方性能测试评估:https://github.com/the-benchmarker/web-frameworks
# 文档
-开发文档:https://goframe.org
+官方站点:[https://goframe.org](https://goframe.org/display/gf)
-接口文档:https://godoc.org/github.com/gogf/gf
+接口文档:[https://pkg.go.dev/github.com/gogf/gf](https://pkg.go.dev/github.com/gogf/gf)
-# 帮助
-- QQ交流群:[116707870](//shang.qq.com/wpa/qunwpa?idkey=195f91eceeb5d7fa76009b7cd5a4641f70bf4897b7f5a520635eb26ff17adfe7)
-- WX交流群:微信添加`389961817`备注`GF`
-- 主库ISSUE:https://github.com/gogf/gf/issues
-
-> 建议通过阅读`GoFrame`的源码以及API文档深度学习`GoFrame`,了解更多的精妙设计。
# 协议
@@ -87,7 +77,7 @@ golang版本 >= 1.11
# 用户
- [腾讯科技](https://www.tencent.com/)
-- [中兴科技](https://www.zte.com.cn/china/)
+- [中兴通讯](https://www.zte.com.cn/china/)
- [蚂蚁金服](https://www.antfin.com/)
- [医联科技](https://www.medlinker.com/)
- [库币科技](https://www.kucoin.io/)
@@ -96,7 +86,7 @@ golang版本 >= 1.11
- [喜马拉雅](https://www.ximalaya.com)
- [作业帮](https://www.zybang.com/)
-> 在这里只列举了部分知名的用户,如果您的企业或者产品正在使用`GoFrame`,欢迎到 [这里](https://github.com/gogf/gf/issues/168) 留言。
+> 在这里只列举了部分知名的用户,如果您的企业或者产品正在使用`GoFrame`,欢迎到 [这里](https://goframe.org/pages/viewpage.action?pageId=1114415) 留言。
# 贡献
@@ -106,7 +96,7 @@ golang版本 >= 1.11
# 捐赠
-如果您喜欢`GF`,要不给开发者 [来杯咖啡](https://itician.org/pages/viewpage.action?pageId=1115633) 吧!
+如果您喜欢`GF`,要不给开发者 [来杯咖啡](https://goframe.org/pages/viewpage.action?pageId=1115633) 吧!
请在捐赠时备注您的`github`/`gitee`账号名称。
# 赞助
@@ -114,5 +104,6 @@ golang版本 >= 1.11
赞助支持`GF`框架的快速研发,如果您感兴趣,请联系 微信 `389961817` / 邮件 `john@goframe.org`。
# 感谢
-
-
+
+
+
diff --git a/container/garray/garray.go b/container/garray/garray.go
index 8cc88e71b..08e9ece89 100644
--- a/container/garray/garray.go
+++ b/container/garray/garray.go
@@ -1,4 +1,4 @@
-// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
+// 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,
diff --git a/container/garray/garray_func.go b/container/garray/garray_func.go
index 572cba444..d3e7b7795 100644
--- a/container/garray/garray_func.go
+++ b/container/garray/garray_func.go
@@ -1,4 +1,4 @@
-// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved.
+// 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,
diff --git a/container/garray/garray_normal_any.go b/container/garray/garray_normal_any.go
index 4c41cc2d4..07b33c813 100644
--- a/container/garray/garray_normal_any.go
+++ b/container/garray/garray_normal_any.go
@@ -1,4 +1,4 @@
-// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
+// 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,
@@ -8,8 +8,9 @@ package garray
import (
"bytes"
- "errors"
"fmt"
+ "github.com/gogf/gf/errors/gcode"
+ "github.com/gogf/gf/errors/gerror"
"github.com/gogf/gf/internal/empty"
"github.com/gogf/gf/internal/json"
"github.com/gogf/gf/text/gstr"
@@ -30,19 +31,19 @@ type Array struct {
}
// New creates and returns an empty array.
-// The parameter is used to specify whether using array in concurrent-safety,
+// The parameter `safe` is used to specify whether using array in concurrent-safety,
// which is false in default.
func New(safe ...bool) *Array {
return NewArraySize(0, 0, safe...)
}
-// See New.
+// NewArray is alias of New, please see New.
func NewArray(safe ...bool) *Array {
return NewArraySize(0, 0, safe...)
}
// NewArraySize create and returns an array with given size and cap.
-// The parameter is used to specify whether using array in concurrent-safety,
+// The parameter `safe` is used to specify whether using array in concurrent-safety,
// which is false in default.
func NewArraySize(size int, cap int, safe ...bool) *Array {
return &Array{
@@ -51,8 +52,8 @@ func NewArraySize(size int, cap int, safe ...bool) *Array {
}
}
-// NewArrayRange creates and returns a array by a range from to
-// with step value .
+// NewArrayRange creates and returns a array by a range from `start` to `end`
+// with step value `step`.
func NewArrayRange(start, end, step int, safe ...bool) *Array {
if step == 0 {
panic(fmt.Sprintf(`invalid step value: %d`, step))
@@ -66,18 +67,20 @@ func NewArrayRange(start, end, step int, safe ...bool) *Array {
return NewArrayFrom(slice, safe...)
}
+// NewFrom is alias of NewArrayFrom.
// See NewArrayFrom.
func NewFrom(array []interface{}, safe ...bool) *Array {
return NewArrayFrom(array, safe...)
}
+// NewFromCopy is alias of NewArrayFromCopy.
// See NewArrayFromCopy.
func NewFromCopy(array []interface{}, safe ...bool) *Array {
return NewArrayFromCopy(array, safe...)
}
-// NewArrayFrom creates and returns an array with given slice .
-// The parameter is used to specify whether using array in concurrent-safety,
+// NewArrayFrom creates and returns an array with given slice `array`.
+// The parameter `safe` is used to specify whether using array in concurrent-safety,
// which is false in default.
func NewArrayFrom(array []interface{}, safe ...bool) *Array {
return &Array{
@@ -86,8 +89,8 @@ func NewArrayFrom(array []interface{}, safe ...bool) *Array {
}
}
-// NewArrayFromCopy creates and returns an array from a copy of given slice .
-// The parameter is used to specify whether using array in concurrent-safety,
+// NewArrayFromCopy creates and returns an array from a copy of given slice `array`.
+// The parameter `safe` is used to specify whether using array in concurrent-safety,
// which is false in default.
func NewArrayFromCopy(array []interface{}, safe ...bool) *Array {
newArray := make([]interface{}, len(array))
@@ -98,8 +101,15 @@ func NewArrayFromCopy(array []interface{}, safe ...bool) *Array {
}
}
+// At returns the value by the specified index.
+// If the given `index` is out of range of the array, it returns `nil`.
+func (a *Array) At(index int) (value interface{}) {
+ value, _ = a.Get(index)
+ return
+}
+
// Get returns the value by the specified index.
-// If the given is out of range of the array, the is false.
+// If the given `index` is out of range of the array, the `found` is false.
func (a *Array) Get(index int) (value interface{}, found bool) {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -114,13 +124,13 @@ func (a *Array) Set(index int, value interface{}) error {
a.mu.Lock()
defer a.mu.Unlock()
if index < 0 || index >= len(a.array) {
- return errors.New(fmt.Sprintf("index %d out of array range %d", index, len(a.array)))
+ return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", index, len(a.array))
}
a.array[index] = value
return nil
}
-// SetArray sets the underlying slice array with the given .
+// SetArray sets the underlying slice array with the given `array`.
func (a *Array) SetArray(array []interface{}) *Array {
a.mu.Lock()
defer a.mu.Unlock()
@@ -128,7 +138,7 @@ func (a *Array) SetArray(array []interface{}) *Array {
return a
}
-// Replace replaces the array items by given from the beginning of array.
+// Replace replaces the array items by given `array` from the beginning of array.
func (a *Array) Replace(array []interface{}) *Array {
a.mu.Lock()
defer a.mu.Unlock()
@@ -152,7 +162,7 @@ func (a *Array) Sum() (sum int) {
return
}
-// SortFunc sorts the array by custom function .
+// SortFunc sorts the array by custom function `less`.
func (a *Array) SortFunc(less func(v1, v2 interface{}) bool) *Array {
a.mu.Lock()
defer a.mu.Unlock()
@@ -162,12 +172,12 @@ func (a *Array) SortFunc(less func(v1, v2 interface{}) bool) *Array {
return a
}
-// InsertBefore inserts the to the front of .
+// InsertBefore inserts the `value` to the front of `index`.
func (a *Array) InsertBefore(index int, value interface{}) error {
a.mu.Lock()
defer a.mu.Unlock()
if index < 0 || index >= len(a.array) {
- return errors.New(fmt.Sprintf("index %d out of array range %d", index, len(a.array)))
+ return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", index, len(a.array))
}
rear := append([]interface{}{}, a.array[index:]...)
a.array = append(a.array[0:index], value)
@@ -175,12 +185,12 @@ func (a *Array) InsertBefore(index int, value interface{}) error {
return nil
}
-// InsertAfter inserts the to the back of .
+// InsertAfter inserts the `value` to the back of `index`.
func (a *Array) InsertAfter(index int, value interface{}) error {
a.mu.Lock()
defer a.mu.Unlock()
if index < 0 || index >= len(a.array) {
- return errors.New(fmt.Sprintf("index %d out of array range %d", index, len(a.array)))
+ return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", index, len(a.array))
}
rear := append([]interface{}{}, a.array[index+1:]...)
a.array = append(a.array[0:index+1], value)
@@ -189,7 +199,7 @@ func (a *Array) InsertAfter(index int, value interface{}) error {
}
// Remove removes an item by index.
-// If the given is out of range of the array, the is false.
+// If the given `index` is out of range of the array, the `found` is false.
func (a *Array) Remove(index int) (value interface{}, found bool) {
a.mu.Lock()
defer a.mu.Unlock()
@@ -247,14 +257,14 @@ func (a *Array) PushRight(value ...interface{}) *Array {
}
// PopRand randomly pops and return an item out of array.
-// Note that if the array is empty, the is false.
+// Note that if the array is empty, the `found` is false.
func (a *Array) PopRand() (value interface{}, found bool) {
a.mu.Lock()
defer a.mu.Unlock()
return a.doRemoveWithoutLock(grand.Intn(len(a.array)))
}
-// PopRands randomly pops and returns items out of array.
+// PopRands randomly pops and returns `size` items out of array.
func (a *Array) PopRands(size int) []interface{} {
a.mu.Lock()
defer a.mu.Unlock()
@@ -272,7 +282,7 @@ func (a *Array) PopRands(size int) []interface{} {
}
// PopLeft pops and returns an item from the beginning of array.
-// Note that if the array is empty, the is false.
+// Note that if the array is empty, the `found` is false.
func (a *Array) PopLeft() (value interface{}, found bool) {
a.mu.Lock()
defer a.mu.Unlock()
@@ -285,7 +295,7 @@ func (a *Array) PopLeft() (value interface{}, found bool) {
}
// PopRight pops and returns an item from the end of array.
-// Note that if the array is empty, the is false.
+// Note that if the array is empty, the `found` is false.
func (a *Array) PopRight() (value interface{}, found bool) {
a.mu.Lock()
defer a.mu.Unlock()
@@ -298,7 +308,7 @@ func (a *Array) PopRight() (value interface{}, found bool) {
return value, true
}
-// PopLefts pops and returns items from the beginning of array.
+// PopLefts pops and returns `size` items from the beginning of array.
func (a *Array) PopLefts(size int) []interface{} {
a.mu.Lock()
defer a.mu.Unlock()
@@ -315,7 +325,7 @@ func (a *Array) PopLefts(size int) []interface{} {
return value
}
-// PopRights pops and returns items from the end of array.
+// PopRights pops and returns `size` items from the end of array.
func (a *Array) PopRights(size int) []interface{} {
a.mu.Lock()
defer a.mu.Unlock()
@@ -337,8 +347,8 @@ func (a *Array) PopRights(size int) []interface{} {
// Notice, if in concurrent-safe usage, it returns a copy of slice;
// else a pointer to the underlying data.
//
-// If is negative, then the offset will start from the end of array.
-// If is omitted, then the sequence will have everything from start up
+// If `end` is negative, then the offset will start from the end of array.
+// If `end` is omitted, then the sequence will have everything from start up
// until the end of the array.
func (a *Array) Range(start int, end ...int) []interface{} {
a.mu.RLock()
@@ -364,7 +374,7 @@ func (a *Array) Range(start int, end ...int) []interface{} {
}
// SubSlice returns a slice of elements from the array as specified
-// by the and parameters.
+// by the `offset` and `size` parameters.
// If in concurrent safe usage, it returns a copy of the slice; else a pointer.
//
// If offset is non-negative, the sequence will start at that offset in the array.
@@ -413,7 +423,7 @@ func (a *Array) SubSlice(offset int, length ...int) []interface{} {
}
}
-// See PushRight.
+// Append is alias of PushRight, please See PushRight.
func (a *Array) Append(value ...interface{}) *Array {
a.PushRight(value...)
return a
@@ -471,7 +481,7 @@ func (a *Array) Contains(value interface{}) bool {
return a.Search(value) != -1
}
-// Search searches array by , returns the index of ,
+// Search searches array by `value`, returns the index of `value`,
// or returns -1 if not exists.
func (a *Array) Search(value interface{}) int {
a.mu.RLock()
@@ -506,7 +516,7 @@ func (a *Array) Unique() *Array {
return a
}
-// LockFunc locks writing by callback function .
+// LockFunc locks writing by callback function `f`.
func (a *Array) LockFunc(f func(array []interface{})) *Array {
a.mu.Lock()
defer a.mu.Unlock()
@@ -514,7 +524,7 @@ func (a *Array) LockFunc(f func(array []interface{})) *Array {
return a
}
-// RLockFunc locks reading by callback function .
+// RLockFunc locks reading by callback function `f`.
func (a *Array) RLockFunc(f func(array []interface{})) *Array {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -522,21 +532,21 @@ func (a *Array) RLockFunc(f func(array []interface{})) *Array {
return a
}
-// Merge merges into current array.
-// The parameter can be any garray or slice type.
+// Merge merges `array` into current array.
+// The parameter `array` can be any garray or slice type.
// The difference between Merge and Append is Append supports only specified slice type,
// but Merge supports more parameter types.
func (a *Array) Merge(array interface{}) *Array {
return a.Append(gconv.Interfaces(array)...)
}
-// Fill fills an array with num entries of the value ,
-// keys starting at the parameter.
+// Fill fills an array with num entries of the value `value`,
+// keys starting at the `startIndex` parameter.
func (a *Array) Fill(startIndex int, num int, value interface{}) error {
a.mu.Lock()
defer a.mu.Unlock()
if startIndex < 0 || startIndex > len(a.array) {
- return errors.New(fmt.Sprintf("index %d out of array range %d", startIndex, len(a.array)))
+ return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", startIndex, len(a.array))
}
for i := startIndex; i < startIndex+num; i++ {
if i > len(a.array)-1 {
@@ -549,7 +559,7 @@ func (a *Array) Fill(startIndex int, num int, value interface{}) error {
}
// Chunk splits an array into multiple arrays,
-// the size of each array is determined by .
+// the size of each array is determined by `size`.
// The last chunk may contain less than size elements.
func (a *Array) Chunk(size int) [][]interface{} {
if size < 1 {
@@ -571,9 +581,9 @@ func (a *Array) Chunk(size int) [][]interface{} {
return n
}
-// Pad pads array to the specified length with .
+// Pad pads array to the specified length with `value`.
// If size is positive then the array is padded on the right, or negative on the left.
-// If the absolute value of is less than or equal to the length of the array
+// If the absolute value of `size` is less than or equal to the length of the array
// then no padding takes place.
func (a *Array) Pad(size int, val interface{}) *Array {
a.mu.Lock()
@@ -608,7 +618,7 @@ func (a *Array) Rand() (value interface{}, found bool) {
return a.array[grand.Intn(len(a.array))], true
}
-// Rands randomly returns items from array(no deleting).
+// Rands randomly returns `size` items from array(no deleting).
func (a *Array) Rands(size int) []interface{} {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -642,7 +652,7 @@ func (a *Array) Reverse() *Array {
return a
}
-// Join joins array elements with a string .
+// Join joins array elements with a string `glue`.
func (a *Array) Join(glue string) string {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -675,8 +685,8 @@ func (a *Array) Iterator(f func(k int, v interface{}) bool) {
a.IteratorAsc(f)
}
-// IteratorAsc iterates the array readonly in ascending order with given callback function .
-// If returns true, then it continues iterating; or false to stop.
+// IteratorAsc iterates the array readonly in ascending order with given callback function `f`.
+// If `f` returns true, then it continues iterating; or false to stop.
func (a *Array) IteratorAsc(f func(k int, v interface{}) bool) {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -687,8 +697,8 @@ func (a *Array) IteratorAsc(f func(k int, v interface{}) bool) {
}
}
-// IteratorDesc iterates the array readonly in descending order with given callback function .
-// If returns true, then it continues iterating; or false to stop.
+// IteratorDesc iterates the array readonly in descending order with given callback function `f`.
+// If `f` returns true, then it continues iterating; or false to stop.
func (a *Array) IteratorDesc(f func(k int, v interface{}) bool) {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -736,7 +746,7 @@ func (a *Array) UnmarshalJSON(b []byte) error {
}
a.mu.Lock()
defer a.mu.Unlock()
- if err := json.Unmarshal(b, &a.array); err != nil {
+ if err := json.UnmarshalUseNumber(b, &a.array); err != nil {
return err
}
return nil
@@ -748,7 +758,7 @@ func (a *Array) UnmarshalValue(value interface{}) error {
defer a.mu.Unlock()
switch value.(type) {
case string, []byte:
- return json.Unmarshal(gconv.Bytes(value), &a.array)
+ return json.UnmarshalUseNumber(gconv.Bytes(value), &a.array)
default:
a.array = gconv.SliceAny(value)
}
@@ -784,7 +794,7 @@ func (a *Array) FilterEmpty() *Array {
return a
}
-// Walk applies a user supplied function to every item of array.
+// Walk applies a user supplied function `f` to every item of array.
func (a *Array) Walk(f func(value interface{}) interface{}) *Array {
a.mu.Lock()
defer a.mu.Unlock()
diff --git a/container/garray/garray_normal_int.go b/container/garray/garray_normal_int.go
index 69d4c157a..ee3d173ba 100644
--- a/container/garray/garray_normal_int.go
+++ b/container/garray/garray_normal_int.go
@@ -1,4 +1,4 @@
-// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
+// 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,
@@ -8,8 +8,9 @@ package garray
import (
"bytes"
- "errors"
"fmt"
+ "github.com/gogf/gf/errors/gcode"
+ "github.com/gogf/gf/errors/gerror"
"github.com/gogf/gf/internal/json"
"math"
"sort"
@@ -28,14 +29,14 @@ type IntArray struct {
}
// NewIntArray creates and returns an empty array.
-// The parameter is used to specify whether using array in concurrent-safety,
+// The parameter `safe` is used to specify whether using array in concurrent-safety,
// which is false in default.
func NewIntArray(safe ...bool) *IntArray {
return NewIntArraySize(0, 0, safe...)
}
// NewIntArraySize create and returns an array with given size and cap.
-// The parameter is used to specify whether using array in concurrent-safety,
+// The parameter `safe` is used to specify whether using array in concurrent-safety,
// which is false in default.
func NewIntArraySize(size int, cap int, safe ...bool) *IntArray {
return &IntArray{
@@ -44,8 +45,8 @@ func NewIntArraySize(size int, cap int, safe ...bool) *IntArray {
}
}
-// NewIntArrayRange creates and returns a array by a range from to
-// with step value .
+// NewIntArrayRange creates and returns a array by a range from `start` to `end`
+// with step value `step`.
func NewIntArrayRange(start, end, step int, safe ...bool) *IntArray {
if step == 0 {
panic(fmt.Sprintf(`invalid step value: %d`, step))
@@ -59,8 +60,8 @@ func NewIntArrayRange(start, end, step int, safe ...bool) *IntArray {
return NewIntArrayFrom(slice, safe...)
}
-// NewIntArrayFrom creates and returns an array with given slice .
-// The parameter is used to specify whether using array in concurrent-safety,
+// NewIntArrayFrom creates and returns an array with given slice `array`.
+// The parameter `safe` is used to specify whether using array in concurrent-safety,
// which is false in default.
func NewIntArrayFrom(array []int, safe ...bool) *IntArray {
return &IntArray{
@@ -69,8 +70,8 @@ func NewIntArrayFrom(array []int, safe ...bool) *IntArray {
}
}
-// NewIntArrayFromCopy creates and returns an array from a copy of given slice .
-// The parameter is used to specify whether using array in concurrent-safety,
+// NewIntArrayFromCopy creates and returns an array from a copy of given slice `array`.
+// The parameter `safe` is used to specify whether using array in concurrent-safety,
// which is false in default.
func NewIntArrayFromCopy(array []int, safe ...bool) *IntArray {
newArray := make([]int, len(array))
@@ -81,8 +82,15 @@ func NewIntArrayFromCopy(array []int, safe ...bool) *IntArray {
}
}
+// At returns the value by the specified index.
+// If the given `index` is out of range of the array, it returns `0`.
+func (a *IntArray) At(index int) (value int) {
+ value, _ = a.Get(index)
+ return
+}
+
// Get returns the value by the specified index.
-// If the given is out of range of the array, the is false.
+// If the given `index` is out of range of the array, the `found` is false.
func (a *IntArray) Get(index int) (value int, found bool) {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -97,13 +105,13 @@ func (a *IntArray) Set(index int, value int) error {
a.mu.Lock()
defer a.mu.Unlock()
if index < 0 || index >= len(a.array) {
- return errors.New(fmt.Sprintf("index %d out of array range %d", index, len(a.array)))
+ return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", index, len(a.array))
}
a.array[index] = value
return nil
}
-// SetArray sets the underlying slice array with the given .
+// SetArray sets the underlying slice array with the given `array`.
func (a *IntArray) SetArray(array []int) *IntArray {
a.mu.Lock()
defer a.mu.Unlock()
@@ -111,7 +119,7 @@ func (a *IntArray) SetArray(array []int) *IntArray {
return a
}
-// Replace replaces the array items by given from the beginning of array.
+// Replace replaces the array items by given `array` from the beginning of array.
func (a *IntArray) Replace(array []int) *IntArray {
a.mu.Lock()
defer a.mu.Unlock()
@@ -136,16 +144,13 @@ func (a *IntArray) Sum() (sum int) {
}
// Sort sorts the array in increasing order.
-// The parameter controls whether sort in increasing order(default) or decreasing order.
+// The parameter `reverse` controls whether sort in increasing order(default) or decreasing order.
func (a *IntArray) Sort(reverse ...bool) *IntArray {
a.mu.Lock()
defer a.mu.Unlock()
if len(reverse) > 0 && reverse[0] {
sort.Slice(a.array, func(i, j int) bool {
- if a.array[i] < a.array[j] {
- return false
- }
- return true
+ return a.array[i] >= a.array[j]
})
} else {
sort.Ints(a.array)
@@ -153,7 +158,7 @@ func (a *IntArray) Sort(reverse ...bool) *IntArray {
return a
}
-// SortFunc sorts the array by custom function .
+// SortFunc sorts the array by custom function `less`.
func (a *IntArray) SortFunc(less func(v1, v2 int) bool) *IntArray {
a.mu.Lock()
defer a.mu.Unlock()
@@ -163,12 +168,12 @@ func (a *IntArray) SortFunc(less func(v1, v2 int) bool) *IntArray {
return a
}
-// InsertBefore inserts the to the front of .
+// InsertBefore inserts the `value` to the front of `index`.
func (a *IntArray) InsertBefore(index int, value int) error {
a.mu.Lock()
defer a.mu.Unlock()
if index < 0 || index >= len(a.array) {
- return errors.New(fmt.Sprintf("index %d out of array range %d", index, len(a.array)))
+ return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", index, len(a.array))
}
rear := append([]int{}, a.array[index:]...)
a.array = append(a.array[0:index], value)
@@ -176,12 +181,12 @@ func (a *IntArray) InsertBefore(index int, value int) error {
return nil
}
-// InsertAfter inserts the to the back of .
+// InsertAfter inserts the `value` to the back of `index`.
func (a *IntArray) InsertAfter(index int, value int) error {
a.mu.Lock()
defer a.mu.Unlock()
if index < 0 || index >= len(a.array) {
- return errors.New(fmt.Sprintf("index %d out of array range %d", index, len(a.array)))
+ return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", index, len(a.array))
}
rear := append([]int{}, a.array[index+1:]...)
a.array = append(a.array[0:index+1], value)
@@ -190,7 +195,7 @@ func (a *IntArray) InsertAfter(index int, value int) error {
}
// Remove removes an item by index.
-// If the given is out of range of the array, the is false.
+// If the given `index` is out of range of the array, the `found` is false.
func (a *IntArray) Remove(index int) (value int, found bool) {
a.mu.Lock()
defer a.mu.Unlock()
@@ -248,7 +253,7 @@ func (a *IntArray) PushRight(value ...int) *IntArray {
}
// PopLeft pops and returns an item from the beginning of array.
-// Note that if the array is empty, the is false.
+// Note that if the array is empty, the `found` is false.
func (a *IntArray) PopLeft() (value int, found bool) {
a.mu.Lock()
defer a.mu.Unlock()
@@ -261,7 +266,7 @@ func (a *IntArray) PopLeft() (value int, found bool) {
}
// PopRight pops and returns an item from the end of array.
-// Note that if the array is empty, the is false.
+// Note that if the array is empty, the `found` is false.
func (a *IntArray) PopRight() (value int, found bool) {
a.mu.Lock()
defer a.mu.Unlock()
@@ -275,16 +280,16 @@ func (a *IntArray) PopRight() (value int, found bool) {
}
// PopRand randomly pops and return an item out of array.
-// Note that if the array is empty, the is false.
+// Note that if the array is empty, the `found` is false.
func (a *IntArray) PopRand() (value int, found bool) {
a.mu.Lock()
defer a.mu.Unlock()
return a.doRemoveWithoutLock(grand.Intn(len(a.array)))
}
-// PopRands randomly pops and returns items out of array.
-// If the given is greater than size of the array, it returns all elements of the array.
-// Note that if given <= 0 or the array is empty, it returns nil.
+// PopRands randomly pops and returns `size` items out of array.
+// If the given `size` is greater than size of the array, it returns all elements of the array.
+// Note that if given `size` <= 0 or the array is empty, it returns nil.
func (a *IntArray) PopRands(size int) []int {
a.mu.Lock()
defer a.mu.Unlock()
@@ -301,9 +306,9 @@ func (a *IntArray) PopRands(size int) []int {
return array
}
-// PopLefts pops and returns items from the beginning of array.
-// If the given is greater than size of the array, it returns all elements of the array.
-// Note that if given <= 0 or the array is empty, it returns nil.
+// PopLefts pops and returns `size` items from the beginning of array.
+// If the given `size` is greater than size of the array, it returns all elements of the array.
+// Note that if given `size` <= 0 or the array is empty, it returns nil.
func (a *IntArray) PopLefts(size int) []int {
a.mu.Lock()
defer a.mu.Unlock()
@@ -320,9 +325,9 @@ func (a *IntArray) PopLefts(size int) []int {
return value
}
-// PopRights pops and returns items from the end of array.
-// If the given is greater than size of the array, it returns all elements of the array.
-// Note that if given <= 0 or the array is empty, it returns nil.
+// PopRights pops and returns `size` items from the end of array.
+// If the given `size` is greater than size of the array, it returns all elements of the array.
+// Note that if given `size` <= 0 or the array is empty, it returns nil.
func (a *IntArray) PopRights(size int) []int {
a.mu.Lock()
defer a.mu.Unlock()
@@ -344,8 +349,8 @@ func (a *IntArray) PopRights(size int) []int {
// Notice, if in concurrent-safe usage, it returns a copy of slice;
// else a pointer to the underlying data.
//
-// If is negative, then the offset will start from the end of array.
-// If is omitted, then the sequence will have everything from start up
+// If `end` is negative, then the offset will start from the end of array.
+// If `end` is omitted, then the sequence will have everything from start up
// until the end of the array.
func (a *IntArray) Range(start int, end ...int) []int {
a.mu.RLock()
@@ -371,7 +376,7 @@ func (a *IntArray) Range(start int, end ...int) []int {
}
// SubSlice returns a slice of elements from the array as specified
-// by the and parameters.
+// by the `offset` and `size` parameters.
// If in concurrent safe usage, it returns a copy of the slice; else a pointer.
//
// If offset is non-negative, the sequence will start at that offset in the array.
@@ -420,7 +425,7 @@ func (a *IntArray) SubSlice(offset int, length ...int) []int {
}
}
-// See PushRight.
+// Append is alias of PushRight,please See PushRight.
func (a *IntArray) Append(value ...int) *IntArray {
a.mu.Lock()
a.array = append(a.array, value...)
@@ -487,7 +492,7 @@ func (a *IntArray) Contains(value int) bool {
return a.Search(value) != -1
}
-// Search searches array by , returns the index of ,
+// Search searches array by `value`, returns the index of `value`,
// or returns -1 if not exists.
func (a *IntArray) Search(value int) int {
a.mu.RLock()
@@ -522,7 +527,7 @@ func (a *IntArray) Unique() *IntArray {
return a
}
-// LockFunc locks writing by callback function .
+// LockFunc locks writing by callback function `f`.
func (a *IntArray) LockFunc(f func(array []int)) *IntArray {
a.mu.Lock()
defer a.mu.Unlock()
@@ -530,7 +535,7 @@ func (a *IntArray) LockFunc(f func(array []int)) *IntArray {
return a
}
-// RLockFunc locks reading by callback function .
+// RLockFunc locks reading by callback function `f`.
func (a *IntArray) RLockFunc(f func(array []int)) *IntArray {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -538,21 +543,21 @@ func (a *IntArray) RLockFunc(f func(array []int)) *IntArray {
return a
}
-// Merge merges into current array.
-// The parameter can be any garray or slice type.
+// Merge merges `array` into current array.
+// The parameter `array` can be any garray or slice type.
// The difference between Merge and Append is Append supports only specified slice type,
// but Merge supports more parameter types.
func (a *IntArray) Merge(array interface{}) *IntArray {
return a.Append(gconv.Ints(array)...)
}
-// Fill fills an array with num entries of the value ,
-// keys starting at the parameter.
+// Fill fills an array with num entries of the value `value`,
+// keys starting at the `startIndex` parameter.
func (a *IntArray) Fill(startIndex int, num int, value int) error {
a.mu.Lock()
defer a.mu.Unlock()
if startIndex < 0 || startIndex > len(a.array) {
- return errors.New(fmt.Sprintf("index %d out of array range %d", startIndex, len(a.array)))
+ return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", startIndex, len(a.array))
}
for i := startIndex; i < startIndex+num; i++ {
if i > len(a.array)-1 {
@@ -565,7 +570,7 @@ func (a *IntArray) Fill(startIndex int, num int, value int) error {
}
// Chunk splits an array into multiple arrays,
-// the size of each array is determined by .
+// the size of each array is determined by `size`.
// The last chunk may contain less than size elements.
func (a *IntArray) Chunk(size int) [][]int {
if size < 1 {
@@ -587,9 +592,9 @@ func (a *IntArray) Chunk(size int) [][]int {
return n
}
-// Pad pads array to the specified length with .
+// Pad pads array to the specified length with `value`.
// If size is positive then the array is padded on the right, or negative on the left.
-// If the absolute value of is less than or equal to the length of the array
+// If the absolute value of `size` is less than or equal to the length of the array
// then no padding takes place.
func (a *IntArray) Pad(size int, value int) *IntArray {
a.mu.Lock()
@@ -624,7 +629,7 @@ func (a *IntArray) Rand() (value int, found bool) {
return a.array[grand.Intn(len(a.array))], true
}
-// Rands randomly returns items from array(no deleting).
+// Rands randomly returns `size` items from array(no deleting).
func (a *IntArray) Rands(size int) []int {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -658,7 +663,7 @@ func (a *IntArray) Reverse() *IntArray {
return a
}
-// Join joins array elements with a string .
+// Join joins array elements with a string `glue`.
func (a *IntArray) Join(glue string) string {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -691,8 +696,8 @@ func (a *IntArray) Iterator(f func(k int, v int) bool) {
a.IteratorAsc(f)
}
-// IteratorAsc iterates the array readonly in ascending order with given callback function .
-// If returns true, then it continues iterating; or false to stop.
+// IteratorAsc iterates the array readonly in ascending order with given callback function `f`.
+// If `f` returns true, then it continues iterating; or false to stop.
func (a *IntArray) IteratorAsc(f func(k int, v int) bool) {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -703,8 +708,8 @@ func (a *IntArray) IteratorAsc(f func(k int, v int) bool) {
}
}
-// IteratorDesc iterates the array readonly in descending order with given callback function .
-// If returns true, then it continues iterating; or false to stop.
+// IteratorDesc iterates the array readonly in descending order with given callback function `f`.
+// If `f` returns true, then it continues iterating; or false to stop.
func (a *IntArray) IteratorDesc(f func(k int, v int) bool) {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -735,7 +740,7 @@ func (a *IntArray) UnmarshalJSON(b []byte) error {
}
a.mu.Lock()
defer a.mu.Unlock()
- if err := json.Unmarshal(b, &a.array); err != nil {
+ if err := json.UnmarshalUseNumber(b, &a.array); err != nil {
return err
}
return nil
@@ -747,7 +752,7 @@ func (a *IntArray) UnmarshalValue(value interface{}) error {
defer a.mu.Unlock()
switch value.(type) {
case string, []byte:
- return json.Unmarshal(gconv.Bytes(value), &a.array)
+ return json.UnmarshalUseNumber(gconv.Bytes(value), &a.array)
default:
a.array = gconv.SliceInt(value)
}
@@ -768,7 +773,7 @@ func (a *IntArray) FilterEmpty() *IntArray {
return a
}
-// Walk applies a user supplied function to every item of array.
+// Walk applies a user supplied function `f` to every item of array.
func (a *IntArray) Walk(f func(value int) int) *IntArray {
a.mu.Lock()
defer a.mu.Unlock()
diff --git a/container/garray/garray_normal_str.go b/container/garray/garray_normal_str.go
index 889a19a09..11cb6551b 100644
--- a/container/garray/garray_normal_str.go
+++ b/container/garray/garray_normal_str.go
@@ -1,4 +1,4 @@
-// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
+// 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,
@@ -8,8 +8,8 @@ package garray
import (
"bytes"
- "errors"
- "fmt"
+ "github.com/gogf/gf/errors/gcode"
+ "github.com/gogf/gf/errors/gerror"
"github.com/gogf/gf/internal/json"
"github.com/gogf/gf/text/gstr"
"math"
@@ -30,14 +30,14 @@ type StrArray struct {
}
// NewStrArray creates and returns an empty array.
-// The parameter is used to specify whether using array in concurrent-safety,
+// The parameter `safe` is used to specify whether using array in concurrent-safety,
// which is false in default.
func NewStrArray(safe ...bool) *StrArray {
return NewStrArraySize(0, 0, safe...)
}
// NewStrArraySize create and returns an array with given size and cap.
-// The parameter is used to specify whether using array in concurrent-safety,
+// The parameter `safe` is used to specify whether using array in concurrent-safety,
// which is false in default.
func NewStrArraySize(size int, cap int, safe ...bool) *StrArray {
return &StrArray{
@@ -46,8 +46,8 @@ func NewStrArraySize(size int, cap int, safe ...bool) *StrArray {
}
}
-// NewStrArrayFrom creates and returns an array with given slice .
-// The parameter is used to specify whether using array in concurrent-safety,
+// NewStrArrayFrom creates and returns an array with given slice `array`.
+// The parameter `safe` is used to specify whether using array in concurrent-safety,
// which is false in default.
func NewStrArrayFrom(array []string, safe ...bool) *StrArray {
return &StrArray{
@@ -56,8 +56,8 @@ func NewStrArrayFrom(array []string, safe ...bool) *StrArray {
}
}
-// NewStrArrayFromCopy creates and returns an array from a copy of given slice .
-// The parameter is used to specify whether using array in concurrent-safety,
+// NewStrArrayFromCopy creates and returns an array from a copy of given slice `array`.
+// The parameter `safe` is used to specify whether using array in concurrent-safety,
// which is false in default.
func NewStrArrayFromCopy(array []string, safe ...bool) *StrArray {
newArray := make([]string, len(array))
@@ -68,8 +68,15 @@ func NewStrArrayFromCopy(array []string, safe ...bool) *StrArray {
}
}
+// At returns the value by the specified index.
+// If the given `index` is out of range of the array, it returns an empty string.
+func (a *StrArray) At(index int) (value string) {
+ value, _ = a.Get(index)
+ return
+}
+
// Get returns the value by the specified index.
-// If the given is out of range of the array, the is false.
+// If the given `index` is out of range of the array, the `found` is false.
func (a *StrArray) Get(index int) (value string, found bool) {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -84,13 +91,13 @@ func (a *StrArray) Set(index int, value string) error {
a.mu.Lock()
defer a.mu.Unlock()
if index < 0 || index >= len(a.array) {
- return errors.New(fmt.Sprintf("index %d out of array range %d", index, len(a.array)))
+ return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", index, len(a.array))
}
a.array[index] = value
return nil
}
-// SetArray sets the underlying slice array with the given .
+// SetArray sets the underlying slice array with the given `array`.
func (a *StrArray) SetArray(array []string) *StrArray {
a.mu.Lock()
defer a.mu.Unlock()
@@ -98,7 +105,7 @@ func (a *StrArray) SetArray(array []string) *StrArray {
return a
}
-// Replace replaces the array items by given from the beginning of array.
+// Replace replaces the array items by given `array` from the beginning of array.
func (a *StrArray) Replace(array []string) *StrArray {
a.mu.Lock()
defer a.mu.Unlock()
@@ -123,17 +130,14 @@ func (a *StrArray) Sum() (sum int) {
}
// Sort sorts the array in increasing order.
-// The parameter controls whether sort
+// The parameter `reverse` controls whether sort
// in increasing order(default) or decreasing order
func (a *StrArray) Sort(reverse ...bool) *StrArray {
a.mu.Lock()
defer a.mu.Unlock()
if len(reverse) > 0 && reverse[0] {
sort.Slice(a.array, func(i, j int) bool {
- if strings.Compare(a.array[i], a.array[j]) < 0 {
- return false
- }
- return true
+ return strings.Compare(a.array[i], a.array[j]) >= 0
})
} else {
sort.Strings(a.array)
@@ -141,7 +145,7 @@ func (a *StrArray) Sort(reverse ...bool) *StrArray {
return a
}
-// SortFunc sorts the array by custom function .
+// SortFunc sorts the array by custom function `less`.
func (a *StrArray) SortFunc(less func(v1, v2 string) bool) *StrArray {
a.mu.Lock()
defer a.mu.Unlock()
@@ -151,12 +155,12 @@ func (a *StrArray) SortFunc(less func(v1, v2 string) bool) *StrArray {
return a
}
-// InsertBefore inserts the to the front of .
+// InsertBefore inserts the `value` to the front of `index`.
func (a *StrArray) InsertBefore(index int, value string) error {
a.mu.Lock()
defer a.mu.Unlock()
if index < 0 || index >= len(a.array) {
- return errors.New(fmt.Sprintf("index %d out of array range %d", index, len(a.array)))
+ return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", index, len(a.array))
}
rear := append([]string{}, a.array[index:]...)
a.array = append(a.array[0:index], value)
@@ -164,12 +168,12 @@ func (a *StrArray) InsertBefore(index int, value string) error {
return nil
}
-// InsertAfter inserts the to the back of .
+// InsertAfter inserts the `value` to the back of `index`.
func (a *StrArray) InsertAfter(index int, value string) error {
a.mu.Lock()
defer a.mu.Unlock()
if index < 0 || index >= len(a.array) {
- return errors.New(fmt.Sprintf("index %d out of array range %d", index, len(a.array)))
+ return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", index, len(a.array))
}
rear := append([]string{}, a.array[index+1:]...)
a.array = append(a.array[0:index+1], value)
@@ -178,7 +182,7 @@ func (a *StrArray) InsertAfter(index int, value string) error {
}
// Remove removes an item by index.
-// If the given is out of range of the array, the is false.
+// If the given `index` is out of range of the array, the `found` is false.
func (a *StrArray) Remove(index int) (value string, found bool) {
a.mu.Lock()
defer a.mu.Unlock()
@@ -236,7 +240,7 @@ func (a *StrArray) PushRight(value ...string) *StrArray {
}
// PopLeft pops and returns an item from the beginning of array.
-// Note that if the array is empty, the is false.
+// Note that if the array is empty, the `found` is false.
func (a *StrArray) PopLeft() (value string, found bool) {
a.mu.Lock()
defer a.mu.Unlock()
@@ -249,7 +253,7 @@ func (a *StrArray) PopLeft() (value string, found bool) {
}
// PopRight pops and returns an item from the end of array.
-// Note that if the array is empty, the is false.
+// Note that if the array is empty, the `found` is false.
func (a *StrArray) PopRight() (value string, found bool) {
a.mu.Lock()
defer a.mu.Unlock()
@@ -263,16 +267,16 @@ func (a *StrArray) PopRight() (value string, found bool) {
}
// PopRand randomly pops and return an item out of array.
-// Note that if the array is empty, the is false.
+// Note that if the array is empty, the `found` is false.
func (a *StrArray) PopRand() (value string, found bool) {
a.mu.Lock()
defer a.mu.Unlock()
return a.doRemoveWithoutLock(grand.Intn(len(a.array)))
}
-// PopRands randomly pops and returns items out of array.
-// If the given is greater than size of the array, it returns all elements of the array.
-// Note that if given <= 0 or the array is empty, it returns nil.
+// PopRands randomly pops and returns `size` items out of array.
+// If the given `size` is greater than size of the array, it returns all elements of the array.
+// Note that if given `size` <= 0 or the array is empty, it returns nil.
func (a *StrArray) PopRands(size int) []string {
a.mu.Lock()
defer a.mu.Unlock()
@@ -289,9 +293,9 @@ func (a *StrArray) PopRands(size int) []string {
return array
}
-// PopLefts pops and returns items from the beginning of array.
-// If the given is greater than size of the array, it returns all elements of the array.
-// Note that if given <= 0 or the array is empty, it returns nil.
+// PopLefts pops and returns `size` items from the beginning of array.
+// If the given `size` is greater than size of the array, it returns all elements of the array.
+// Note that if given `size` <= 0 or the array is empty, it returns nil.
func (a *StrArray) PopLefts(size int) []string {
a.mu.Lock()
defer a.mu.Unlock()
@@ -308,9 +312,9 @@ func (a *StrArray) PopLefts(size int) []string {
return value
}
-// PopRights pops and returns items from the end of array.
-// If the given is greater than size of the array, it returns all elements of the array.
-// Note that if given <= 0 or the array is empty, it returns nil.
+// PopRights pops and returns `size` items from the end of array.
+// If the given `size` is greater than size of the array, it returns all elements of the array.
+// Note that if given `size` <= 0 or the array is empty, it returns nil.
func (a *StrArray) PopRights(size int) []string {
a.mu.Lock()
defer a.mu.Unlock()
@@ -332,8 +336,8 @@ func (a *StrArray) PopRights(size int) []string {
// Notice, if in concurrent-safe usage, it returns a copy of slice;
// else a pointer to the underlying data.
//
-// If is negative, then the offset will start from the end of array.
-// If is omitted, then the sequence will have everything from start up
+// If `end` is negative, then the offset will start from the end of array.
+// If `end` is omitted, then the sequence will have everything from start up
// until the end of the array.
func (a *StrArray) Range(start int, end ...int) []string {
a.mu.RLock()
@@ -359,7 +363,7 @@ func (a *StrArray) Range(start int, end ...int) []string {
}
// SubSlice returns a slice of elements from the array as specified
-// by the and parameters.
+// by the `offset` and `size` parameters.
// If in concurrent safe usage, it returns a copy of the slice; else a pointer.
//
// If offset is non-negative, the sequence will start at that offset in the array.
@@ -408,7 +412,7 @@ func (a *StrArray) SubSlice(offset int, length ...int) []string {
}
}
-// See PushRight.
+// Append is alias of PushRight,please See PushRight.
func (a *StrArray) Append(value ...string) *StrArray {
a.mu.Lock()
a.array = append(a.array, value...)
@@ -491,7 +495,7 @@ func (a *StrArray) ContainsI(value string) bool {
return false
}
-// Search searches array by , returns the index of ,
+// Search searches array by `value`, returns the index of `value`,
// or returns -1 if not exists.
func (a *StrArray) Search(value string) int {
a.mu.RLock()
@@ -526,7 +530,7 @@ func (a *StrArray) Unique() *StrArray {
return a
}
-// LockFunc locks writing by callback function .
+// LockFunc locks writing by callback function `f`.
func (a *StrArray) LockFunc(f func(array []string)) *StrArray {
a.mu.Lock()
defer a.mu.Unlock()
@@ -534,7 +538,7 @@ func (a *StrArray) LockFunc(f func(array []string)) *StrArray {
return a
}
-// RLockFunc locks reading by callback function .
+// RLockFunc locks reading by callback function `f`.
func (a *StrArray) RLockFunc(f func(array []string)) *StrArray {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -542,21 +546,21 @@ func (a *StrArray) RLockFunc(f func(array []string)) *StrArray {
return a
}
-// Merge merges into current array.
-// The parameter can be any garray or slice type.
+// Merge merges `array` into current array.
+// The parameter `array` can be any garray or slice type.
// The difference between Merge and Append is Append supports only specified slice type,
// but Merge supports more parameter types.
func (a *StrArray) Merge(array interface{}) *StrArray {
return a.Append(gconv.Strings(array)...)
}
-// Fill fills an array with num entries of the value ,
-// keys starting at the parameter.
+// Fill fills an array with num entries of the value `value`,
+// keys starting at the `startIndex` parameter.
func (a *StrArray) Fill(startIndex int, num int, value string) error {
a.mu.Lock()
defer a.mu.Unlock()
if startIndex < 0 || startIndex > len(a.array) {
- return errors.New(fmt.Sprintf("index %d out of array range %d", startIndex, len(a.array)))
+ return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", startIndex, len(a.array))
}
for i := startIndex; i < startIndex+num; i++ {
if i > len(a.array)-1 {
@@ -569,7 +573,7 @@ func (a *StrArray) Fill(startIndex int, num int, value string) error {
}
// Chunk splits an array into multiple arrays,
-// the size of each array is determined by .
+// the size of each array is determined by `size`.
// The last chunk may contain less than size elements.
func (a *StrArray) Chunk(size int) [][]string {
if size < 1 {
@@ -591,9 +595,9 @@ func (a *StrArray) Chunk(size int) [][]string {
return n
}
-// Pad pads array to the specified length with .
+// Pad pads array to the specified length with `value`.
// If size is positive then the array is padded on the right, or negative on the left.
-// If the absolute value of is less than or equal to the length of the array
+// If the absolute value of `size` is less than or equal to the length of the array
// then no padding takes place.
func (a *StrArray) Pad(size int, value string) *StrArray {
a.mu.Lock()
@@ -628,7 +632,7 @@ func (a *StrArray) Rand() (value string, found bool) {
return a.array[grand.Intn(len(a.array))], true
}
-// Rands randomly returns items from array(no deleting).
+// Rands randomly returns `size` items from array(no deleting).
func (a *StrArray) Rands(size int) []string {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -662,7 +666,7 @@ func (a *StrArray) Reverse() *StrArray {
return a
}
-// Join joins array elements with a string .
+// Join joins array elements with a string `glue`.
func (a *StrArray) Join(glue string) string {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -695,8 +699,8 @@ func (a *StrArray) Iterator(f func(k int, v string) bool) {
a.IteratorAsc(f)
}
-// IteratorAsc iterates the array readonly in ascending order with given callback function .
-// If returns true, then it continues iterating; or false to stop.
+// IteratorAsc iterates the array readonly in ascending order with given callback function `f`.
+// If `f` returns true, then it continues iterating; or false to stop.
func (a *StrArray) IteratorAsc(f func(k int, v string) bool) {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -707,8 +711,8 @@ func (a *StrArray) IteratorAsc(f func(k int, v string) bool) {
}
}
-// IteratorDesc iterates the array readonly in descending order with given callback function .
-// If returns true, then it continues iterating; or false to stop.
+// IteratorDesc iterates the array readonly in descending order with given callback function `f`.
+// If `f` returns true, then it continues iterating; or false to stop.
func (a *StrArray) IteratorDesc(f func(k int, v string) bool) {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -750,7 +754,7 @@ func (a *StrArray) UnmarshalJSON(b []byte) error {
}
a.mu.Lock()
defer a.mu.Unlock()
- if err := json.Unmarshal(b, &a.array); err != nil {
+ if err := json.UnmarshalUseNumber(b, &a.array); err != nil {
return err
}
return nil
@@ -762,7 +766,7 @@ func (a *StrArray) UnmarshalValue(value interface{}) error {
defer a.mu.Unlock()
switch value.(type) {
case string, []byte:
- return json.Unmarshal(gconv.Bytes(value), &a.array)
+ return json.UnmarshalUseNumber(gconv.Bytes(value), &a.array)
default:
a.array = gconv.SliceStr(value)
}
@@ -783,7 +787,7 @@ func (a *StrArray) FilterEmpty() *StrArray {
return a
}
-// Walk applies a user supplied function to every item of array.
+// Walk applies a user supplied function `f` to every item of array.
func (a *StrArray) Walk(f func(value string) string) *StrArray {
a.mu.Lock()
defer a.mu.Unlock()
diff --git a/container/garray/garray_sorted_any.go b/container/garray/garray_sorted_any.go
index 3122be023..f120809a5 100644
--- a/container/garray/garray_sorted_any.go
+++ b/container/garray/garray_sorted_any.go
@@ -1,4 +1,4 @@
-// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
+// 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,
@@ -34,8 +34,8 @@ type SortedArray struct {
}
// NewSortedArray creates and returns an empty sorted array.
-// The parameter is used to specify whether using array in concurrent-safety, which is false in default.
-// The parameter used to compare values to sort in array,
+// The parameter `safe` is used to specify whether using array in concurrent-safety, which is false in default.
+// The parameter `comparator` used to compare values to sort in array,
// if it returns value < 0, means v1 < v2; the v1 will be inserted before v2;
// if it returns value = 0, means v1 = v2; the v1 will be replaced by v2;
// if it returns value > 0, means v1 > v2; the v1 will be inserted after v2;
@@ -44,7 +44,7 @@ func NewSortedArray(comparator func(a, b interface{}) int, safe ...bool) *Sorted
}
// NewSortedArraySize create and returns an sorted array with given size and cap.
-// The parameter is used to specify whether using array in concurrent-safety,
+// The parameter `safe` is used to specify whether using array in concurrent-safety,
// which is false in default.
func NewSortedArraySize(cap int, comparator func(a, b interface{}) int, safe ...bool) *SortedArray {
return &SortedArray{
@@ -54,8 +54,8 @@ func NewSortedArraySize(cap int, comparator func(a, b interface{}) int, safe ...
}
}
-// NewSortedArrayRange creates and returns a array by a range from to
-// with step value .
+// NewSortedArrayRange creates and returns a array by a range from `start` to `end`
+// with step value `step`.
func NewSortedArrayRange(start, end, step int, comparator func(a, b interface{}) int, safe ...bool) *SortedArray {
if step == 0 {
panic(fmt.Sprintf(`invalid step value: %d`, step))
@@ -69,8 +69,8 @@ func NewSortedArrayRange(start, end, step int, comparator func(a, b interface{})
return NewSortedArrayFrom(slice, comparator, safe...)
}
-// NewSortedArrayFrom creates and returns an sorted array with given slice .
-// The parameter is used to specify whether using array in concurrent-safety,
+// NewSortedArrayFrom creates and returns an sorted array with given slice `array`.
+// The parameter `safe` is used to specify whether using array in concurrent-safety,
// which is false in default.
func NewSortedArrayFrom(array []interface{}, comparator func(a, b interface{}) int, safe ...bool) *SortedArray {
a := NewSortedArraySize(0, comparator, safe...)
@@ -81,8 +81,8 @@ func NewSortedArrayFrom(array []interface{}, comparator func(a, b interface{}) i
return a
}
-// NewSortedArrayFromCopy creates and returns an sorted array from a copy of given slice .
-// The parameter is used to specify whether using array in concurrent-safety,
+// NewSortedArrayFromCopy creates and returns an sorted array from a copy of given slice `array`.
+// The parameter `safe` is used to specify whether using array in concurrent-safety,
// which is false in default.
func NewSortedArrayFromCopy(array []interface{}, comparator func(a, b interface{}) int, safe ...bool) *SortedArray {
newArray := make([]interface{}, len(array))
@@ -90,7 +90,14 @@ func NewSortedArrayFromCopy(array []interface{}, comparator func(a, b interface{
return NewSortedArrayFrom(newArray, comparator, safe...)
}
-// SetArray sets the underlying slice array with the given .
+// At returns the value by the specified index.
+// If the given `index` is out of range of the array, it returns `nil`.
+func (a *SortedArray) At(index int) (value interface{}) {
+ value, _ = a.Get(index)
+ return
+}
+
+// SetArray sets the underlying slice array with the given `array`.
func (a *SortedArray) SetArray(array []interface{}) *SortedArray {
a.mu.Lock()
defer a.mu.Unlock()
@@ -113,7 +120,7 @@ func (a *SortedArray) SetComparator(comparator func(a, b interface{}) int) {
}
// Sort sorts the array in increasing order.
-// The parameter controls whether sort
+// The parameter `reverse` controls whether sort
// in increasing order(default) or decreasing order
func (a *SortedArray) Sort() *SortedArray {
a.mu.Lock()
@@ -149,15 +156,13 @@ func (a *SortedArray) Append(values ...interface{}) *SortedArray {
if cmp > 0 {
index++
}
- rear := append([]interface{}{}, a.array[index:]...)
- a.array = append(a.array[0:index], value)
- a.array = append(a.array, rear...)
+ a.array = append(a.array[:index], append([]interface{}{value}, a.array[index:]...)...)
}
return a
}
// Get returns the value by the specified index.
-// If the given is out of range of the array, the is false.
+// If the given `index` is out of range of the array, the `found` is false.
func (a *SortedArray) Get(index int) (value interface{}, found bool) {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -168,7 +173,7 @@ func (a *SortedArray) Get(index int) (value interface{}, found bool) {
}
// Remove removes an item by index.
-// If the given is out of range of the array, the is false.
+// If the given `index` is out of range of the array, the `found` is false.
func (a *SortedArray) Remove(index int) (value interface{}, found bool) {
a.mu.Lock()
defer a.mu.Unlock()
@@ -209,7 +214,7 @@ func (a *SortedArray) RemoveValue(value interface{}) bool {
}
// PopLeft pops and returns an item from the beginning of array.
-// Note that if the array is empty, the is false.
+// Note that if the array is empty, the `found` is false.
func (a *SortedArray) PopLeft() (value interface{}, found bool) {
a.mu.Lock()
defer a.mu.Unlock()
@@ -222,7 +227,7 @@ func (a *SortedArray) PopLeft() (value interface{}, found bool) {
}
// PopRight pops and returns an item from the end of array.
-// Note that if the array is empty, the is false.
+// Note that if the array is empty, the `found` is false.
func (a *SortedArray) PopRight() (value interface{}, found bool) {
a.mu.Lock()
defer a.mu.Unlock()
@@ -236,14 +241,14 @@ func (a *SortedArray) PopRight() (value interface{}, found bool) {
}
// PopRand randomly pops and return an item out of array.
-// Note that if the array is empty, the is false.
+// Note that if the array is empty, the `found` is false.
func (a *SortedArray) PopRand() (value interface{}, found bool) {
a.mu.Lock()
defer a.mu.Unlock()
return a.doRemoveWithoutLock(grand.Intn(len(a.array)))
}
-// PopRands randomly pops and returns items out of array.
+// PopRands randomly pops and returns `size` items out of array.
func (a *SortedArray) PopRands(size int) []interface{} {
a.mu.Lock()
defer a.mu.Unlock()
@@ -260,7 +265,7 @@ func (a *SortedArray) PopRands(size int) []interface{} {
return array
}
-// PopLefts pops and returns items from the beginning of array.
+// PopLefts pops and returns `size` items from the beginning of array.
func (a *SortedArray) PopLefts(size int) []interface{} {
a.mu.Lock()
defer a.mu.Unlock()
@@ -277,7 +282,7 @@ func (a *SortedArray) PopLefts(size int) []interface{} {
return value
}
-// PopRights pops and returns items from the end of array.
+// PopRights pops and returns `size` items from the end of array.
func (a *SortedArray) PopRights(size int) []interface{} {
a.mu.Lock()
defer a.mu.Unlock()
@@ -299,8 +304,8 @@ func (a *SortedArray) PopRights(size int) []interface{} {
// Notice, if in concurrent-safe usage, it returns a copy of slice;
// else a pointer to the underlying data.
//
-// If is negative, then the offset will start from the end of array.
-// If is omitted, then the sequence will have everything from start up
+// If `end` is negative, then the offset will start from the end of array.
+// If `end` is omitted, then the sequence will have everything from start up
// until the end of the array.
func (a *SortedArray) Range(start int, end ...int) []interface{} {
a.mu.RLock()
@@ -326,7 +331,7 @@ func (a *SortedArray) Range(start int, end ...int) []interface{} {
}
// SubSlice returns a slice of elements from the array as specified
-// by the and parameters.
+// by the `offset` and `size` parameters.
// If in concurrent safe usage, it returns a copy of the slice; else a pointer.
//
// If offset is non-negative, the sequence will start at that offset in the array.
@@ -419,7 +424,7 @@ func (a *SortedArray) Contains(value interface{}) bool {
return a.Search(value) != -1
}
-// Search searches array by , returns the index of ,
+// Search searches array by `value`, returns the index of `value`,
// or returns -1 if not exists.
func (a *SortedArray) Search(value interface{}) (index int) {
if i, r := a.binSearch(value, true); r == 0 {
@@ -430,9 +435,9 @@ func (a *SortedArray) Search(value interface{}) (index int) {
// Binary search.
// It returns the last compared index and the result.
-// If equals to 0, it means the value at is equals to .
-// If lesser than 0, it means the value at is lesser than .
-// If greater than 0, it means the value at is greater than .
+// If `result` equals to 0, it means the value at `index` is equals to `value`.
+// If `result` lesser than 0, it means the value at `index` is lesser than `value`.
+// If `result` greater than 0, it means the value at `index` is greater than `value`.
func (a *SortedArray) binSearch(value interface{}, lock bool) (index int, result int) {
if lock {
a.mu.RLock()
@@ -446,7 +451,7 @@ func (a *SortedArray) binSearch(value interface{}, lock bool) (index int, result
mid := 0
cmp := -2
for min <= max {
- mid = min + int((max-min)/2)
+ mid = min + (max-min)/2
cmp = a.getComparator()(value, a.array[mid])
switch {
case cmp < 0:
@@ -512,7 +517,7 @@ func (a *SortedArray) Clear() *SortedArray {
return a
}
-// LockFunc locks writing by callback function .
+// LockFunc locks writing by callback function `f`.
func (a *SortedArray) LockFunc(f func(array []interface{})) *SortedArray {
a.mu.Lock()
defer a.mu.Unlock()
@@ -526,7 +531,7 @@ func (a *SortedArray) LockFunc(f func(array []interface{})) *SortedArray {
return a
}
-// RLockFunc locks reading by callback function .
+// RLockFunc locks reading by callback function `f`.
func (a *SortedArray) RLockFunc(f func(array []interface{})) *SortedArray {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -534,8 +539,8 @@ func (a *SortedArray) RLockFunc(f func(array []interface{})) *SortedArray {
return a
}
-// Merge merges into current array.
-// The parameter can be any garray or slice type.
+// Merge merges `array` into current array.
+// The parameter `array` can be any garray or slice type.
// The difference between Merge and Append is Append supports only specified slice type,
// but Merge supports more parameter types.
func (a *SortedArray) Merge(array interface{}) *SortedArray {
@@ -543,7 +548,7 @@ func (a *SortedArray) Merge(array interface{}) *SortedArray {
}
// Chunk splits an array into multiple arrays,
-// the size of each array is determined by .
+// the size of each array is determined by `size`.
// The last chunk may contain less than size elements.
func (a *SortedArray) Chunk(size int) [][]interface{} {
if size < 1 {
@@ -575,7 +580,7 @@ func (a *SortedArray) Rand() (value interface{}, found bool) {
return a.array[grand.Intn(len(a.array))], true
}
-// Rands randomly returns items from array(no deleting).
+// Rands randomly returns `size` items from array(no deleting).
func (a *SortedArray) Rands(size int) []interface{} {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -589,7 +594,7 @@ func (a *SortedArray) Rands(size int) []interface{} {
return array
}
-// Join joins array elements with a string .
+// Join joins array elements with a string `glue`.
func (a *SortedArray) Join(glue string) string {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -622,8 +627,8 @@ func (a *SortedArray) Iterator(f func(k int, v interface{}) bool) {
a.IteratorAsc(f)
}
-// IteratorAsc iterates the array readonly in ascending order with given callback function .
-// If returns true, then it continues iterating; or false to stop.
+// IteratorAsc iterates the array readonly in ascending order with given callback function `f`.
+// If `f` returns true, then it continues iterating; or false to stop.
func (a *SortedArray) IteratorAsc(f func(k int, v interface{}) bool) {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -634,8 +639,8 @@ func (a *SortedArray) IteratorAsc(f func(k int, v interface{}) bool) {
}
}
-// IteratorDesc iterates the array readonly in descending order with given callback function .
-// If returns true, then it continues iterating; or false to stop.
+// IteratorDesc iterates the array readonly in descending order with given callback function `f`.
+// If `f` returns true, then it continues iterating; or false to stop.
func (a *SortedArray) IteratorDesc(f func(k int, v interface{}) bool) {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -685,7 +690,7 @@ func (a *SortedArray) UnmarshalJSON(b []byte) error {
}
a.mu.Lock()
defer a.mu.Unlock()
- if err := json.Unmarshal(b, &a.array); err != nil {
+ if err := json.UnmarshalUseNumber(b, &a.array); err != nil {
return err
}
if a.comparator != nil && a.array != nil {
@@ -706,7 +711,7 @@ func (a *SortedArray) UnmarshalValue(value interface{}) (err error) {
defer a.mu.Unlock()
switch value.(type) {
case string, []byte:
- err = json.Unmarshal(gconv.Bytes(value), &a.array)
+ err = json.UnmarshalUseNumber(gconv.Bytes(value), &a.array)
default:
a.array = gconv.SliceAny(value)
}
@@ -761,7 +766,7 @@ func (a *SortedArray) FilterEmpty() *SortedArray {
return a
}
-// Walk applies a user supplied function to every item of array.
+// Walk applies a user supplied function `f` to every item of array.
func (a *SortedArray) Walk(f func(value interface{}) interface{}) *SortedArray {
a.mu.Lock()
defer a.mu.Unlock()
diff --git a/container/garray/garray_sorted_int.go b/container/garray/garray_sorted_int.go
index fa44ed534..f250d989c 100644
--- a/container/garray/garray_sorted_int.go
+++ b/container/garray/garray_sorted_int.go
@@ -1,4 +1,4 @@
-// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
+// 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,
@@ -31,14 +31,14 @@ type SortedIntArray struct {
}
// NewSortedIntArray creates and returns an empty sorted array.
-// The parameter is used to specify whether using array in concurrent-safety,
+// The parameter `safe` is used to specify whether using array in concurrent-safety,
// which is false in default.
func NewSortedIntArray(safe ...bool) *SortedIntArray {
return NewSortedIntArraySize(0, safe...)
}
// NewSortedIntArrayComparator creates and returns an empty sorted array with specified comparator.
-// The parameter is used to specify whether using array in concurrent-safety which is false in default.
+// The parameter `safe` is used to specify whether using array in concurrent-safety which is false in default.
func NewSortedIntArrayComparator(comparator func(a, b int) int, safe ...bool) *SortedIntArray {
array := NewSortedIntArray(safe...)
array.comparator = comparator
@@ -46,7 +46,7 @@ func NewSortedIntArrayComparator(comparator func(a, b int) int, safe ...bool) *S
}
// NewSortedIntArraySize create and returns an sorted array with given size and cap.
-// The parameter is used to specify whether using array in concurrent-safety,
+// The parameter `safe` is used to specify whether using array in concurrent-safety,
// which is false in default.
func NewSortedIntArraySize(cap int, safe ...bool) *SortedIntArray {
return &SortedIntArray{
@@ -56,8 +56,8 @@ func NewSortedIntArraySize(cap int, safe ...bool) *SortedIntArray {
}
}
-// NewSortedIntArrayRange creates and returns a array by a range from to
-// with step value .
+// NewSortedIntArrayRange creates and returns a array by a range from `start` to `end`
+// with step value `step`.
func NewSortedIntArrayRange(start, end, step int, safe ...bool) *SortedIntArray {
if step == 0 {
panic(fmt.Sprintf(`invalid step value: %d`, step))
@@ -71,8 +71,8 @@ func NewSortedIntArrayRange(start, end, step int, safe ...bool) *SortedIntArray
return NewSortedIntArrayFrom(slice, safe...)
}
-// NewIntArrayFrom creates and returns an sorted array with given slice .
-// The parameter is used to specify whether using array in concurrent-safety,
+// NewSortedIntArrayFrom creates and returns an sorted array with given slice `array`.
+// The parameter `safe` is used to specify whether using array in concurrent-safety,
// which is false in default.
func NewSortedIntArrayFrom(array []int, safe ...bool) *SortedIntArray {
a := NewSortedIntArraySize(0, safe...)
@@ -81,8 +81,8 @@ func NewSortedIntArrayFrom(array []int, safe ...bool) *SortedIntArray {
return a
}
-// NewSortedIntArrayFromCopy creates and returns an sorted array from a copy of given slice .
-// The parameter is used to specify whether using array in concurrent-safety,
+// NewSortedIntArrayFromCopy creates and returns an sorted array from a copy of given slice `array`.
+// The parameter `safe` is used to specify whether using array in concurrent-safety,
// which is false in default.
func NewSortedIntArrayFromCopy(array []int, safe ...bool) *SortedIntArray {
newArray := make([]int, len(array))
@@ -90,7 +90,14 @@ func NewSortedIntArrayFromCopy(array []int, safe ...bool) *SortedIntArray {
return NewSortedIntArrayFrom(newArray, safe...)
}
-// SetArray sets the underlying slice array with the given .
+// At returns the value by the specified index.
+// If the given `index` is out of range of the array, it returns `0`.
+func (a *SortedIntArray) At(index int) (value int) {
+ value, _ = a.Get(index)
+ return
+}
+
+// SetArray sets the underlying slice array with the given `array`.
func (a *SortedIntArray) SetArray(array []int) *SortedIntArray {
a.mu.Lock()
defer a.mu.Unlock()
@@ -100,7 +107,7 @@ func (a *SortedIntArray) SetArray(array []int) *SortedIntArray {
}
// Sort sorts the array in increasing order.
-// The parameter controls whether sort
+// The parameter `reverse` controls whether sort
// in increasing order(default) or decreasing order.
func (a *SortedIntArray) Sort() *SortedIntArray {
a.mu.Lock()
@@ -142,7 +149,7 @@ func (a *SortedIntArray) Append(values ...int) *SortedIntArray {
}
// Get returns the value by the specified index.
-// If the given is out of range of the array, the is false.
+// If the given `index` is out of range of the array, the `found` is false.
func (a *SortedIntArray) Get(index int) (value int, found bool) {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -153,7 +160,7 @@ func (a *SortedIntArray) Get(index int) (value int, found bool) {
}
// Remove removes an item by index.
-// If the given is out of range of the array, the is false.
+// If the given `index` is out of range of the array, the `found` is false.
func (a *SortedIntArray) Remove(index int) (value int, found bool) {
a.mu.Lock()
defer a.mu.Unlock()
@@ -194,7 +201,7 @@ func (a *SortedIntArray) RemoveValue(value int) bool {
}
// PopLeft pops and returns an item from the beginning of array.
-// Note that if the array is empty, the is false.
+// Note that if the array is empty, the `found` is false.
func (a *SortedIntArray) PopLeft() (value int, found bool) {
a.mu.Lock()
defer a.mu.Unlock()
@@ -207,7 +214,7 @@ func (a *SortedIntArray) PopLeft() (value int, found bool) {
}
// PopRight pops and returns an item from the end of array.
-// Note that if the array is empty, the is false.
+// Note that if the array is empty, the `found` is false.
func (a *SortedIntArray) PopRight() (value int, found bool) {
a.mu.Lock()
defer a.mu.Unlock()
@@ -221,16 +228,16 @@ func (a *SortedIntArray) PopRight() (value int, found bool) {
}
// PopRand randomly pops and return an item out of array.
-// Note that if the array is empty, the is false.
+// Note that if the array is empty, the `found` is false.
func (a *SortedIntArray) PopRand() (value int, found bool) {
a.mu.Lock()
defer a.mu.Unlock()
return a.doRemoveWithoutLock(grand.Intn(len(a.array)))
}
-// PopRands randomly pops and returns items out of array.
-// If the given is greater than size of the array, it returns all elements of the array.
-// Note that if given <= 0 or the array is empty, it returns nil.
+// PopRands randomly pops and returns `size` items out of array.
+// If the given `size` is greater than size of the array, it returns all elements of the array.
+// Note that if given `size` <= 0 or the array is empty, it returns nil.
func (a *SortedIntArray) PopRands(size int) []int {
a.mu.Lock()
defer a.mu.Unlock()
@@ -247,9 +254,9 @@ func (a *SortedIntArray) PopRands(size int) []int {
return array
}
-// PopLefts pops and returns items from the beginning of array.
-// If the given is greater than size of the array, it returns all elements of the array.
-// Note that if given <= 0 or the array is empty, it returns nil.
+// PopLefts pops and returns `size` items from the beginning of array.
+// If the given `size` is greater than size of the array, it returns all elements of the array.
+// Note that if given `size` <= 0 or the array is empty, it returns nil.
func (a *SortedIntArray) PopLefts(size int) []int {
a.mu.Lock()
defer a.mu.Unlock()
@@ -266,9 +273,9 @@ func (a *SortedIntArray) PopLefts(size int) []int {
return value
}
-// PopRights pops and returns items from the end of array.
-// If the given is greater than size of the array, it returns all elements of the array.
-// Note that if given <= 0 or the array is empty, it returns nil.
+// PopRights pops and returns `size` items from the end of array.
+// If the given `size` is greater than size of the array, it returns all elements of the array.
+// Note that if given `size` <= 0 or the array is empty, it returns nil.
func (a *SortedIntArray) PopRights(size int) []int {
a.mu.Lock()
defer a.mu.Unlock()
@@ -290,8 +297,8 @@ func (a *SortedIntArray) PopRights(size int) []int {
// Notice, if in concurrent-safe usage, it returns a copy of slice;
// else a pointer to the underlying data.
//
-// If is negative, then the offset will start from the end of array.
-// If is omitted, then the sequence will have everything from start up
+// If `end` is negative, then the offset will start from the end of array.
+// If `end` is omitted, then the sequence will have everything from start up
// until the end of the array.
func (a *SortedIntArray) Range(start int, end ...int) []int {
a.mu.RLock()
@@ -317,7 +324,7 @@ func (a *SortedIntArray) Range(start int, end ...int) []int {
}
// SubSlice returns a slice of elements from the array as specified
-// by the and parameters.
+// by the `offset` and `size` parameters.
// If in concurrent safe usage, it returns a copy of the slice; else a pointer.
//
// If offset is non-negative, the sequence will start at that offset in the array.
@@ -416,7 +423,7 @@ func (a *SortedIntArray) Contains(value int) bool {
return a.Search(value) != -1
}
-// Search searches array by , returns the index of ,
+// Search searches array by `value`, returns the index of `value`,
// or returns -1 if not exists.
func (a *SortedIntArray) Search(value int) (index int) {
if i, r := a.binSearch(value, true); r == 0 {
@@ -427,9 +434,9 @@ func (a *SortedIntArray) Search(value int) (index int) {
// Binary search.
// It returns the last compared index and the result.
-// If equals to 0, it means the value at is equals to .
-// If lesser than 0, it means the value at is lesser than .
-// If greater than 0, it means the value at is greater than .
+// If `result` equals to 0, it means the value at `index` is equals to `value`.
+// If `result` lesser than 0, it means the value at `index` is lesser than `value`.
+// If `result` greater than 0, it means the value at `index` is greater than `value`.
func (a *SortedIntArray) binSearch(value int, lock bool) (index int, result int) {
if lock {
a.mu.RLock()
@@ -509,7 +516,7 @@ func (a *SortedIntArray) Clear() *SortedIntArray {
return a
}
-// LockFunc locks writing by callback function .
+// LockFunc locks writing by callback function `f`.
func (a *SortedIntArray) LockFunc(f func(array []int)) *SortedIntArray {
a.mu.Lock()
defer a.mu.Unlock()
@@ -517,7 +524,7 @@ func (a *SortedIntArray) LockFunc(f func(array []int)) *SortedIntArray {
return a
}
-// RLockFunc locks reading by callback function .
+// RLockFunc locks reading by callback function `f`.
func (a *SortedIntArray) RLockFunc(f func(array []int)) *SortedIntArray {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -525,8 +532,8 @@ func (a *SortedIntArray) RLockFunc(f func(array []int)) *SortedIntArray {
return a
}
-// Merge merges into current array.
-// The parameter can be any garray or slice type.
+// Merge merges `array` into current array.
+// The parameter `array` can be any garray or slice type.
// The difference between Merge and Append is Append supports only specified slice type,
// but Merge supports more parameter types.
func (a *SortedIntArray) Merge(array interface{}) *SortedIntArray {
@@ -534,7 +541,7 @@ func (a *SortedIntArray) Merge(array interface{}) *SortedIntArray {
}
// Chunk splits an array into multiple arrays,
-// the size of each array is determined by .
+// the size of each array is determined by `size`.
// The last chunk may contain less than size elements.
func (a *SortedIntArray) Chunk(size int) [][]int {
if size < 1 {
@@ -566,7 +573,7 @@ func (a *SortedIntArray) Rand() (value int, found bool) {
return a.array[grand.Intn(len(a.array))], true
}
-// Rands randomly returns items from array(no deleting).
+// Rands randomly returns `size` items from array(no deleting).
func (a *SortedIntArray) Rands(size int) []int {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -580,7 +587,7 @@ func (a *SortedIntArray) Rands(size int) []int {
return array
}
-// Join joins array elements with a string