fix merge conflicts for gdb_driver_pgsql

This commit is contained in:
imloama
2021-06-08 09:20:22 +08:00
275 changed files with 8406 additions and 4132 deletions

View File

@ -1,12 +1,7 @@
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package 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),

View File

@ -0,0 +1,9 @@
package main
import (
"github.com/gogf/gf/frame/g"
)
func main() {
g.DB().Model("user").Distinct().CountColumn("uid,name")
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1 +1,3 @@
OrderPaid = "您已成功完成订单号 #%d 支付,支付金额¥%.2f。"
OrderPaid = "您已成功完成订单号 #%d 支付,支付金额¥%.2f。"
hello = "你好"
world = "世界"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,14 @@
# MySQL.
[database]
[database.default]
link = "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
debug = true

View File

@ -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:两次密码输入不相等]]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,14 +0,0 @@
"gf.gvalid.required" = "字段不能为空"

View File

@ -0,0 +1,7 @@
"gf.gvalid.required" = "字段不能为空"
"ReuiredUserName" = "Please input user name"
"ReuiredUserType" = "Please select user type"
"MustSize" = "Size of :attribute must be :size"

View File

@ -0,0 +1,16 @@
"gf.gvalid.required" = "字段不能为空"
"ReuiredUserName" = "请输入用户名称"
"ReuiredUserType" = "请选择用户类型"
"MustSize" = ":attribute长度必须为:size"

View File

@ -1,4 +1,7 @@
<!-- 为高效率地交流并解决问题请按照以下模板提交issue感谢 -->
<!-- 为高效处理您的疑问如果觉得是BUG类问题请您务必提供可复现该问题的最小可运行代码 -->
<!-- 为高效处理您的疑问如果觉得是BUG类问题请您务必提供可复现该问题的最小可运行代码 -->
<!-- 为高效处理您的疑问如果觉得是BUG类问题请您务必提供可复现该问题的最小可运行代码 -->
<!-- 重要的事情说三遍! -->
### 1. 您当前使用的`Go`版本,及系统版本、系统架构?

View File

@ -1,5 +1,10 @@
<!-- Please answer these questions before submitting your issue. Thanks! -->
<!-- 为高效处理您的疑问如果觉得是BUG类问题请您务必提供可复现该问题的最小可运行代码 -->
<!-- 为高效处理您的疑问如果觉得是BUG类问题请您务必提供可复现该问题的最小可运行代码 -->
<!-- 为高效处理您的疑问如果觉得是BUG类问题请您务必提供可复现该问题的最小可运行代码 -->
<!-- 重要的事情说三遍! -->
### 1. What version of `Go` and system type/arch are you using?
<!--
@ -13,7 +18,7 @@ What expect to see is like: `go 1.12, linux/amd64`
<!-- You can find the GF version from your `go.mod`, or from the `version.go` in `GF` -->
### 3. Can this issue be reproduced with the latest release?
### 3. Can this issue be re-produced with the latest release?

View File

@ -50,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 GroupAdd friend`389961817` in WeChat, commenting `GF`
- Issueshttps://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.

View File

