Merge branch 'master' into feat/render

This commit is contained in:
1911860538 2025-04-18 22:01:50 +08:00
commit af49958f8c
17 changed files with 132 additions and 76 deletions

View File

@ -33,9 +33,15 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest, macos-latest] os: [ubuntu-latest, macos-latest]
go: ["1.22", "1.23", "1.24"] go: ["1.23", "1.24"]
test-tags: test-tags:
["", "-tags nomsgpack", '-tags "sonic avx"', "-tags go_json", "-race"] [
"",
"-tags nomsgpack",
'--ldflags="-checklinkname=0" -tags "sonic avx"',
"-tags go_json",
"-race",
]
include: include:
- os: ubuntu-latest - os: ubuntu-latest
go-build: ~/.cache/go-build go-build: ~/.cache/go-build
@ -75,7 +81,3 @@ jobs:
uses: codecov/codecov-action@v4 uses: codecov/codecov-action@v4
with: with:
flags: ${{ matrix.os }},go-${{ matrix.go }},${{ matrix.test-tags }} flags: ${{ matrix.os }},go-${{ matrix.go }},${{ matrix.test-tags }}
- name: Format
if: matrix.go-version == '1.22.x'
run: diff -u <(echo -n) <(gofmt -d .)

View File

@ -7,7 +7,7 @@ linters:
- durationcheck - durationcheck
- errcheck - errcheck
- errorlint - errorlint
- exportloopref - copyloopvar
- gci - gci
- gofmt - gofmt
- goimports - goimports
@ -39,7 +39,6 @@ linters-settings:
perfsprint: perfsprint:
err-error: true err-error: true
errorf: true errorf: true
fiximports: true
int-conversion: true int-conversion: true
sprintf1: true sprintf1: true
strconcat: true strconcat: true

View File