@ -13,14 +13,16 @@
> 如果您初识`Go`语言,您可以将`GoFrame`类似于`PHP`中的`Laravel`, `Java`中的`SpringBoot`或者`Python`中的`Django`。
# 特点
* 模块化、松耦合设计;
* 模块丰富、开箱即用
* 简便易用、易于维护;
* 高代码质量、高单元测试覆盖率;
* 社区活跃,大牛谦逊低调脾气好;
* 详尽的开发文档及示例;
* 完善的本地中文化支持;
* 设计为团队及企业使用;
* 模块化、松耦合
* 模块丰富、开箱即用
* 简洁易用、快速接入
* 文档详尽、易于维护
* 自顶向下、体系化设计
* 统一框架、统一组件、降低选择成本
* 开发规范、设计模式、代码分层模型
* 强大便捷的开发工具链
* 完善的本地中文化支持
* 设计为团队及企业使用
# 地址
- **主库**https://github.com/gogf/gf
@ -63,16 +65,10 @@ golang版本 >= 1.11
# 文档
开发文档: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`
- 主库ISSUEhttps://github.com/gogf/gf/issues
> 建议通过阅读`GoFrame`的源码以及API文档深度学习`GoFrame`,了解更多的精妙设计。
# 协议

View File

@ -30,7 +30,7 @@ type Array struct {
}
// New creates and returns an empty array.
// The parameter <safe> 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...)
@ -42,7 +42,7 @@ func NewArray(safe ...bool) *Array {
}
// NewArraySize create and returns an array with given size and cap.
// The parameter <safe> 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 +51,8 @@ func NewArraySize(size int, cap int, safe ...bool) *Array {
}
}
// NewArrayRange creates and returns a array by a range from <start> to <end>
// with step value <step>.
// 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 +66,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 <array>.
// The parameter <safe> 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 +88,8 @@ func NewArrayFrom(array []interface{}, safe ...bool) *Array {
}
}
// 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,
// 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 +100,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 <index> is out of range of the array, the <found> 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()
@ -120,7 +129,7 @@ func (a *Array) Set(index int, value interface{}) error {
return nil
}
// SetArray sets the underlying slice array with the given <array>.
// 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 +137,7 @@ func (a *Array) SetArray(array []interface{}) *Array {
return a
}
// Replace replaces the array items by given <array> 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 +161,7 @@ func (a *Array) Sum() (sum int) {
return
}
// SortFunc sorts the array by custom function <less>.
// 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,7 +171,7 @@ func (a *Array) SortFunc(less func(v1, v2 interface{}) bool) *Array {
return a
}
// InsertBefore inserts the <value> to the front of <index>.
// 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()
@ -175,7 +184,7 @@ func (a *Array) InsertBefore(index int, value interface{}) error {
return nil
}
// InsertAfter inserts the <value> to the back of <index>.
// 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()
@ -189,7 +198,7 @@ func (a *Array) InsertAfter(index int, value interface{}) error {
}
// Remove removes an item by index.
// If the given <index> is out of range of the array, the <found> 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 +256,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 <found> 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 <size> 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 +281,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 <found> 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 +294,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 <found> 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 +307,7 @@ func (a *Array) PopRight() (value interface{}, found bool) {
return value, true
}
// PopLefts pops and returns <size> 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 +324,7 @@ func (a *Array) PopLefts(size int) []interface{} {
return value
}
// PopRights pops and returns <size> 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 +346,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 <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
// 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 +373,7 @@ func (a *Array) Range(start int, end ...int) []interface{} {
}
// SubSlice returns a slice of elements from the array as specified
// by the <offset> and <size> 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.
@ -471,7 +480,7 @@ func (a *Array) Contains(value interface{}) bool {
return a.Search(value) != -1
}
// Search searches array by <value>, returns the index of <value>,
// 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 +515,7 @@ func (a *Array) Unique() *Array {
return a
}
// LockFunc locks writing by callback function <f>.
// 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 +523,7 @@ func (a *Array) LockFunc(f func(array []interface{})) *Array {
return a
}
// RLockFunc locks reading by callback function <f>.
// RLockFunc locks reading by callback function `f`.
func (a *Array) RLockFunc(f func(array []interface{})) *Array {
a.mu.RLock()
defer a.mu.RUnlock()
@ -522,16 +531,16 @@ func (a *Array) RLockFunc(f func(array []interface{})) *Array {
return a
}
// Merge merges <array> into current array.
// The parameter <array> 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 <value>,
// keys starting at the <startIndex> 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()
@ -549,7 +558,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 <size>.
// 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 +580,9 @@ func (a *Array) Chunk(size int) [][]interface{} {
return n
}
// Pad pads array to the specified length with <value>.
// 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 <size> 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 +617,7 @@ func (a *Array) Rand() (value interface{}, found bool) {
return a.array[grand.Intn(len(a.array))], true
}
// Rands randomly returns <size> 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 +651,7 @@ func (a *Array) Reverse() *Array {
return a
}
// Join joins array elements with a string <glue>.
// Join joins array elements with a string `glue`.
func (a *Array) Join(glue string) string {
a.mu.RLock()
defer a.mu.RUnlock()
@ -675,8 +684,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 <f>.
// If <f> 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 +696,8 @@ func (a *Array) IteratorAsc(f func(k int, v interface{}) bool) {
}
}
// 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.
// 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 +745,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 +757,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 +793,7 @@ func (a *Array) FilterEmpty() *Array {
return a
}
// Walk applies a user supplied function <f> 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()

View File

@ -28,14 +28,14 @@ type IntArray struct {
}
// NewIntArray creates and returns an empty array.
// The parameter <safe> 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 <safe> 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 +44,8 @@ func NewIntArraySize(size int, cap int, safe ...bool) *IntArray {
}
}
// NewIntArrayRange creates and returns a array by a range from <start> to <end>
// with step value <step>.
// 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 +59,8 @@ func NewIntArrayRange(start, end, step int, safe ...bool) *IntArray {
return NewIntArrayFrom(slice, safe...)
}
// NewIntArrayFrom creates and returns an array with given slice <array>.
// The parameter <safe> 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 +69,8 @@ func NewIntArrayFrom(array []int, safe ...bool) *IntArray {
}
}
// 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,
// 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 +81,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 <index> is out of range of the array, the <found> 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()
@ -103,7 +110,7 @@ func (a *IntArray) Set(index int, value int) error {
return nil
}
// SetArray sets the underlying slice array with the given <array>.
// 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 +118,7 @@ func (a *IntArray) SetArray(array []int) *IntArray {
return a
}
// Replace replaces the array items by given <array> 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,7 +143,7 @@ func (a *IntArray) Sum() (sum int) {
}
// Sort sorts the array in increasing order.
// The parameter <reverse> 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()
@ -153,7 +160,7 @@ func (a *IntArray) Sort(reverse ...bool) *IntArray {
return a
}
// SortFunc sorts the array by custom function <less>.
// 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,7 +170,7 @@ func (a *IntArray) SortFunc(less func(v1, v2 int) bool) *IntArray {
return a
}
// InsertBefore inserts the <value> to the front of <index>.
// 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()
@ -176,7 +183,7 @@ func (a *IntArray) InsertBefore(index int, value int) error {
return nil
}
// InsertAfter inserts the <value> to the back of <index>.
// 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()
@ -190,7 +197,7 @@ func (a *IntArray) InsertAfter(index int, value int) error {
}
// Remove removes an item by index.
// If the given <index> is out of range of the array, the <found> 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 +255,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 <found> 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 +268,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 <found> 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 +282,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 <found> 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 <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.
// 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 +308,9 @@ func (a *IntArray) PopRands(size int) []int {
return array
}
// 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.
// 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 +327,9 @@ func (a *IntArray) PopLefts(size int) []int {
return value
}
// 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.
// 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 +351,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 <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
// 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 +378,7 @@ func (a *IntArray) Range(start int, end ...int) []int {
}
// SubSlice returns a slice of elements from the array as specified
// by the <offset> and <size> 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.
@ -487,7 +494,7 @@ func (a *IntArray) Contains(value int) bool {
return a.Search(value) != -1
}
// Search searches array by <value>, returns the index of <value>,
// 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 +529,7 @@ func (a *IntArray) Unique() *IntArray {
return a
}
// LockFunc locks writing by callback function <f>.
// 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 +537,7 @@ func (a *IntArray) LockFunc(f func(array []int)) *IntArray {
return a
}
// RLockFunc locks reading by callback function <f>.
// RLockFunc locks reading by callback function `f`.
func (a *IntArray) RLockFunc(f func(array []int)) *IntArray {
a.mu.RLock()
defer a.mu.RUnlock()
@ -538,16 +545,16 @@ func (a *IntArray) RLockFunc(f func(array []int)) *IntArray {
return a
}
// Merge merges <array> into current array.
// The parameter <array> 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 <value>,
// keys starting at the <startIndex> 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()
@ -565,7 +572,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 <size>.
// 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 +594,9 @@ func (a *IntArray) Chunk(size int) [][]int {
return n
}
// Pad pads array to the specified length with <value>.
// 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 <size> 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 +631,7 @@ func (a *IntArray) Rand() (value int, found bool) {
return a.array[grand.Intn(len(a.array))], true
}
// Rands randomly returns <size> 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 +665,7 @@ func (a *IntArray) Reverse() *IntArray {
return a
}
// Join joins array elements with a string <glue>.
// Join joins array elements with a string `glue`.
func (a *IntArray) Join(glue string) string {
a.mu.RLock()
defer a.mu.RUnlock()
@ -691,8 +698,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 <f>.
// If <f> 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 +710,8 @@ func (a *IntArray) IteratorAsc(f func(k int, v int) bool) {
}
}
// 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.
// 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 +742,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 +754,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 +775,7 @@ func (a *IntArray) FilterEmpty() *IntArray {
return a
}
// Walk applies a user supplied function <f> 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()

View File

@ -30,14 +30,14 @@ type StrArray struct {
}
// NewStrArray creates and returns an empty array.
// The parameter <safe> 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 <safe> 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 <array>.
// The parameter <safe> 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 <array>.
// The parameter <safe> 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 <index> is out of range of the array, the <found> 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()
@ -90,7 +97,7 @@ func (a *StrArray) Set(index int, value string) error {
return nil
}
// SetArray sets the underlying slice array with the given <array>.
// 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 <array> 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,7 +130,7 @@ func (a *StrArray) Sum() (sum int) {
}
// Sort sorts the array in increasing order.
// The parameter <reverse> 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()
@ -141,7 +148,7 @@ func (a *StrArray) Sort(reverse ...bool) *StrArray {
return a
}
// SortFunc sorts the array by custom function <less>.
// 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,7 +158,7 @@ func (a *StrArray) SortFunc(less func(v1, v2 string) bool) *StrArray {
return a
}
// InsertBefore inserts the <value> to the front of <index>.
// 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()
@ -164,7 +171,7 @@ func (a *StrArray) InsertBefore(index int, value string) error {
return nil
}
// InsertAfter inserts the <value> to the back of <index>.
// 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()
@ -178,7 +185,7 @@ func (a *StrArray) InsertAfter(index int, value string) error {
}
// Remove removes an item by index.
// If the given <index> is out of range of the array, the <found> 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 +243,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 <found> 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 +256,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 <found> 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 +270,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 <found> 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 <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.
// 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 +296,9 @@ func (a *StrArray) PopRands(size int) []string {
return array
}
// 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.
// 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 +315,9 @@ func (a *StrArray) PopLefts(size int) []string {
return value
}
// 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.
// 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 +339,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 <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
// 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 +366,7 @@ func (a *StrArray) Range(start int, end ...int) []string {
}
// SubSlice returns a slice of elements from the array as specified
// by the <offset> and <size> 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.
@ -491,7 +498,7 @@ func (a *StrArray) ContainsI(value string) bool {
return false
}
// Search searches array by <value>, returns the index of <value>,
// 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 +533,7 @@ func (a *StrArray) Unique() *StrArray {
return a
}
// LockFunc locks writing by callback function <f>.
// 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 +541,7 @@ func (a *StrArray) LockFunc(f func(array []string)) *StrArray {
return a
}
// RLockFunc locks reading by callback function <f>.
// RLockFunc locks reading by callback function `f`.
func (a *StrArray) RLockFunc(f func(array []string)) *StrArray {
a.mu.RLock()
defer a.mu.RUnlock()
@ -542,16 +549,16 @@ func (a *StrArray) RLockFunc(f func(array []string)) *StrArray {
return a
}
// Merge merges <array> into current array.
// The parameter <array> 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 <value>,
// keys starting at the <startIndex> 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()
@ -569,7 +576,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 <size>.
// 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 +598,9 @@ func (a *StrArray) Chunk(size int) [][]string {
return n
}
// Pad pads array to the specified length with <value>.
// 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 <size> 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 +635,7 @@ func (a *StrArray) Rand() (value string, found bool) {
return a.array[grand.Intn(len(a.array))], true
}
// Rands randomly returns <size> 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 +669,7 @@ func (a *StrArray) Reverse() *StrArray {
return a
}
// Join joins array elements with a string <glue>.
// Join joins array elements with a string `glue`.
func (a *StrArray) Join(glue string) string {
a.mu.RLock()
defer a.mu.RUnlock()
@ -695,8 +702,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 <f>.
// If <f> 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 +714,8 @@ func (a *StrArray) IteratorAsc(f func(k int, v string) bool) {
}
}
// 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.
// 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 +757,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 +769,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 +790,7 @@ func (a *StrArray) FilterEmpty() *StrArray {
return a
}
// Walk applies a user supplied function <f> 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()

View File

@ -34,8 +34,8 @@ type SortedArray struct {
}
// NewSortedArray creates and returns an empty sorted 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,
// 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 <safe> 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 <start> to <end>
// with step value <step>.
// 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 <array>.
// The parameter <safe> 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 <array>.
// The parameter <safe> 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 <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 *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 <reverse> controls whether sort
// The parameter `reverse` controls whether sort
// in increasing order(default) or decreasing order
func (a *SortedArray) Sort() *SortedArray {
a.mu.Lock()
@ -157,7 +164,7 @@ func (a *SortedArray) Append(values ...interface{}) *SortedArray {
}
// Get returns the value by the specified index.
// If the given <index> is out of range of the array, the <found> 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 +175,7 @@ func (a *SortedArray) Get(index int) (value interface{}, found bool) {
}
// Remove removes an item by index.
// If the given <index> is out of range of the array, the <found> 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 +216,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 <found> 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 +229,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 <found> 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 +243,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 <found> 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 <size> 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 +267,7 @@ func (a *SortedArray) PopRands(size int) []interface{} {
return array
}
// PopLefts pops and returns <size> 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 +284,7 @@ func (a *SortedArray) PopLefts(size int) []interface{} {
return value
}
// PopRights pops and returns <size> 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 +306,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 <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
// 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 +333,7 @@ func (a *SortedArray) Range(start int, end ...int) []interface{} {
}
// SubSlice returns a slice of elements from the array as specified
// by the <offset> and <size> 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 +426,7 @@ func (a *SortedArray) Contains(value interface{}) bool {
return a.Search(value) != -1
}
// Search searches array by <value>, returns the index of <value>,
// 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 +437,9 @@ func (a *SortedArray) Search(value interface{}) (index int) {
// Binary search.
// It returns the last compared index and the result.
// 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>.
// 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()
@ -512,7 +519,7 @@ func (a *SortedArray) Clear() *SortedArray {
return a
}
// LockFunc locks writing by callback function <f>.
// 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 +533,7 @@ func (a *SortedArray) LockFunc(f func(array []interface{})) *SortedArray {
return a
}
// RLockFunc locks reading by callback function <f>.
// 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 +541,8 @@ func (a *SortedArray) RLockFunc(f func(array []interface{})) *SortedArray {
return a
}
// Merge merges <array> into current array.
// The parameter <array> 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 +550,7 @@ func (a *SortedArray) Merge(array interface{}) *SortedArray {
}
// Chunk splits an array into multiple arrays,
// the size of each array is determined by <size>.
// 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 +582,7 @@ func (a *SortedArray) Rand() (value interface{}, found bool) {
return a.array[grand.Intn(len(a.array))], true
}
// Rands randomly returns <size> 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 +596,7 @@ func (a *SortedArray) Rands(size int) []interface{} {
return array
}
// Join joins array elements with a string <glue>.
// Join joins array elements with a string `glue`.
func (a *SortedArray) Join(glue string) string {
a.mu.RLock()
defer a.mu.RUnlock()
@ -622,8 +629,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 <f>.
// If <f> 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 +641,8 @@ func (a *SortedArray) IteratorAsc(f func(k int, v interface{}) bool) {
}
}
// 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.
// 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 +692,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 +713,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 +768,7 @@ func (a *SortedArray) FilterEmpty() *SortedArray {
return a
}
// Walk applies a user supplied function <f> 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()

View File

@ -31,14 +31,14 @@ type SortedIntArray struct {
}
// NewSortedIntArray creates and returns an empty sorted array.
// The parameter <safe> 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 <safe> 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 <safe> 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 <start> to <end>
// with step value <step>.
// 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 <array>.
// The parameter <safe> 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 <array>.
// The parameter <safe> 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 <array>.
// 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 <reverse> 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 <index> is out of range of the array, the <found> 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 <index> is out of range of the array, the <found> 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 <found> 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 <found> 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 <found> 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 <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.
// 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 <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.
// 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 <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.
// 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 <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
// 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 <offset> and <size> 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 <value>, returns the index of <value>,
// 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 <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>.
// 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 <f>.
// 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 <f>.
// 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 <array> into current array.
// The parameter <array> 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 <size>.
// 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 <size> 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 <glue>.
// Join joins array elements with a string `glue`.
func (a *SortedIntArray) Join(glue string) string {
a.mu.RLock()
defer a.mu.RUnlock()
@ -613,8 +620,8 @@ func (a *SortedIntArray) Iterator(f func(k int, v int) bool) {
a.IteratorAsc(f)
}
// 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.
// 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 *SortedIntArray) IteratorAsc(f func(k int, v int) bool) {
a.mu.RLock()
defer a.mu.RUnlock()
@ -625,8 +632,8 @@ func (a *SortedIntArray) IteratorAsc(f func(k int, v int) bool) {
}
}
// 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.
// 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 *SortedIntArray) IteratorDesc(f func(k int, v int) bool) {
a.mu.RLock()
defer a.mu.RUnlock()
@ -658,7 +665,7 @@ func (a *SortedIntArray) 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.array != nil {
@ -676,7 +683,7 @@ func (a *SortedIntArray) 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.SliceInt(value)
}
@ -707,7 +714,7 @@ func (a *SortedIntArray) FilterEmpty() *SortedIntArray {
return a
}
// Walk applies a user supplied function <f> to every item of array.
// Walk applies a user supplied function `f` to every item of array.
func (a *SortedIntArray) Walk(f func(value int) int) *SortedIntArray {
a.mu.Lock()
defer a.mu.Unlock()

View File

@ -32,14 +32,14 @@ type SortedStrArray struct {
}
// NewSortedStrArray creates and returns an empty sorted array.
// The parameter <safe> 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 NewSortedStrArray(safe ...bool) *SortedStrArray {
return NewSortedStrArraySize(0, safe...)
}
// NewSortedStrArrayComparator creates and returns an empty sorted array with specified comparator.
// The parameter <safe> 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 NewSortedStrArrayComparator(comparator func(a, b string) int, safe ...bool) *SortedStrArray {
array := NewSortedStrArray(safe...)
array.comparator = comparator
@ -47,7 +47,7 @@ func NewSortedStrArrayComparator(comparator func(a, b string) int, safe ...bool)
}
// NewSortedStrArraySize create and returns an sorted array with given size and cap.
// The parameter <safe> 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 NewSortedStrArraySize(cap int, safe ...bool) *SortedStrArray {
return &SortedStrArray{
@ -57,8 +57,8 @@ func NewSortedStrArraySize(cap int, safe ...bool) *SortedStrArray {
}
}
// NewSortedStrArrayFrom creates and returns an sorted array with given slice <array>.
// The parameter <safe> is used to specify whether using array in concurrent-safety,
// NewSortedStrArrayFrom 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 NewSortedStrArrayFrom(array []string, safe ...bool) *SortedStrArray {
a := NewSortedStrArraySize(0, safe...)
@ -67,8 +67,8 @@ func NewSortedStrArrayFrom(array []string, safe ...bool) *SortedStrArray {
return a
}
// NewSortedStrArrayFromCopy 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,
// NewSortedStrArrayFromCopy 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 NewSortedStrArrayFromCopy(array []string, safe ...bool) *SortedStrArray {
newArray := make([]string, len(array))
@ -76,7 +76,7 @@ func NewSortedStrArrayFromCopy(array []string, safe ...bool) *SortedStrArray {
return NewSortedStrArrayFrom(newArray, safe...)
}
// SetArray sets the underlying slice array with the given <array>.
// SetArray sets the underlying slice array with the given `array`.
func (a *SortedStrArray) SetArray(array []string) *SortedStrArray {
a.mu.Lock()
defer a.mu.Unlock()
@ -85,8 +85,15 @@ func (a *SortedStrArray) SetArray(array []string) *SortedStrArray {
return a
}
// 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 *SortedStrArray) At(index int) (value string) {
value, _ = a.Get(index)
return
}
// Sort sorts the array in increasing order.
// The parameter <reverse> controls whether sort
// The parameter `reverse` controls whether sort
// in increasing order(default) or decreasing order.
func (a *SortedStrArray) Sort() *SortedStrArray {
a.mu.Lock()
@ -128,7 +135,7 @@ func (a *SortedStrArray) Append(values ...string) *SortedStrArray {
}
// Get returns the value by the specified index.
// If the given <index> is out of range of the array, the <found> is false.
// If the given `index` is out of range of the array, the `found` is false.
func (a *SortedStrArray) Get(index int) (value string, found bool) {
a.mu.RLock()
defer a.mu.RUnlock()
@ -139,7 +146,7 @@ func (a *SortedStrArray) Get(index int) (value string, found bool) {
}
// Remove removes an item by index.
// If the given <index> is out of range of the array, the <found> is false.
// If the given `index` is out of range of the array, the `found` is false.
func (a *SortedStrArray) Remove(index int) (value string, found bool) {
a.mu.Lock()
defer a.mu.Unlock()
@ -180,7 +187,7 @@ func (a *SortedStrArray) RemoveValue(value string) bool {
}
// PopLeft pops and returns an item from the beginning of array.
// Note that if the array is empty, the <found> is false.
// Note that if the array is empty, the `found` is false.
func (a *SortedStrArray) PopLeft() (value string, found bool) {
a.mu.Lock()
defer a.mu.Unlock()
@ -193,7 +200,7 @@ func (a *SortedStrArray) PopLeft() (value string, found bool) {
}
// PopRight pops and returns an item from the end of array.
// Note that if the array is empty, the <found> is false.
// Note that if the array is empty, the `found` is false.
func (a *SortedStrArray) PopRight() (value string, found bool) {
a.mu.Lock()
defer a.mu.Unlock()
@ -207,16 +214,16 @@ func (a *SortedStrArray) PopRight() (value string, found bool) {
}
// PopRand randomly pops and return an item out of array.
// Note that if the array is empty, the <found> is false.
// Note that if the array is empty, the `found` is false.
func (a *SortedStrArray) 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 <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.
// 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 *SortedStrArray) PopRands(size int) []string {
a.mu.Lock()
defer a.mu.Unlock()
@ -233,9 +240,9 @@ func (a *SortedStrArray) PopRands(size int) []string {
return array
}
// 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.
// 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 *SortedStrArray) PopLefts(size int) []string {
a.mu.Lock()
defer a.mu.Unlock()
@ -252,9 +259,9 @@ func (a *SortedStrArray) PopLefts(size int) []string {
return value
}
// 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.
// 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 *SortedStrArray) PopRights(size int) []string {
a.mu.Lock()
defer a.mu.Unlock()
@ -276,8 +283,8 @@ func (a *SortedStrArray) PopRights(size int) []string {
// Notice, if in concurrent-safe usage, it returns a copy of slice;
// else a pointer to the underlying data.
//
// 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
// 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 *SortedStrArray) Range(start int, end ...int) []string {
a.mu.RLock()
@ -303,7 +310,7 @@ func (a *SortedStrArray) Range(start int, end ...int) []string {
}
// SubSlice returns a slice of elements from the array as specified
// by the <offset> and <size> 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.
@ -418,7 +425,7 @@ func (a *SortedStrArray) ContainsI(value string) bool {
return false
}
// Search searches array by <value>, returns the index of <value>,
// Search searches array by `value`, returns the index of `value`,
// or returns -1 if not exists.
func (a *SortedStrArray) Search(value string) (index int) {
if i, r := a.binSearch(value, true); r == 0 {
@ -429,9 +436,9 @@ func (a *SortedStrArray) Search(value string) (index int) {
// Binary search.
// It returns the last compared index and the result.
// 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>.
// 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 *SortedStrArray) binSearch(value string, lock bool) (index int, result int) {
if lock {
a.mu.RLock()
@ -511,7 +518,7 @@ func (a *SortedStrArray) Clear() *SortedStrArray {
return a
}
// LockFunc locks writing by callback function <f>.
// LockFunc locks writing by callback function `f`.
func (a *SortedStrArray) LockFunc(f func(array []string)) *SortedStrArray {
a.mu.Lock()
defer a.mu.Unlock()
@ -519,7 +526,7 @@ func (a *SortedStrArray) LockFunc(f func(array []string)) *SortedStrArray {
return a
}
// RLockFunc locks reading by callback function <f>.
// RLockFunc locks reading by callback function `f`.
func (a *SortedStrArray) RLockFunc(f func(array []string)) *SortedStrArray {
a.mu.RLock()
defer a.mu.RUnlock()
@ -527,8 +534,8 @@ func (a *SortedStrArray) RLockFunc(f func(array []string)) *SortedStrArray {
return a
}
// Merge merges <array> into current array.
// The parameter <array> 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 *SortedStrArray) Merge(array interface{}) *SortedStrArray {
@ -536,7 +543,7 @@ func (a *SortedStrArray) Merge(array interface{}) *SortedStrArray {
}
// Chunk splits an array into multiple arrays,
// the size of each array is determined by <size>.
// the size of each array is determined by `size`.
// The last chunk may contain less than size elements.
func (a *SortedStrArray) Chunk(size int) [][]string {
if size < 1 {
@ -568,7 +575,7 @@ func (a *SortedStrArray) Rand() (value string, found bool) {
return a.array[grand.Intn(len(a.array))], true
}
// Rands randomly returns <size> items from array(no deleting).
// Rands randomly returns `size` items from array(no deleting).
func (a *SortedStrArray) Rands(size int) []string {
a.mu.RLock()
defer a.mu.RUnlock()
@ -582,7 +589,7 @@ func (a *SortedStrArray) Rands(size int) []string {
return array
}
// Join joins array elements with a string <glue>.
// Join joins array elements with a string `glue`.
func (a *SortedStrArray) Join(glue string) string {
a.mu.RLock()
defer a.mu.RUnlock()
@ -615,8 +622,8 @@ func (a *SortedStrArray) Iterator(f func(k int, v string) bool) {
a.IteratorAsc(f)
}
// 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.
// 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 *SortedStrArray) IteratorAsc(f func(k int, v string) bool) {
a.mu.RLock()
defer a.mu.RUnlock()
@ -627,8 +634,8 @@ func (a *SortedStrArray) IteratorAsc(f func(k int, v string) bool) {
}
}
// 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.
// 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 *SortedStrArray) IteratorDesc(f func(k int, v string) bool) {
a.mu.RLock()
defer a.mu.RUnlock()
@ -671,7 +678,7 @@ func (a *SortedStrArray) 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.array != nil {
@ -689,7 +696,7 @@ func (a *SortedStrArray) 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.SliceStr(value)
}
@ -720,7 +727,7 @@ func (a *SortedStrArray) FilterEmpty() *SortedStrArray {
return a
}
// Walk applies a user supplied function <f> to every item of array.
// Walk applies a user supplied function `f` to every item of array.
func (a *SortedStrArray) Walk(f func(value string) string) *SortedStrArray {
a.mu.Lock()
defer a.mu.Unlock()

View File

@ -75,14 +75,14 @@ func ExampleNew() {
func ExampleArray_Iterator() {
array := garray.NewArrayFrom(g.Slice{"a", "b", "c"})
// Iterator is alias of IteratorAsc, which iterates the array readonly in ascending order
// with given callback function <f>.
// If <f> returns true, then it continues iterating; or false to stop.
// with given callback function `f`.
// If `f` returns true, then it continues iterating; or false to stop.
array.Iterator(func(k int, v interface{}) bool {
fmt.Println(k, v)
return true
})
// 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.
// 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.
array.IteratorDesc(func(k int, v interface{}) bool {
fmt.Println(k, v)
return true
@ -150,7 +150,7 @@ func ExampleArray_Chunk() {
array := garray.NewFrom(g.Slice{1, 2, 3, 4, 5, 6, 7, 8, 9})
// Chunk splits an array into multiple arrays,
// the size of each array is determined by <size>.
// the size of each array is determined by `size`.
// The last chunk may contain less than size elements.
fmt.Println(array.Chunk(2))

View File

@ -570,12 +570,12 @@ func TestArray_Json(t *testing.T) {
t.Assert(err1, err2)
a2 := garray.New()
err2 = json.Unmarshal(b2, &a2)
err2 = json.UnmarshalUseNumber(b2, &a2)
t.Assert(err2, nil)
t.Assert(a2.Slice(), s1)
var a3 garray.Array
err := json.Unmarshal(b2, &a3)
err := json.UnmarshalUseNumber(b2, &a3)
t.Assert(err, nil)
t.Assert(a3.Slice(), s1)
})
@ -589,12 +589,12 @@ func TestArray_Json(t *testing.T) {
t.Assert(err1, err2)
a2 := garray.New()
err2 = json.Unmarshal(b2, &a2)
err2 = json.UnmarshalUseNumber(b2, &a2)
t.Assert(err2, nil)
t.Assert(a2.Slice(), s1)
var a3 garray.Array
err := json.Unmarshal(b2, &a3)
err := json.UnmarshalUseNumber(b2, &a3)
t.Assert(err, nil)
t.Assert(a3.Slice(), s1)
})
@ -612,7 +612,7 @@ func TestArray_Json(t *testing.T) {
t.Assert(err, nil)
user := new(User)
err = json.Unmarshal(b, user)
err = json.UnmarshalUseNumber(b, user)
t.Assert(err, nil)
t.Assert(user.Name, data["Name"])
t.Assert(user.Scores, data["Scores"])
@ -631,7 +631,7 @@ func TestArray_Json(t *testing.T) {
t.Assert(err, nil)
user := new(User)
err = json.Unmarshal(b, user)
err = json.UnmarshalUseNumber(b, user)
t.Assert(err, nil)
t.Assert(user.Name, data["Name"])
t.Assert(user.Scores, data["Scores"])

View File

@ -615,11 +615,11 @@ func TestIntArray_Json(t *testing.T) {
t.Assert(err1, err2)
a2 := garray.NewIntArray()
err1 = json.Unmarshal(b2, &a2)
err1 = json.UnmarshalUseNumber(b2, &a2)
t.Assert(a2.Slice(), s1)
var a3 garray.IntArray
err := json.Unmarshal(b2, &a3)
err := json.UnmarshalUseNumber(b2, &a3)
t.Assert(err, nil)
t.Assert(a3.Slice(), s1)
})
@ -633,11 +633,11 @@ func TestIntArray_Json(t *testing.T) {
t.Assert(err1, err2)
a2 := garray.NewIntArray()
err1 = json.Unmarshal(b2, &a2)
err1 = json.UnmarshalUseNumber(b2, &a2)
t.Assert(a2.Slice(), s1)
var a3 garray.IntArray
err := json.Unmarshal(b2, &a3)
err := json.UnmarshalUseNumber(b2, &a3)
t.Assert(err, nil)
t.Assert(a3.Slice(), s1)
})
@ -655,7 +655,7 @@ func TestIntArray_Json(t *testing.T) {
t.Assert(err, nil)
user := new(User)
err = json.Unmarshal(b, user)
err = json.UnmarshalUseNumber(b, user)
t.Assert(err, nil)
t.Assert(user.Name, data["Name"])
t.Assert(user.Scores, data["Scores"])
@ -674,7 +674,7 @@ func TestIntArray_Json(t *testing.T) {
t.Assert(err, nil)
user := new(User)
err = json.Unmarshal(b, user)
err = json.UnmarshalUseNumber(b, user)
t.Assert(err, nil)
t.Assert(user.Name, data["Name"])
t.Assert(user.Scores, data["Scores"])

View File

@ -614,11 +614,11 @@ func TestStrArray_Json(t *testing.T) {
t.Assert(err1, err2)
a2 := garray.NewStrArray()
err1 = json.Unmarshal(b2, &a2)
err1 = json.UnmarshalUseNumber(b2, &a2)
t.Assert(a2.Slice(), s1)
var a3 garray.StrArray
err := json.Unmarshal(b2, &a3)
err := json.UnmarshalUseNumber(b2, &a3)
t.Assert(err, nil)
t.Assert(a3.Slice(), s1)
})
@ -632,11 +632,11 @@ func TestStrArray_Json(t *testing.T) {
t.Assert(err1, err2)
a2 := garray.NewStrArray()
err1 = json.Unmarshal(b2, &a2)
err1 = json.UnmarshalUseNumber(b2, &a2)
t.Assert(a2.Slice(), s1)
var a3 garray.StrArray
err := json.Unmarshal(b2, &a3)
err := json.UnmarshalUseNumber(b2, &a3)
t.Assert(err, nil)
t.Assert(a3.Slice(), s1)
})
@ -654,7 +654,7 @@ func TestStrArray_Json(t *testing.T) {
t.Assert(err, nil)
user := new(User)
err = json.Unmarshal(b, user)
err = json.UnmarshalUseNumber(b, user)
t.Assert(err, nil)
t.Assert(user.Name, data["Name"])
t.Assert(user.Scores, data["Scores"])
@ -673,7 +673,7 @@ func TestStrArray_Json(t *testing.T) {
t.Assert(err, nil)
user := new(User)
err = json.Unmarshal(b, user)
err = json.UnmarshalUseNumber(b, user)
t.Assert(err, nil)
t.Assert(user.Name, data["Name"])
t.Assert(user.Scores, data["Scores"])

View File

@ -656,11 +656,11 @@ func TestSortedArray_Json(t *testing.T) {
t.Assert(err1, err2)
a2 := garray.NewSortedArray(gutil.ComparatorString)
err1 = json.Unmarshal(b2, &a2)
err1 = json.UnmarshalUseNumber(b2, &a2)
t.Assert(a2.Slice(), s2)
var a3 garray.SortedArray
err := json.Unmarshal(b2, &a3)
err := json.UnmarshalUseNumber(b2, &a3)
t.Assert(err, nil)
t.Assert(a3.Slice(), s1)
t.Assert(a3.Interfaces(), s1)
@ -676,11 +676,11 @@ func TestSortedArray_Json(t *testing.T) {
t.Assert(err1, err2)
a2 := garray.NewSortedArray(gutil.ComparatorString)
err1 = json.Unmarshal(b2, &a2)
err1 = json.UnmarshalUseNumber(b2, &a2)
t.Assert(a2.Slice(), s2)
var a3 garray.SortedArray
err := json.Unmarshal(b2, &a3)
err := json.UnmarshalUseNumber(b2, &a3)
t.Assert(err, nil)
t.Assert(a3.Slice(), s1)
t.Assert(a3.Interfaces(), s1)
@ -699,7 +699,7 @@ func TestSortedArray_Json(t *testing.T) {
t.Assert(err, nil)
user := new(User)
err = json.Unmarshal(b, user)
err = json.UnmarshalUseNumber(b, user)
t.Assert(err, nil)
t.Assert(user.Name, data["Name"])
t.AssertNE(user.Scores, nil)
@ -735,7 +735,7 @@ func TestSortedArray_Json(t *testing.T) {
t.Assert(err, nil)
user := new(User)
err = json.Unmarshal(b, user)
err = json.UnmarshalUseNumber(b, user)
t.Assert(err, nil)
t.Assert(user.Name, data["Name"])
t.AssertNE(user.Scores, nil)

View File

@ -557,11 +557,11 @@ func TestSortedIntArray_Json(t *testing.T) {
t.Assert(err1, err2)
a2 := garray.NewSortedIntArray()
err1 = json.Unmarshal(b2, &a2)
err1 = json.UnmarshalUseNumber(b2, &a2)
t.Assert(a2.Slice(), s2)
var a3 garray.SortedIntArray
err := json.Unmarshal(b2, &a3)
err := json.UnmarshalUseNumber(b2, &a3)
t.Assert(err, nil)
t.Assert(a3.Slice(), s1)
})
@ -576,11 +576,11 @@ func TestSortedIntArray_Json(t *testing.T) {
t.Assert(err1, err2)
a2 := garray.NewSortedIntArray()
err1 = json.Unmarshal(b2, &a2)
err1 = json.UnmarshalUseNumber(b2, &a2)
t.Assert(a2.Slice(), s2)
var a3 garray.SortedIntArray
err := json.Unmarshal(b2, &a3)
err := json.UnmarshalUseNumber(b2, &a3)
t.Assert(err, nil)
t.Assert(a3.Slice(), s1)
})
@ -598,7 +598,7 @@ func TestSortedIntArray_Json(t *testing.T) {
t.Assert(err, nil)
user := new(User)
err = json.Unmarshal(b, user)
err = json.UnmarshalUseNumber(b, user)
t.Assert(err, nil)
t.Assert(user.Name, data["Name"])
t.Assert(user.Scores, []int{98, 99, 100})
@ -617,7 +617,7 @@ func TestSortedIntArray_Json(t *testing.T) {
t.Assert(err, nil)
user := new(User)
err = json.Unmarshal(b, user)
err = json.UnmarshalUseNumber(b, user)
t.Assert(err, nil)
t.Assert(user.Name, data["Name"])
t.Assert(user.Scores, []int{98, 99, 100})

View File

@ -577,12 +577,12 @@ func TestSortedStrArray_Json(t *testing.T) {
t.Assert(err1, err2)
a2 := garray.NewSortedStrArray()
err1 = json.Unmarshal(b2, &a2)
err1 = json.UnmarshalUseNumber(b2, &a2)
t.Assert(a2.Slice(), s2)
t.Assert(a2.Interfaces(), s2)
var a3 garray.SortedStrArray
err := json.Unmarshal(b2, &a3)
err := json.UnmarshalUseNumber(b2, &a3)
t.Assert(err, nil)
t.Assert(a3.Slice(), s1)
t.Assert(a3.Interfaces(), s1)
@ -598,12 +598,12 @@ func TestSortedStrArray_Json(t *testing.T) {
t.Assert(err1, err2)
a2 := garray.NewSortedStrArray()
err1 = json.Unmarshal(b2, &a2)
err1 = json.UnmarshalUseNumber(b2, &a2)
t.Assert(a2.Slice(), s2)
t.Assert(a2.Interfaces(), s2)
var a3 garray.SortedStrArray
err := json.Unmarshal(b2, &a3)
err := json.UnmarshalUseNumber(b2, &a3)
t.Assert(err, nil)
t.Assert(a3.Slice(), s1)
t.Assert(a3.Interfaces(), s1)
@ -622,7 +622,7 @@ func TestSortedStrArray_Json(t *testing.T) {
t.Assert(err, nil)
user := new(User)
err = json.Unmarshal(b, user)
err = json.UnmarshalUseNumber(b, user)
t.Assert(err, nil)
t.Assert(user.Name, data["Name"])
t.Assert(user.Scores, []string{"A", "A", "A+"})
@ -641,7 +641,7 @@ func TestSortedStrArray_Json(t *testing.T) {
t.Assert(err, nil)
user := new(User)
err = json.Unmarshal(b, user)
err = json.UnmarshalUseNumber(b, user)
t.Assert(err, nil)
t.Assert(user.Name, data["Name"])
t.Assert(user.Scores, []string{"A", "A", "A+"})

View File

@ -519,7 +519,7 @@ func (l *List) UnmarshalJSON(b []byte) error {
l.list = list.New()
}
var array []interface{}
if err := json.Unmarshal(b, &array); err != nil {
if err := json.UnmarshalUseNumber(b, &array); err != nil {
return err
}
l.PushBacks(array)
@ -536,7 +536,7 @@ func (l *List) UnmarshalValue(value interface{}) (err error) {
var array []interface{}
switch value.(type) {
case string, []byte:
err = json.Unmarshal(gconv.Bytes(value), &array)
err = json.UnmarshalUseNumber(gconv.Bytes(value), &array)
default:
array = gconv.SliceAny(value)
}

View File

@ -711,7 +711,7 @@ func TestList_Json(t *testing.T) {
b, err := json.Marshal(a)
t.Assert(err, nil)
err = json.Unmarshal(b, l)
err = json.UnmarshalUseNumber(b, l)
t.Assert(err, nil)
t.Assert(l.FrontAll(), a)
})
@ -721,7 +721,7 @@ func TestList_Json(t *testing.T) {
b, err := json.Marshal(a)
t.Assert(err, nil)
err = json.Unmarshal(b, &l)
err = json.UnmarshalUseNumber(b, &l)
t.Assert(err, nil)
t.Assert(l.FrontAll(), a)
})

View File

@ -476,7 +476,7 @@ func (m *AnyAnyMap) UnmarshalJSON(b []byte) error {
m.data = make(map[interface{}]interface{})
}
var data map[string]interface{}
if err := json.Unmarshal(b, &data); err != nil {
if err := json.UnmarshalUseNumber(b, &data); err != nil {
return err
}
for k, v := range data {

View File

@ -475,7 +475,7 @@ func (m *IntAnyMap) UnmarshalJSON(b []byte) error {
if m.data == nil {
m.data = make(map[int]interface{})
}
if err := json.Unmarshal(b, &m.data); err != nil {
if err := json.UnmarshalUseNumber(b, &m.data); err != nil {
return err
}
return nil
@ -490,7 +490,7 @@ func (m *IntAnyMap) UnmarshalValue(value interface{}) (err error) {
}
switch value.(type) {
case string, []byte:
return json.Unmarshal(gconv.Bytes(value), &m.data)
return json.UnmarshalUseNumber(gconv.Bytes(value), &m.data)
default:
for k, v := range gconv.Map(value) {
m.data[gconv.Int(k)] = v

View File

@ -446,7 +446,7 @@ func (m *IntIntMap) UnmarshalJSON(b []byte) error {
if m.data == nil {
m.data = make(map[int]int)
}
if err := json.Unmarshal(b, &m.data); err != nil {
if err := json.UnmarshalUseNumber(b, &m.data); err != nil {
return err
}
return nil
@ -461,7 +461,7 @@ func (m *IntIntMap) UnmarshalValue(value interface{}) (err error) {
}
switch value.(type) {
case string, []byte:
return json.Unmarshal(gconv.Bytes(value), &m.data)
return json.UnmarshalUseNumber(gconv.Bytes(value), &m.data)
default:
for k, v := range gconv.Map(value) {
m.data[gconv.Int(k)] = gconv.Int(v)

View File

@ -446,7 +446,7 @@ func (m *IntStrMap) UnmarshalJSON(b []byte) error {
if m.data == nil {
m.data = make(map[int]string)
}
if err := json.Unmarshal(b, &m.data); err != nil {
if err := json.UnmarshalUseNumber(b, &m.data); err != nil {
return err
}
return nil
@ -461,7 +461,7 @@ func (m *IntStrMap) UnmarshalValue(value interface{}) (err error) {
}
switch value.(type) {
case string, []byte:
return json.Unmarshal(gconv.Bytes(value), &m.data)
return json.UnmarshalUseNumber(gconv.Bytes(value), &m.data)
default:
for k, v := range gconv.Map(value) {
m.data[gconv.Int(k)] = gconv.String(v)

View File

@ -471,7 +471,7 @@ func (m *StrAnyMap) UnmarshalJSON(b []byte) error {
if m.data == nil {
m.data = make(map[string]interface{})
}
if err := json.Unmarshal(b, &m.data); err != nil {
if err := json.UnmarshalUseNumber(b, &m.data); err != nil {
return err
}
return nil

View File

@ -449,7 +449,7 @@ func (m *StrIntMap) UnmarshalJSON(b []byte) error {
if m.data == nil {
m.data = make(map[string]int)
}
if err := json.Unmarshal(b, &m.data); err != nil {
if err := json.UnmarshalUseNumber(b, &m.data); err != nil {
return err
}
return nil
@ -464,7 +464,7 @@ func (m *StrIntMap) UnmarshalValue(value interface{}) (err error) {
}
switch value.(type) {
case string, []byte:
return json.Unmarshal(gconv.Bytes(value), &m.data)
return json.UnmarshalUseNumber(gconv.Bytes(value), &m.data)
default:
for k, v := range gconv.Map(value) {
m.data[k] = gconv.Int(v)

View File

@ -449,7 +449,7 @@ func (m *StrStrMap) UnmarshalJSON(b []byte) error {
if m.data == nil {
m.data = make(map[string]string)
}
if err := json.Unmarshal(b, &m.data); err != nil {
if err := json.UnmarshalUseNumber(b, &m.data); err != nil {
return err
}
return nil

View File

@ -530,7 +530,7 @@ func (m *ListMap) UnmarshalJSON(b []byte) error {
m.list = glist.New()
}
var data map[string]interface{}
if err := json.Unmarshal(b, &data); err != nil {
if err := json.UnmarshalUseNumber(b, &data); err != nil {
return err
}
for key, value := range data {

View File

@ -255,7 +255,7 @@ func Test_AnyAnyMap_Json(t *testing.T) {
t.Assert(err, nil)
m := gmap.New()
err = json.Unmarshal(b, m)
err = json.UnmarshalUseNumber(b, m)
t.Assert(err, nil)
t.Assert(m.Get("k1"), data["k1"])
t.Assert(m.Get("k2"), data["k2"])
@ -269,7 +269,7 @@ func Test_AnyAnyMap_Json(t *testing.T) {
t.Assert(err, nil)
var m gmap.Map
err = json.Unmarshal(b, &m)
err = json.UnmarshalUseNumber(b, &m)
t.Assert(err, nil)
t.Assert(m.Get("k1"), data["k1"])
t.Assert(m.Get("k2"), data["k2"])

View File

@ -245,7 +245,7 @@ func Test_IntAnyMap_Json(t *testing.T) {
t.Assert(err, nil)
m := gmap.NewIntAnyMap()
err = json.Unmarshal(b, m)
err = json.UnmarshalUseNumber(b, m)
t.Assert(err, nil)
t.Assert(m.Get(1), data[1])
t.Assert(m.Get(2), data[2])

View File

@ -251,7 +251,7 @@ func Test_IntIntMap_Json(t *testing.T) {
t.Assert(err, nil)
m := gmap.NewIntIntMap()
err = json.Unmarshal(b, m)
err = json.UnmarshalUseNumber(b, m)
t.Assert(err, nil)
t.Assert(m.Get(1), data[1])
t.Assert(m.Get(2), data[2])

View File

@ -249,7 +249,7 @@ func Test_IntStrMap_Json(t *testing.T) {
t.Assert(err, nil)
m := gmap.NewIntStrMap()
err = json.Unmarshal(b, m)
err = json.UnmarshalUseNumber(b, m)
t.Assert(err, nil)
t.Assert(m.Get(1), data[1])
t.Assert(m.Get(2), data[2])

View File

@ -204,7 +204,7 @@ func Test_ListMap_Json(t *testing.T) {
t.Assert(err, nil)
m := gmap.NewListMap()
err = json.Unmarshal(b, m)
err = json.UnmarshalUseNumber(b, m)
t.Assert(err, nil)
t.Assert(m.Get("k1"), data["k1"])
t.Assert(m.Get("k2"), data["k2"])
@ -219,7 +219,7 @@ func Test_ListMap_Json(t *testing.T) {
t.Assert(err, nil)
var m gmap.ListMap
err = json.Unmarshal(b, &m)
err = json.UnmarshalUseNumber(b, &m)
t.Assert(err, nil)
t.Assert(m.Get("k1"), data["k1"])
t.Assert(m.Get("k2"), data["k2"])

View File

@ -243,7 +243,7 @@ func Test_StrAnyMap_Json(t *testing.T) {
t.Assert(err, nil)
m := gmap.NewStrAnyMap()
err = json.Unmarshal(b, m)
err = json.UnmarshalUseNumber(b, m)
t.Assert(err, nil)
t.Assert(m.Get("k1"), data["k1"])
t.Assert(m.Get("k2"), data["k2"])
@ -257,7 +257,7 @@ func Test_StrAnyMap_Json(t *testing.T) {
t.Assert(err, nil)
var m gmap.StrAnyMap
err = json.Unmarshal(b, &m)
err = json.UnmarshalUseNumber(b, &m)
t.Assert(err, nil)
t.Assert(m.Get("k1"), data["k1"])
t.Assert(m.Get("k2"), data["k2"])

View File

@ -247,7 +247,7 @@ func Test_StrIntMap_Json(t *testing.T) {
t.Assert(err, nil)
m := gmap.NewStrIntMap()
err = json.Unmarshal(b, m)
err = json.UnmarshalUseNumber(b, m)
t.Assert(err, nil)
t.Assert(m.Get("k1"), data["k1"])
t.Assert(m.Get("k2"), data["k2"])
@ -261,7 +261,7 @@ func Test_StrIntMap_Json(t *testing.T) {
t.Assert(err, nil)
var m gmap.StrIntMap
err = json.Unmarshal(b, &m)
err = json.UnmarshalUseNumber(b, &m)
t.Assert(err, nil)
t.Assert(m.Get("k1"), data["k1"])
t.Assert(m.Get("k2"), data["k2"])

View File

@ -244,7 +244,7 @@ func Test_StrStrMap_Json(t *testing.T) {
t.Assert(err, nil)
m := gmap.NewStrStrMap()
err = json.Unmarshal(b, m)
err = json.UnmarshalUseNumber(b, m)
t.Assert(err, nil)
t.Assert(m.Get("k1"), data["k1"])
t.Assert(m.Get("k2"), data["k2"])
@ -258,7 +258,7 @@ func Test_StrStrMap_Json(t *testing.T) {
t.Assert(err, nil)
var m gmap.StrStrMap
err = json.Unmarshal(b, &m)
err = json.UnmarshalUseNumber(b, &m)
t.Assert(err, nil)
t.Assert(m.Get("k1"), data["k1"])
t.Assert(m.Get("k2"), data["k2"])

View File

@ -188,7 +188,7 @@ func Test_TreeMap_Json(t *testing.T) {
t.Assert(err, nil)
m := gmap.NewTreeMap(gutil.ComparatorString)
err = json.Unmarshal(b, m)
err = json.UnmarshalUseNumber(b, m)
t.Assert(err, nil)
t.Assert(m.Get("k1"), data["k1"])
t.Assert(m.Get("k2"), data["k2"])
@ -202,7 +202,7 @@ func Test_TreeMap_Json(t *testing.T) {
t.Assert(err, nil)
var m gmap.TreeMap
err = json.Unmarshal(b, &m)
err = json.UnmarshalUseNumber(b, &m)
t.Assert(err, nil)
t.Assert(m.Get("k1"), data["k1"])
t.Assert(m.Get("k2"), data["k2"])

View File

@ -35,10 +35,8 @@ type Queue struct {
}
const (
// Size for queue buffer.
gDEFAULT_QUEUE_SIZE = 10000
// Max batch size per-fetching from list.
gDEFAULT_MAX_BATCH_SIZE = 10
defaultQueueSize = 10000 // Size for queue buffer.
defaultBatchSize = 10 // Max batch size per-fetching from list.
)
// New returns an empty queue object.
@ -54,7 +52,7 @@ func New(limit ...int) *Queue {
} else {
q.list = glist.New(true)
q.events = make(chan struct{}, math.MaxInt32)
q.C = make(chan interface{}, gDEFAULT_QUEUE_SIZE)
q.C = make(chan interface{}, defaultQueueSize)
go q.asyncLoopFromListToChannel()
}
return q
@ -72,8 +70,8 @@ func (q *Queue) asyncLoopFromListToChannel() {
<-q.events
for !q.closed.Val() {
if length := q.list.Len(); length > 0 {
if length > gDEFAULT_MAX_BATCH_SIZE {
length = gDEFAULT_MAX_BATCH_SIZE
if length > defaultBatchSize {
length = defaultBatchSize
}
for _, v := range q.list.PopFronts(length) {
// When q.C is closed, it will panic here, especially q.C is being blocked for writing.
@ -101,7 +99,7 @@ func (q *Queue) Push(v interface{}) {
q.C <- v
} else {
q.list.PushBack(v)
if len(q.events) < gDEFAULT_QUEUE_SIZE {
if len(q.events) < defaultQueueSize {
q.events <- struct{}{}
}
}
@ -124,14 +122,14 @@ func (q *Queue) Close() {
if q.limit > 0 {
close(q.C)
}
for i := 0; i < gDEFAULT_MAX_BATCH_SIZE; i++ {
for i := 0; i < defaultBatchSize; i++ {
q.Pop()
}
}
// Len returns the length of the queue.
// Note that the result might not be accurate as there's a
// asynchronize channel reading the list constantly.
// asynchronous channel reading the list constantly.
func (q *Queue) Len() (length int) {
if q.list != nil {
length += q.list.Len()

View File

@ -477,7 +477,7 @@ func (set *Set) UnmarshalJSON(b []byte) error {
set.data = make(map[interface{}]struct{})
}
var array []interface{}
if err := json.Unmarshal(b, &array); err != nil {
if err := json.UnmarshalUseNumber(b, &array); err != nil {
return err
}
for _, v := range array {
@ -496,7 +496,7 @@ func (set *Set) UnmarshalValue(value interface{}) (err error) {
var array []interface{}
switch value.(type) {
case string, []byte:
err = json.Unmarshal(gconv.Bytes(value), &array)
err = json.UnmarshalUseNumber(gconv.Bytes(value), &array)
default:
array = gconv.SliceAny(value)
}

View File

@ -437,7 +437,7 @@ func (set *IntSet) UnmarshalJSON(b []byte) error {
set.data = make(map[int]struct{})
}
var array []int
if err := json.Unmarshal(b, &array); err != nil {
if err := json.UnmarshalUseNumber(b, &array); err != nil {
return err
}
for _, v := range array {
@ -456,7 +456,7 @@ func (set *IntSet) UnmarshalValue(value interface{}) (err error) {
var array []int
switch value.(type) {
case string, []byte:
err = json.Unmarshal(gconv.Bytes(value), &array)
err = json.UnmarshalUseNumber(gconv.Bytes(value), &array)
default:
array = gconv.SliceInt(value)
}

View File

@ -465,7 +465,7 @@ func (set *StrSet) UnmarshalJSON(b []byte) error {
set.data = make(map[string]struct{})
}
var array []string
if err := json.Unmarshal(b, &array); err != nil {
if err := json.UnmarshalUseNumber(b, &array); err != nil {
return err
}
for _, v := range array {
@ -484,7 +484,7 @@ func (set *StrSet) UnmarshalValue(value interface{}) (err error) {
var array []string
switch value.(type) {
case string, []byte:
err = json.Unmarshal(gconv.Bytes(value), &array)
err = json.UnmarshalUseNumber(gconv.Bytes(value), &array)
default:
array = gconv.SliceStr(value)
}

View File

@ -327,7 +327,7 @@ func TestSet_Json(t *testing.T) {
t.Assert(err1, err2)
a2 := gset.New()
err2 = json.Unmarshal(b2, &a2)
err2 = json.UnmarshalUseNumber(b2, &a2)
t.Assert(err2, nil)
t.Assert(a2.Contains("a"), true)
t.Assert(a2.Contains("b"), true)
@ -336,7 +336,7 @@ func TestSet_Json(t *testing.T) {
t.Assert(a2.Contains("e"), false)
var a3 gset.Set
err := json.Unmarshal(b2, &a3)
err := json.UnmarshalUseNumber(b2, &a3)
t.Assert(err, nil)
t.Assert(a3.Contains("a"), true)
t.Assert(a3.Contains("b"), true)

View File

@ -358,7 +358,7 @@ func TestIntSet_Json(t *testing.T) {
t.Assert(err1, err2)
a2 := gset.NewIntSet()
err2 = json.Unmarshal(b2, &a2)
err2 = json.UnmarshalUseNumber(b2, &a2)
t.Assert(err2, nil)
t.Assert(a2.Contains(1), true)
t.Assert(a2.Contains(2), true)
@ -367,7 +367,7 @@ func TestIntSet_Json(t *testing.T) {
t.Assert(a2.Contains(5), false)
var a3 gset.IntSet
err := json.Unmarshal(b2, &a3)
err := json.UnmarshalUseNumber(b2, &a3)
t.Assert(err, nil)
t.Assert(a2.Contains(1), true)
t.Assert(a2.Contains(2), true)

View File

@ -404,7 +404,7 @@ func TestStrSet_Json(t *testing.T) {
t.Assert(err1, err2)
a2 := gset.NewStrSet()
err2 = json.Unmarshal(b2, &a2)
err2 = json.UnmarshalUseNumber(b2, &a2)
t.Assert(err2, nil)
t.Assert(a2.Contains("a"), true)
t.Assert(a2.Contains("b"), true)
@ -413,7 +413,7 @@ func TestStrSet_Json(t *testing.T) {
t.Assert(a2.Contains("e"), false)
var a3 gset.StrSet
err := json.Unmarshal(b2, &a3)
err := json.UnmarshalUseNumber(b2, &a3)
t.Assert(err, nil)
t.Assert(a3.Contains("a"), true)
t.Assert(a3.Contains("b"), true)

View File

@ -937,7 +937,7 @@ func (tree *RedBlackTree) UnmarshalJSON(b []byte) error {
tree.comparator = gutil.ComparatorString
}
var data map[string]interface{}
if err := json.Unmarshal(b, &data); err != nil {
if err := json.UnmarshalUseNumber(b, &data); err != nil {
return err
}
for k, v := range data {

View File

@ -58,7 +58,7 @@ func (v *Interface) MarshalJSON() ([]byte, error) {
// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal.
func (v *Interface) UnmarshalJSON(b []byte) error {
var i interface{}
err := json.Unmarshal(b, &i)
err := json.UnmarshalUseNumber(b, &i)
if err != nil {
return err
}

View File

@ -55,16 +55,16 @@ func Test_Bool_JSON(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var err error
i := gtype.NewBool()
err = json.Unmarshal([]byte("true"), &i)
err = json.UnmarshalUseNumber([]byte("true"), &i)
t.Assert(err, nil)
t.Assert(i.Val(), true)
err = json.Unmarshal([]byte("false"), &i)
err = json.UnmarshalUseNumber([]byte("false"), &i)
t.Assert(err, nil)
t.Assert(i.Val(), false)
err = json.Unmarshal([]byte("1"), &i)
err = json.UnmarshalUseNumber([]byte("1"), &i)
t.Assert(err, nil)
t.Assert(i.Val(), true)
err = json.Unmarshal([]byte("0"), &i)
err = json.UnmarshalUseNumber([]byte("0"), &i)
t.Assert(err, nil)
t.Assert(i.Val(), false)
})
@ -78,7 +78,7 @@ func Test_Bool_JSON(t *testing.T) {
t.Assert(b1, b2)
i2 := gtype.NewBool()
err := json.Unmarshal(b2, &i2)
err := json.UnmarshalUseNumber(b2, &i2)
t.Assert(err, nil)
t.Assert(i2.Val(), i.Val())
})
@ -91,7 +91,7 @@ func Test_Bool_JSON(t *testing.T) {
t.Assert(b1, b2)
i2 := gtype.NewBool()
err := json.Unmarshal(b2, &i2)
err := json.UnmarshalUseNumber(b2, &i2)
t.Assert(err, nil)
t.Assert(i2.Val(), i.Val())
})

View File

@ -53,7 +53,7 @@ func Test_Byte_JSON(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var err error
i := gtype.NewByte()
err = json.Unmarshal([]byte("49"), &i)
err = json.UnmarshalUseNumber([]byte("49"), &i)
t.Assert(err, nil)
t.Assert(i.Val(), "49")
})

View File

@ -39,7 +39,7 @@ func Test_Bytes_JSON(t *testing.T) {
t.Assert(b1, b2)
i2 := gtype.NewBytes()
err := json.Unmarshal(b2, &i2)
err := json.UnmarshalUseNumber(b2, &i2)
t.Assert(err, nil)
t.Assert(i2.Val(), b)
})

View File

@ -40,7 +40,7 @@ func Test_Float32_JSON(t *testing.T) {
t.Assert(b1, b2)
i2 := gtype.NewFloat32()
err := json.Unmarshal(b2, &i2)
err := json.UnmarshalUseNumber(b2, &i2)
t.Assert(err, nil)
t.Assert(i2.Val(), v)
})

View File

@ -38,7 +38,7 @@ func Test_Float64_JSON(t *testing.T) {
t.Assert(b1, b2)
i2 := gtype.NewFloat64()
err := json.Unmarshal(b2, &i2)
err := json.UnmarshalUseNumber(b2, &i2)
t.Assert(err, nil)
t.Assert(i2.Val(), v)
})

View File

@ -51,7 +51,7 @@ func Test_Int32_JSON(t *testing.T) {
t.Assert(b1, b2)
i2 := gtype.NewInt32()
err := json.Unmarshal(b2, &i2)
err := json.UnmarshalUseNumber(b2, &i2)
t.Assert(err, nil)
t.Assert(i2.Val(), v)
})

View File

@ -50,7 +50,7 @@ func Test_Int64_JSON(t *testing.T) {
t.Assert(b1, b2)
i2 := gtype.NewInt64()
err := json.Unmarshal(b2, &i2)
err := json.UnmarshalUseNumber(b2, &i2)
t.Assert(err, nil)
t.Assert(i2.Val(), i)
})

View File

@ -50,7 +50,7 @@ func Test_Int_JSON(t *testing.T) {
t.Assert(b1, b2)
i2 := gtype.NewInt()
err := json.Unmarshal(b2, &i2)
err := json.UnmarshalUseNumber(b2, &i2)
t.Assert(err, nil)
t.Assert(i2.Val(), v)
})

View File

@ -40,7 +40,7 @@ func Test_Interface_JSON(t *testing.T) {
t.Assert(b1, b2)
i2 := gtype.New()
err := json.Unmarshal(b2, &i2)
err := json.UnmarshalUseNumber(b2, &i2)
t.Assert(err, nil)
t.Assert(i2.Val(), s)
})

View File

@ -38,7 +38,7 @@ func Test_String_JSON(t *testing.T) {
t.Assert(b1, b2)
i2 := gtype.NewString()
err := json.Unmarshal(b2, &i2)
err := json.UnmarshalUseNumber(b2, &i2)
t.Assert(err, nil)
t.Assert(i2.Val(), s)
})

View File

@ -50,7 +50,7 @@ func Test_Uint32_JSON(t *testing.T) {
t.Assert(b1, b2)
i2 := gtype.NewUint32()
err := json.Unmarshal(b2, &i2)
err := json.UnmarshalUseNumber(b2, &i2)
t.Assert(err, nil)
t.Assert(i2.Val(), i)
})

View File

@ -55,7 +55,7 @@ func Test_Uint64_JSON(t *testing.T) {
t.Assert(b1, b2)
i2 := gtype.NewUint64()
err := json.Unmarshal(b2, &i2)
err := json.UnmarshalUseNumber(b2, &i2)
t.Assert(err, nil)
t.Assert(i2.Val(), i)
})

View File

@ -49,7 +49,7 @@ func Test_Uint_JSON(t *testing.T) {
t.Assert(b1, b2)
i2 := gtype.NewUint()
err := json.Unmarshal(b2, &i2)
err := json.UnmarshalUseNumber(b2, &i2)
t.Assert(err, nil)
t.Assert(i2.Val(), i)
})

View File

@ -189,7 +189,7 @@ func (v *Var) MarshalJSON() ([]byte, error) {
// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal.
func (v *Var) UnmarshalJSON(b []byte) error {
var i interface{}
err := json.Unmarshal(b, &i)
err := json.UnmarshalUseNumber(b, &i)
if err != nil {
return err
}

View File

@ -41,7 +41,7 @@ func TestVar_Json(t *testing.T) {
b, err := json.Marshal(s)
t.Assert(err, nil)
err = json.Unmarshal(b, v)
err = json.UnmarshalUseNumber(b, v)
t.Assert(err, nil)
t.Assert(v.String(), s)
})
@ -52,7 +52,7 @@ func TestVar_Json(t *testing.T) {
b, err := json.Marshal(s)
t.Assert(err, nil)
err = json.Unmarshal(b, &v)
err = json.UnmarshalUseNumber(b, &v)
t.Assert(err, nil)
t.Assert(v.String(), s)
})

View File

@ -11,9 +11,10 @@ import (
"context"
"database/sql"
"fmt"
"time"
"github.com/gogf/gf/errors/gerror"
"github.com/gogf/gf/os/gcmd"
"time"
"github.com/gogf/gf/container/gvar"
"github.com/gogf/gf/internal/intlog"
@ -32,11 +33,12 @@ type DB interface {
// Model creation.
// ===========================================================================
// Table function is deprecated, use Model instead.
// The DB interface is designed not only for
// relational databases but also for NoSQL databases in the future. The name
// "Table" is not proper for that purpose any more.
// Deprecated, use Model instead.
Table(table ...string) *Model
// Also see Core.Table.
Table(tableNameOrStruct ...interface{}) *Model
// Model creates and returns a new ORM model from given schema.
// The parameter `table` can be more than one table names, and also alias name, like:
@ -46,150 +48,144 @@ type DB interface {
// Model("user, user_detail")
// Model("user u, user_detail ud")
// 2. Model name with alias: Model("user", "u")
Model(table ...string) *Model
// Also see Core.Model.
Model(tableNameOrStruct ...interface{}) *Model
// Schema creates and returns a schema.
// Also see Core.Schema.
Schema(schema string) *Schema
// With creates and returns an ORM model based on meta data of given object.
With(object interface{}) *Model
// Also see Core.With.
With(objects ...interface{}) *Model
// Open creates a raw connection object for database with given node configuration.
// Note that it is not recommended using the this function manually.
// Also see DriverMysql.Open.
Open(config *ConfigNode) (*sql.DB, error)
// Ctx is a chaining function, which creates and returns a new DB that is a shallow copy
// of current DB object and with given context in it.
// Note that this returned DB object can be used only once, so do not assign it to
// a global or package variable for long using.
// Also see Core.Ctx.
Ctx(ctx context.Context) DB
// ===========================================================================
// Query APIs.
// ===========================================================================
Query(sql string, args ...interface{}) (*sql.Rows, error)
Exec(sql string, args ...interface{}) (sql.Result, error)
Prepare(sql string, execOnMaster ...bool) (*Stmt, error)
Query(sql string, args ...interface{}) (*sql.Rows, error) // See Core.Query.
Exec(sql string, args ...interface{}) (sql.Result, error) // See Core.Exec.
Prepare(sql string, execOnMaster ...bool) (*Stmt, error) // See Core.Prepare.
// ===========================================================================
// Common APIs for CURD.
// ===========================================================================
Insert(table string, data interface{}, batch ...int) (sql.Result, error)
InsertIgnore(table string, data interface{}, batch ...int) (sql.Result, error)
Replace(table string, data interface{}, batch ...int) (sql.Result, error)
Save(table string, data interface{}, batch ...int) (sql.Result, error)
Insert(table string, data interface{}, batch ...int) (sql.Result, error) // See Core.Insert.
InsertIgnore(table string, data interface{}, batch ...int) (sql.Result, error) // See Core.InsertIgnore.
InsertAndGetId(table string, data interface{}, batch ...int) (int64, error) // See Core.InsertAndGetId.
Replace(table string, data interface{}, batch ...int) (sql.Result, error) // See Core.Replace.
Save(table string, data interface{}, batch ...int) (sql.Result, error) // See Core.Save.
BatchInsert(table string, list interface{}, batch ...int) (sql.Result, error)
BatchReplace(table string, list interface{}, batch ...int) (sql.Result, error)
BatchSave(table string, list interface{}, batch ...int) (sql.Result, error)
BatchInsert(table string, list interface{}, batch ...int) (sql.Result, error) // See Core.BatchInsert.
BatchReplace(table string, list interface{}, batch ...int) (sql.Result, error) // See Core.BatchReplace.
BatchSave(table string, list interface{}, batch ...int) (sql.Result, error) // See Core.BatchSave.
Update(table string, data interface{}, condition interface{}, args ...interface{}) (sql.Result, error)
Delete(table string, condition interface{}, args ...interface{}) (sql.Result, error)
Update(table string, data interface{}, condition interface{}, args ...interface{}) (sql.Result, error) // See Core.Update.
Delete(table string, condition interface{}, args ...interface{}) (sql.Result, error) // See Core.Delete.
// ===========================================================================
// Internal APIs for CURD, which can be overwrote for custom CURD implements.
// ===========================================================================
DoQuery(link Link, sql string, args ...interface{}) (rows *sql.Rows, err error)
DoGetAll(link Link, sql string, args ...interface{}) (result Result, err error)
DoExec(link Link, sql string, args ...interface{}) (result sql.Result, err error)
DoPrepare(link Link, sql string) (*Stmt, error)
DoInsert(link Link, table string, data interface{}, option int, batch ...int) (result sql.Result, err error)
DoBatchInsert(link Link, table string, list interface{}, option int, batch ...int) (result sql.Result, err error)
DoUpdate(link Link, table string, data interface{}, condition string, args ...interface{}) (result sql.Result, err error)
DoDelete(link Link, table string, condition string, args ...interface{}) (result sql.Result, err error)
DoQuery(ctx context.Context, link Link, sql string, args ...interface{}) (rows *sql.Rows, err error) // See Core.DoQuery.
DoExec(ctx context.Context, link Link, sql string, args ...interface{}) (result sql.Result, err error) // See Core.DoExec.
DoPrepare(ctx context.Context, link Link, sql string) (*Stmt, error) // See Core.DoPrepare.
DoGetAll(ctx context.Context, link Link, sql string, args ...interface{}) (result Result, err error) // See Core.DoGetAll.
DoInsert(ctx context.Context, link Link, table string, data interface{}, option int, batch ...int) (result sql.Result, err error) // See Core.DoInsert.
DoBatchInsert(ctx context.Context, link Link, table string, list interface{}, option int, batch ...int) (result sql.Result, err error) // See Core.DoBatchInsert.
DoUpdate(ctx context.Context, link Link, table string, data interface{}, condition string, args ...interface{}) (result sql.Result, err error) // See Core.DoUpdate.
DoDelete(ctx context.Context, link Link, table string, condition string, args ...interface{}) (result sql.Result, err error) // See Core.DoDelete.
// ===========================================================================
// Query APIs for convenience purpose.
// ===========================================================================
GetAll(sql string, args ...interface{}) (Result, error)
GetOne(sql string, args ...interface{}) (Record, error)
GetValue(sql string, args ...interface{}) (Value, error)
GetArray(sql string, args ...interface{}) ([]Value, error)
GetCount(sql string, args ...interface{}) (int, error)
GetStruct(objPointer interface{}, sql string, args ...interface{}) error
GetStructs(objPointerSlice interface{}, sql string, args ...interface{}) error
GetScan(objPointer interface{}, sql string, args ...interface{}) error
GetAll(sql string, args ...interface{}) (Result, error) // See Core.GetAll.
GetOne(sql string, args ...interface{}) (Record, error) // See Core.GetOne.
GetValue(sql string, args ...interface{}) (Value, error) // See Core.GetValue.
GetArray(sql string, args ...interface{}) ([]Value, error) // See Core.GetArray.
GetCount(sql string, args ...interface{}) (int, error) // See Core.GetCount.
GetStruct(objPointer interface{}, sql string, args ...interface{}) error // See Core.GetStruct.
GetStructs(objPointerSlice interface{}, sql string, args ...interface{}) error // See Core.GetStructs.
GetScan(objPointer interface{}, sql string, args ...interface{}) error // See Core.GetScan.
// ===========================================================================
// Master/Slave specification support.
// ===========================================================================
Master() (*sql.DB, error)
Slave() (*sql.DB, error)
Master(schema ...string) (*sql.DB, error) // See Core.Master.
Slave(schema ...string) (*sql.DB, error) // See Core.Slave.
// ===========================================================================
// Ping-Pong.
// ===========================================================================
PingMaster() error
PingSlave() error
PingMaster() error // See Core.PingMaster.
PingSlave() error // See Core.PingSlave.
// ===========================================================================
// Transaction.
// ===========================================================================
Begin() (*TX, error)
Transaction(f func(tx *TX) error) (err error)
Begin() (*TX, error) // See Core.Begin.
Transaction(ctx context.Context, f func(ctx context.Context, tx *TX) error) error // See Core.Transaction.
// ===========================================================================
// Configuration methods.
// ===========================================================================
GetCache() *gcache.Cache
SetDebug(debug bool)
GetDebug() bool
SetSchema(schema string)
GetSchema() string
GetPrefix() string
GetGroup() string
SetDryRun(dryrun bool)
GetDryRun() bool
SetLogger(logger *glog.Logger)
GetLogger() *glog.Logger
GetConfig() *ConfigNode
SetMaxIdleConnCount(n int)
SetMaxOpenConnCount(n int)
SetMaxConnLifetime(d time.Duration)
GetCache() *gcache.Cache // See Core.GetCache.
SetDebug(debug bool) // See Core.SetDebug.
GetDebug() bool // See Core.GetDebug.
SetSchema(schema string) // See Core.SetSchema.
GetSchema() string // See Core.GetSchema.
GetPrefix() string // See Core.GetPrefix.
GetGroup() string // See Core.GetGroup.
SetDryRun(enabled bool) // See Core.SetDryRun.
GetDryRun() bool // See Core.GetDryRun.
SetLogger(logger *glog.Logger) // See Core.SetLogger.
GetLogger() *glog.Logger // See Core.GetLogger.
GetConfig() *ConfigNode // See Core.GetConfig.
SetMaxIdleConnCount(n int) // See Core.SetMaxIdleConnCount.
SetMaxOpenConnCount(n int) // See Core.SetMaxOpenConnCount.
SetMaxConnLifeTime(d time.Duration) // See Core.SetMaxConnLifeTime.
// ===========================================================================
// Utility methods.
// ===========================================================================
GetCtx() context.Context
GetChars() (charLeft string, charRight string)
GetMaster(schema ...string) (*sql.DB, error)
GetSlave(schema ...string) (*sql.DB, error)
QuoteWord(s string) string
QuoteString(s string) string
QuotePrefixTableName(table string) string
Tables(schema ...string) (tables []string, err error)
TableFields(table string, schema ...string) (map[string]*TableField, error)
HasTable(name string) (bool, error)
FilteredLinkInfo() string
GetCtx() context.Context // See Core.GetCtx.
GetCore() *Core // See Core.GetCore
GetChars() (charLeft string, charRight string) // See Core.GetChars.
Tables(ctx context.Context, schema ...string) (tables []string, err error) // See Core.Tables.
TableFields(ctx context.Context, table string, schema ...string) (map[string]*TableField, error) // See Core.TableFields.
FilteredLinkInfo() string // See Core.FilteredLinkInfo.
// HandleSqlBeforeCommit is a hook function, which deals with the sql string before
// it's committed to underlying driver. The parameter `link` specifies the current
// database connection operation object. You can modify the sql string `sql` and its
// arguments `args` as you wish before they're committed to driver.
HandleSqlBeforeCommit(link Link, sql string, args []interface{}) (string, []interface{})
// ===========================================================================
// Internal methods, for internal usage purpose, you do not need consider it.
// ===========================================================================
mappingAndFilterData(schema, table string, data map[string]interface{}, filter bool) (map[string]interface{}, error)
convertFieldValueToLocalValue(fieldValue interface{}, fieldType string) interface{}
convertRowsToResult(rows *sql.Rows) (Result, error)
// Also see Core.HandleSqlBeforeCommit.
HandleSqlBeforeCommit(ctx context.Context, link Link, sql string, args []interface{}) (string, []interface{})
}
// Core is the base struct for database management.
type Core struct {
db DB // DB interface object.
ctx context.Context // Context for chaining operation only.
ctx context.Context // Context for chaining operation only. Do not set a default value in Core initialization.
group string // Configuration group name.
debug *gtype.Bool // Enable debug mode for the database, which can be changed in runtime.
cache *gcache.Cache // Cache manager, SQL result cache only.
@ -204,16 +200,28 @@ type Driver interface {
New(core *Core, node *ConfigNode) (DB, error)
}
// Link is a common database function wrapper interface.
type Link interface {
Query(sql string, args ...interface{}) (*sql.Rows, error)
Exec(sql string, args ...interface{}) (sql.Result, error)
Prepare(sql string) (*sql.Stmt, error)
QueryContext(ctx context.Context, sql string, args ...interface{}) (*sql.Rows, error)
ExecContext(ctx context.Context, sql string, args ...interface{}) (sql.Result, error)
PrepareContext(ctx context.Context, sql string) (*sql.Stmt, error)
IsTransaction() bool
}
// Sql is the sql recording struct.
type Sql struct {
Sql string // SQL string(may contain reserved char '?').
Type string // SQL operation type.
Args []interface{} // Arguments for this sql.
Format string // Formatted sql which contains arguments in the sql.
Error error // Execution result.
Start int64 // Start execution timestamp in milliseconds.
End int64 // End execution timestamp in milliseconds.
Group string // Group is the group name of the configuration that the sql is executed from.
Sql string // SQL string(may contain reserved char '?').
Type string // SQL operation type.
Args []interface{} // Arguments for this sql.
Format string // Formatted sql which contains arguments in the sql.
Error error // Execution result.
Start int64 // Start execution timestamp in milliseconds.
End int64 // End execution timestamp in milliseconds.
Group string // Group is the group name of the configuration that the sql is executed from.
IsTransaction bool // IsTransaction marks whether this sql is executed in transaction.
}
// TableField is the struct for table field.
@ -228,16 +236,6 @@ type TableField struct {
Comment string // Comment.
}
// Link is a common database function wrapper interface.
type Link interface {
Query(sql string, args ...interface{}) (*sql.Rows, error)
Exec(sql string, args ...interface{}) (sql.Result, error)
Prepare(sql string) (*sql.Stmt, error)
QueryContext(ctx context.Context, sql string, args ...interface{}) (*sql.Rows, error)
ExecContext(ctx context.Context, sql string, args ...interface{}) (sql.Result, error)
PrepareContext(ctx context.Context, sql string) (*sql.Stmt, error)
}
// Counter is the type for update count.
type Counter struct {
Field string
@ -289,16 +287,19 @@ var (
// regularFieldNameRegPattern is the regular expression pattern for a string
// which is a regular field name of table.
regularFieldNameRegPattern = `^[\w\.\-\_]+$`
regularFieldNameRegPattern = `^[\w\.\-]+$`
// regularFieldNameWithoutDotRegPattern is similar to regularFieldNameRegPattern but not allows '.'.
// Note that, although some databases allow char '.' in the field name, but it here does not allow '.'
// in the field name as it conflicts with "db.table.field" pattern in SOME situations.
regularFieldNameWithoutDotRegPattern = `^[\w\-\_]+$`
regularFieldNameWithoutDotRegPattern = `^[\w\-]+$`
// internalCache is the memory cache for internal usage.
internalCache = gcache.New()
// tableFieldsMap caches the table information retrived from database.
tableFieldsMap = gmap.New(true)
// allDryRun sets dry-run feature for all database connections.
// It is commonly used for command options for convenience.
allDryRun = false
@ -327,7 +328,7 @@ func New(group ...string) (db DB, err error) {
defer configs.RUnlock()
if len(configs.config) < 1 {
return nil, gerror.New("empty database configuration")
return nil, gerror.New("database configuration is empty, please set the database configuration before using")
}
if _, ok := configs.config[groupName]; ok {
if node, err := getConfigNodeByGroup(groupName, true); err == nil {
@ -346,13 +347,19 @@ func New(group ...string) (db DB, err error) {
}
return c.db, nil
} else {
return nil, gerror.New(fmt.Sprintf(`unsupported database type "%s"`, node.Type))
return nil, gerror.Newf(
`cannot find database driver for specified database type "%s", did you misspell type name "%s" or forget importing the database driver?`,
node.Type, node.Type,
)
}
} else {
return nil, err
}
} else {
return nil, gerror.New(fmt.Sprintf(`database configuration node "%s" is not found`, groupName))
return nil, gerror.Newf(
`database configuration node "%s" is not found, did you misspell group name "%s" or miss the database configuration?`,
groupName, groupName,
)
}
}
@ -471,15 +478,26 @@ func (c *Core) getSqlDb(master bool, schema ...string) (sqlDb *sql.DB, err error
}
// Cache the underlying connection pool object by node.
v, _ := internalCache.GetOrSetFuncLock(node.String(), func() (interface{}, error) {
sqlDb, err = c.db.Open(node)
if err != nil {
intlog.Printf(`db open failed: %v, %+v`, err, node)
return nil, err
}
intlog.Printf(
`open new connection, master:%v, config:%+v, node:%+v`,
`open new connection, master:%#v, config:%#v, node:%#v`,
master, c.config, node,
)
defer func() {
if err != nil {
intlog.Printf(`open new connection failed: %v, %#v`, err, node)
} else {
intlog.Printf(
`open new connection success, master:%#v, config:%#v, node:%#v`,
master, c.config, node,
)
}
}()
sqlDb, err = c.db.Open(node)
if err != nil {
return nil, err
}
if c.config.MaxIdleConnCount > 0 {
sqlDb.SetMaxIdleConns(c.config.MaxIdleConnCount)
} else {
@ -490,13 +508,13 @@ func (c *Core) getSqlDb(master bool, schema ...string) (sqlDb *sql.DB, err error
} else {
sqlDb.SetMaxOpenConns(defaultMaxOpenConnCount)
}
if c.config.MaxConnLifetime > 0 {
if c.config.MaxConnLifeTime > 0 {
// Automatically checks whether MaxConnLifetime is configured using string like: "30s", "60s", etc.
// Or else it is configured just using number, which means value in seconds.
if c.config.MaxConnLifetime > time.Second {
sqlDb.SetConnMaxLifetime(c.config.MaxConnLifetime)
if c.config.MaxConnLifeTime > time.Second {
sqlDb.SetConnMaxLifetime(c.config.MaxConnLifeTime)
} else {
sqlDb.SetConnMaxLifetime(c.config.MaxConnLifetime * time.Second)
sqlDb.SetConnMaxLifetime(c.config.MaxConnLifeTime * time.Second)
}
} else {
sqlDb.SetConnMaxLifetime(defaultMaxConnLifeTime)

Some files were not shown because too many files have changed in this diff Show More