@ -488,7 +488,7 @@
- [FIX] Refactor render - [FIX] Refactor render
- [FIX] Reworked tests - [FIX] Reworked tests
- [FIX] logger now supports cygwin - [FIX] logger now supports cygwin
- [FIX] Use X-Forwarded-For before X-Real-Ip - [FIX] Use X-Forwarded-For before X-Real-IP
- [FIX] time.Time binding (#904) - [FIX] time.Time binding (#904)
## Gin 1.1.4 ## Gin 1.1.4

View File

@ -30,7 +30,7 @@ If you need performance and good productivity, you will love Gin.
### Prerequisites ### Prerequisites
Gin requires [Go](https://go.dev/) version [1.22](https://go.dev/doc/devel/release#go1.22.0) or above. Gin requires [Go](https://go.dev/) version [1.23](https://go.dev/doc/devel/release#go1.23.0) or above.
### Getting Gin ### Getting Gin
@ -73,7 +73,7 @@ func main() {
To run the code, use the `go run` command, like: To run the code, use the `go run` command, like:
```sh ```sh
$ go run example.go go run example.go
``` ```
Then visit [`0.0.0.0:8080/ping`](http://0.0.0.0:8080/ping) in your browser to see the response! Then visit [`0.0.0.0:8080/ping`](http://0.0.0.0:8080/ping) in your browser to see the response!
@ -103,6 +103,7 @@ The documentation is also available on [gin-gonic.com](https://gin-gonic.com) in
- [Turkish](https://gin-gonic.com/tr/docs/) - [Turkish](https://gin-gonic.com/tr/docs/)
- [Persian](https://gin-gonic.com/fa/docs/) - [Persian](https://gin-gonic.com/fa/docs/)
- [Português](https://gin-gonic.com/pt/docs/) - [Português](https://gin-gonic.com/pt/docs/)
- [Russian](https://gin-gonic.com/ru/docs/)
### Articles ### Articles

View File

@ -69,15 +69,19 @@ type FooStructDisallowUnknownFields struct {
} }
type FooBarStructForTimeType struct { type FooBarStructForTimeType struct {
TimeFoo time.Time `form:"time_foo" time_format:"2006-01-02" time_utc:"1" time_location:"Asia/Chongqing"` TimeFoo time.Time `form:"time_foo" time_format:"2006-01-02" time_utc:"1" time_location:"Asia/Chongqing"`
TimeBar time.Time `form:"time_bar" time_format:"2006-01-02" time_utc:"1"` TimeBar time.Time `form:"time_bar" time_format:"2006-01-02" time_utc:"1"`
CreateTime time.Time `form:"createTime" time_format:"unixNano"` CreateTime time.Time `form:"createTime" time_format:"unixNano"`
UnixTime time.Time `form:"unixTime" time_format:"unix"` UnixTime time.Time `form:"unixTime" time_format:"unix"`
UnixMilliTime time.Time `form:"unixMilliTime" time_format:"unixmilli"`
UnixMicroTime time.Time `form:"unixMicroTime" time_format:"uNiXmiCrO"`
} }
type FooStructForTimeTypeNotUnixFormat struct { type FooStructForTimeTypeNotUnixFormat struct {
CreateTime time.Time `form:"createTime" time_format:"unixNano"` CreateTime time.Time `form:"createTime" time_format:"unixNano"`
UnixTime time.Time `form:"unixTime" time_format:"unix"` UnixTime time.Time `form:"unixTime" time_format:"unix"`
UnixMilliTime time.Time `form:"unixMilliTime" time_format:"unixMilli"`
UnixMicroTime time.Time `form:"unixMicroTime" time_format:"unixMicro"`
} }
type FooStructForTimeTypeNotFormat struct { type FooStructForTimeTypeNotFormat struct {
@ -265,10 +269,10 @@ func TestBindingFormDefaultValue2(t *testing.T) {
func TestBindingFormForTime(t *testing.T) { func TestBindingFormForTime(t *testing.T) {
testFormBindingForTime(t, http.MethodPost, testFormBindingForTime(t, http.MethodPost,
"/", "/", "/", "/",
"time_foo=2017-11-15&time_bar=&createTime=1562400033000000123&unixTime=1562400033", "bar2=foo") "time_foo=2017-11-15&time_bar=&createTime=1562400033000000123&unixTime=1562400033&unixMilliTime=1562400033001&unixMicroTime=1562400033000012", "bar2=foo")
testFormBindingForTimeNotUnixFormat(t, http.MethodPost, testFormBindingForTimeNotUnixFormat(t, http.MethodPost,
"/", "/", "/", "/",
"time_foo=2017-11-15&createTime=bad&unixTime=bad", "bar2=foo") "time_foo=2017-11-15&createTime=bad&unixTime=bad&unixMilliTime=bad&unixMicroTime=bad", "bar2=foo")
testFormBindingForTimeNotFormat(t, http.MethodPost, testFormBindingForTimeNotFormat(t, http.MethodPost,
"/", "/", "/", "/",
"time_foo=2017-11-15", "bar2=foo") "time_foo=2017-11-15", "bar2=foo")
@ -282,11 +286,11 @@ func TestBindingFormForTime(t *testing.T) {
func TestBindingFormForTime2(t *testing.T) { func TestBindingFormForTime2(t *testing.T) {
testFormBindingForTime(t, http.MethodGet, testFormBindingForTime(t, http.MethodGet,
"/?time_foo=2017-11-15&time_bar=&createTime=1562400033000000123&unixTime=1562400033", "/?bar2=foo", "/?time_foo=2017-11-15&time_bar=&createTime=1562400033000000123&unixTime=1562400033&unixMilliTime=1562400033001&unixMicroTime=1562400033000012", "/?bar2=foo",
"", "") "", "")
testFormBindingForTimeNotUnixFormat(t, http.MethodPost, testFormBindingForTimeNotUnixFormat(t, http.MethodPost,
"/", "/", "/", "/",
"time_foo=2017-11-15&createTime=bad&unixTime=bad", "bar2=foo") "time_foo=2017-11-15&createTime=bad&unixTime=bad&unixMilliTime=bad&unixMicroTime=bad", "bar2=foo")
testFormBindingForTimeNotFormat(t, http.MethodGet, testFormBindingForTimeNotFormat(t, http.MethodGet,
"/?time_foo=2017-11-15", "/?bar2=foo", "/?time_foo=2017-11-15", "/?bar2=foo",
"", "") "", "")
@ -952,6 +956,8 @@ func testFormBindingForTime(t *testing.T, method, path, badPath, body, badBody s
assert.Equal(t, "UTC", obj.TimeBar.Location().String()) assert.Equal(t, "UTC", obj.TimeBar.Location().String())
assert.Equal(t, int64(1562400033000000123), obj.CreateTime.UnixNano()) assert.Equal(t, int64(1562400033000000123), obj.CreateTime.UnixNano())
assert.Equal(t, int64(1562400033), obj.UnixTime.Unix()) assert.Equal(t, int64(1562400033), obj.UnixTime.Unix())
assert.Equal(t, int64(1562400033001), obj.UnixMilliTime.UnixMilli())
assert.Equal(t, int64(1562400033000012), obj.UnixMicroTime.UnixMicro())
obj = FooBarStructForTimeType{} obj = FooBarStructForTimeType{}
req = requestWithBody(method, badPath, badBody) req = requestWithBody(method, badPath, badBody)

View File

@ -398,18 +398,24 @@ func setTimeField(val string, structField reflect.StructField, value reflect.Val
} }
switch tf := strings.ToLower(timeFormat); tf { switch tf := strings.ToLower(timeFormat); tf {
case "unix", "unixnano": case "unix", "unixmilli", "unixmicro", "unixnano":
tv, err := strconv.ParseInt(val, 10, 64) tv, err := strconv.ParseInt(val, 10, 64)
if err != nil { if err != nil {
return err return err
} }
d := time.Duration(1) var t time.Time
if tf == "unixnano" { switch tf {
d = time.Second case "unix":
t = time.Unix(tv, 0)
case "unixmilli":
t = time.UnixMilli(tv)
case "unixmicro":
t = time.UnixMicro(tv)
default:
t = time.Unix(0, tv)
} }
t := time.Unix(tv/int64(d), tv%int64(d))
value.Set(reflect.ValueOf(t)) value.Set(reflect.ValueOf(t))
return nil return nil
} }

View File

@ -34,7 +34,7 @@ func (protobufBinding) BindBody(body []byte, obj any) error {
if err := proto.Unmarshal(body, msg); err != nil { if err := proto.Unmarshal(body, msg); err != nil {
return err return err
} }
// Here it's same to return validate(obj), but util now we can't add // Here it's same to return validate(obj), but until now we can't add
// `binding:""` to the struct which automatically generate by gen-proto // `binding:""` to the struct which automatically generate by gen-proto
return nil return nil
// return validate(obj) // return validate(obj)

View File

@ -31,5 +31,5 @@ func decodeToml(r io.Reader, obj any) error {
if err := decoder.Decode(obj); err != nil { if err := decoder.Decode(obj); err != nil {
return err return err
} }
return decoder.Decode(obj) return validate(obj)
} }

View File

@ -684,15 +684,15 @@ func (c *Context) SaveUploadedFile(file *multipart.FileHeader, dst string, perm
} }
defer src.Close() defer src.Close()
if len(perm) <= 0 { var mode os.FileMode = 0o750
perm = append(perm, 0o750) if len(perm) > 0 {
mode = perm[0]
} }
dir := filepath.Dir(dst)
if err = os.MkdirAll(filepath.Dir(dst), perm[0]); err != nil { if err = os.MkdirAll(dir, mode); err != nil {
return err return err
} }
if err = os.Chmod(dir, mode); err != nil {
if err = os.Chmod(filepath.Dir(dst), perm[0]); err != nil {
return err return err
} }
@ -889,7 +889,7 @@ func (c *Context) ShouldBindBodyWithPlain(obj any) error {
// ClientIP implements one best effort algorithm to return the real client IP. // ClientIP implements one best effort algorithm to return the real client IP.
// It calls c.RemoteIP() under the hood, to check if the remote IP is a trusted proxy or not. // It calls c.RemoteIP() under the hood, to check if the remote IP is a trusted proxy or not.
// If it is it will then try to parse the headers defined in Engine.RemoteIPHeaders (defaulting to [X-Forwarded-For, X-Real-Ip]). // If it is it will then try to parse the headers defined in Engine.RemoteIPHeaders (defaulting to [X-Forwarded-For, X-Real-IP]).
// If the headers are not syntactically valid OR the remote IP does not correspond to a trusted proxy, // If the headers are not syntactically valid OR the remote IP does not correspond to a trusted proxy,
// the remote IP (coming from Request.RemoteAddr) is returned. // the remote IP (coming from Request.RemoteAddr) is returned.
func (c *Context) ClientIP() string { func (c *Context) ClientIP() string {

View File

@ -78,7 +78,7 @@ func getMinVer(v string) (uint64, error) {
func debugPrintWARNINGDefault() { func debugPrintWARNINGDefault() {
if v, e := getMinVer(runtime.Version()); e == nil && v < ginSupportMinGoVer { if v, e := getMinVer(runtime.Version()); e == nil && v < ginSupportMinGoVer {
debugPrint(`[WARNING] Now Gin requires Go 1.22+. debugPrint(`[WARNING] Now Gin requires Go 1.23+.
`) `)
} }

View File

@ -106,7 +106,7 @@ func TestDebugPrintWARNINGDefault(t *testing.T) {
}) })
m, e := getMinVer(runtime.Version()) m, e := getMinVer(runtime.Version())
if e == nil && m < ginSupportMinGoVer { if e == nil && m < ginSupportMinGoVer {
assert.Equal(t, "[GIN-debug] [WARNING] Now Gin requires Go 1.22+.\n\n[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.\n\n", re) assert.Equal(t, "[GIN-debug] [WARNING] Now Gin requires Go 1.23+.\n\n[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.\n\n", re)
} else { } else {
assert.Equal(t, "[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.\n\n", re) assert.Equal(t, "[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.\n\n", re)
} }

View File

@ -70,7 +70,7 @@
### Build with json replacement ### Build with json replacement
Gin uses `encoding/json` as default json package but you can change it by build from other tags. Gin uses `encoding/json` as the default JSON package but you can change it by building from other tags.
[jsoniter](https://github.com/json-iterator/go) [jsoniter](https://github.com/json-iterator/go)
@ -84,7 +84,7 @@ go build -tags=jsoniter .
go build -tags=go_json . go build -tags=go_json .
``` ```
[sonic](https://github.com/bytedance/sonic) (you have to ensure that your cpu support avx instruction.) [sonic](https://github.com/bytedance/sonic) (you have to ensure that your cpu supports avx instruction.)
```sh ```sh
$ go build -tags="sonic avx" . $ go build -tags="sonic avx" .
@ -120,7 +120,7 @@ func main() {
router.HEAD("/someHead", head) router.HEAD("/someHead", head)
router.OPTIONS("/someOptions", options) router.OPTIONS("/someOptions", options)
// By default it serves on :8080 unless a // By default, it serves on :8080 unless a
// PORT environment variable was defined. // PORT environment variable was defined.
router.Run() router.Run()
// router.Run(":3000") for a hard coded port // router.Run(":3000") for a hard coded port
@ -172,7 +172,7 @@ func main() {
router := gin.Default() router := gin.Default()
// Query string parameters are parsed using the existing underlying request object. // Query string parameters are parsed using the existing underlying request object.
// The request responds to an url matching: /welcome?firstname=Jane&lastname=Doe // The request responds to a URL matching: /welcome?firstname=Jane&lastname=Doe
router.GET("/welcome", func(c *gin.Context) { router.GET("/welcome", func(c *gin.Context) {
firstname := c.DefaultQuery("firstname", "Guest") firstname := c.DefaultQuery("firstname", "Guest")
lastname := c.Query("lastname") // shortcut for c.Request.URL.Query().Get("lastname") lastname := c.Query("lastname") // shortcut for c.Request.URL.Query().Get("lastname")
@ -300,7 +300,7 @@ curl -X POST http://localhost:8080/upload \
#### Multiple files #### Multiple files
See the detail [example code](https://github.com/gin-gonic/examples/tree/master/upload-file/multiple). See the detailed [example code](https://github.com/gin-gonic/examples/tree/master/upload-file/multiple).
```go ```go
func main() { func main() {
@ -704,7 +704,7 @@ $ curl -v -X POST \
{"error":"Key: 'Login.Password' Error:Field validation for 'Password' failed on the 'required' tag"} {"error":"Key: 'Login.Password' Error:Field validation for 'Password' failed on the 'required' tag"}
``` ```
Skip validate: when running the above example using the above the `curl` command, it returns error. Because the example use `binding:"required"` for `Password`. If use `binding:"-"` for `Password`, then it will not return error when running the above example again. Skip-validation: Running the example above using the `curl` command returns an error. This is because the example uses `binding:"required"` for `Password`. If instead, you use `binding:"-"` for `Password`, then it will not return an error when you run the example again.
### Custom Validators ### Custom Validators
@ -832,6 +832,8 @@ type Person struct {
Birthday time.Time `form:"birthday" time_format:"2006-01-02" time_utc:"1"` Birthday time.Time `form:"birthday" time_format:"2006-01-02" time_utc:"1"`
CreateTime time.Time `form:"createTime" time_format:"unixNano"` CreateTime time.Time `form:"createTime" time_format:"unixNano"`
UnixTime time.Time `form:"unixTime" time_format:"unix"` UnixTime time.Time `form:"unixTime" time_format:"unix"`
UnixMilliTime time.Time `form:"unixMilliTime" time_format:"unixmilli"`
UnixMicroTime time.Time `form:"unixMicroTime" time_format:"uNiXmIcRo"` // case does not matter for "unix*" time formats
} }
func main() { func main() {
@ -851,6 +853,8 @@ func startPage(c *gin.Context) {
log.Println(person.Birthday) log.Println(person.Birthday)
log.Println(person.CreateTime) log.Println(person.CreateTime)
log.Println(person.UnixTime) log.Println(person.UnixTime)
log.Println(person.UnixMilliTime)
log.Println(person.UnixMicroTime)
} }
c.String(http.StatusOK, "Success") c.String(http.StatusOK, "Success")
@ -860,7 +864,7 @@ func startPage(c *gin.Context) {
Test it with: Test it with:
```sh ```sh
curl -X GET "localhost:8085/testing?name=appleboy&address=xyz&birthday=1992-03-15&createTime=1562400033000000123&unixTime=1562400033" curl -X GET "localhost:8085/testing?name=appleboy&address=xyz&birthday=1992-03-15&createTime=1562400033000000123&unixTime=1562400033&unixMilliTime=1562400033001&unixMicroTime=1562400033000012"
``` ```
@ -1183,7 +1187,7 @@ func main() {
}) })
r.GET("/moreJSON", func(c *gin.Context) { r.GET("/moreJSON", func(c *gin.Context) {
// You also can use a struct // You can also use a struct
var msg struct { var msg struct {
Name string `json:"user"` Name string `json:"user"`
Message string Message string
@ -1486,7 +1490,7 @@ You may use custom delims
#### Custom Template Funcs #### Custom Template Funcs
See the detail [example code](https://github.com/gin-gonic/examples/tree/master/template). See the detailed [example code](https://github.com/gin-gonic/examples/tree/master/template).
main.go main.go
@ -1538,7 +1542,7 @@ Date: 2017/07/01
### Multitemplate ### Multitemplate
Gin allow by default use only one html.Template. Check [a multitemplate render](https://github.com/gin-contrib/multitemplate) for using features like go 1.6 `block template`. Gin allows only one html.Template by default. Check [a multitemplate render](https://github.com/gin-contrib/multitemplate) for using features like go 1.6 `block template`.
### Redirects ### Redirects
@ -2087,7 +2091,7 @@ type formB struct {
func SomeHandler(c *gin.Context) { func SomeHandler(c *gin.Context) {
objA := formA{} objA := formA{}
objB := formB{} objB := formB{}
// This c.ShouldBind consumes c.Request.Body and it cannot be reused. // Calling c.ShouldBind consumes c.Request.Body and it cannot be reused.
if errA := c.ShouldBind(&objA); errA == nil { if errA := c.ShouldBind(&objA); errA == nil {
c.String(http.StatusOK, `the body should be formA`) c.String(http.StatusOK, `the body should be formA`)
// Always an error is occurred by this because c.Request.Body is EOF now. // Always an error is occurred by this because c.Request.Body is EOF now.
@ -2320,7 +2324,7 @@ or network CIDRs from where clients which their request headers related to clien
IP can be trusted. They can be IPv4 addresses, IPv4 CIDRs, IPv6 addresses or IP can be trusted. They can be IPv4 addresses, IPv4 CIDRs, IPv6 addresses or
IPv6 CIDRs. IPv6 CIDRs.
**Attention:** Gin trust all proxies by default if you don't specify a trusted **Attention:** Gin trusts all proxies by default if you don't specify a trusted
proxy using the function above, **this is NOT safe**. At the same time, if you don't proxy using the function above, **this is NOT safe**. At the same time, if you don't
use any proxy, you can disable this feature by using `Engine.SetTrustedProxies(nil)`, use any proxy, you can disable this feature by using `Engine.SetTrustedProxies(nil)`,
then `Context.ClientIP()` will return the remote address directly to avoid some then `Context.ClientIP()` will return the remote address directly to avoid some

2
gin.go
View File

@ -637,10 +637,12 @@ func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// Disclaimer: You can loop yourself to deal with this, use wisely. // Disclaimer: You can loop yourself to deal with this, use wisely.
func (engine *Engine) HandleContext(c *Context) { func (engine *Engine) HandleContext(c *Context) {
oldIndexValue := c.index oldIndexValue := c.index
oldHandlers := c.handlers
c.reset() c.reset()
engine.handleHTTPRequest(c) engine.handleHTTPRequest(c)
c.index = oldIndexValue c.index = oldIndexValue
c.handlers = oldHandlers
} }
func (engine *Engine) handleHTTPRequest(c *Context) { func (engine *Engine) handleHTTPRequest(c *Context) {

View File

@ -154,7 +154,7 @@ func RunUnix(file string) (err error) {
// RunFd attaches the router to a http.Server and starts listening and serving HTTP requests // RunFd attaches the router to a http.Server and starts listening and serving HTTP requests
// through the specified file descriptor. // through the specified file descriptor.
// Note: the method will block the calling goroutine indefinitely unless on error happens. // Note: the method will block the calling goroutine indefinitely unless an error happens.
func RunFd(fd int) (err error) { func RunFd(fd int) (err error) {
return engine().RunFd(fd) return engine().RunFd(fd)
} }

View File

@ -573,6 +573,44 @@ func TestEngineHandleContextManyReEntries(t *testing.T) {
assert.Equal(t, int64(expectValue), middlewareCounter) assert.Equal(t, int64(expectValue), middlewareCounter)
} }
func TestEngineHandleContextPreventsMiddlewareReEntry(t *testing.T) {
// given
var handlerCounterV1, handlerCounterV2, middlewareCounterV1 int64
r := New()
v1 := r.Group("/v1")
{
v1.Use(func(c *Context) {
atomic.AddInt64(&middlewareCounterV1, 1)
})
v1.GET("/test", func(c *Context) {
atomic.AddInt64(&handlerCounterV1, 1)
c.Status(http.StatusOK)
})
}
v2 := r.Group("/v2")
{
v2.GET("/test", func(c *Context) {
c.Request.URL.Path = "/v1/test"
r.HandleContext(c)
}, func(c *Context) {
atomic.AddInt64(&handlerCounterV2, 1)
})
}
// when
responseV1 := PerformRequest(r, "GET", "/v1/test")
responseV2 := PerformRequest(r, "GET", "/v2/test")
// then
assert.Equal(t, 200, responseV1.Code)
assert.Equal(t, 200, responseV2.Code)
assert.Equal(t, int64(2), handlerCounterV1)
assert.Equal(t, int64(2), middlewareCounterV1)
assert.Equal(t, int64(1), handlerCounterV2)
}
func TestPrepareTrustedCIRDsWith(t *testing.T) { func TestPrepareTrustedCIRDsWith(t *testing.T) {
r := New() r := New()

17
go.mod
View File

@ -1,9 +1,9 @@
module github.com/gin-gonic/gin module github.com/gin-gonic/gin
go 1.22 go 1.23.0
require ( require (
github.com/bytedance/sonic v1.11.6 github.com/bytedance/sonic v1.13.1
github.com/gin-contrib/sse v0.1.0 github.com/gin-contrib/sse v0.1.0
github.com/go-playground/validator/v10 v10.22.1 github.com/go-playground/validator/v10 v10.22.1
github.com/goccy/go-json v0.10.2 github.com/goccy/go-json v0.10.2
@ -13,15 +13,14 @@ require (
github.com/quic-go/quic-go v0.48.2 github.com/quic-go/quic-go v0.48.2
github.com/stretchr/testify v1.9.0 github.com/stretchr/testify v1.9.0
github.com/ugorji/go/codec v1.2.12 github.com/ugorji/go/codec v1.2.12
golang.org/x/net v0.33.0 golang.org/x/net v0.37.0
google.golang.org/protobuf v1.34.1 google.golang.org/protobuf v1.34.1
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )
require ( require (
github.com/bytedance/sonic/loader v0.1.1 // indirect github.com/bytedance/sonic/loader v0.2.4 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/base64x v0.1.5 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/locales v0.14.1 // indirect
@ -38,10 +37,10 @@ require (
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
go.uber.org/mock v0.4.0 // indirect go.uber.org/mock v0.4.0 // indirect
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
golang.org/x/crypto v0.31.0 // indirect golang.org/x/crypto v0.36.0 // indirect
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
golang.org/x/mod v0.17.0 // indirect golang.org/x/mod v0.17.0 // indirect
golang.org/x/sys v0.28.0 // indirect golang.org/x/sys v0.31.0 // indirect
golang.org/x/text v0.21.0 // indirect golang.org/x/text v0.23.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
) )

33
go.sum
View File

@ -1,13 +1,13 @@
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= github.com/bytedance/sonic v1.13.1 h1:Jyd5CIvdFnkOWuKXr+wm4Nyk2h0yAFsr8ucJgEasO3g=
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= github.com/bytedance/sonic v1.13.1/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY=
github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@ -84,22 +84,22 @@ go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU= golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
@ -112,4 +112,3 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=