From c65747306be7bc2452acbe9fd7afc510bd8de6d2 Mon Sep 17 00:00:00 2001 From: Pavlo Date: Tue, 3 Mar 2026 01:59:47 +0200 Subject: [PATCH] add Param method for all int/uint/float/bool --- context.go | 74 +++++++++++++++++++++++++++++++++ context_test.go | 107 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 181 insertions(+) diff --git a/context.go b/context.go index 5174033eb3..c400ccc26a 100644 --- a/context.go +++ b/context.go @@ -18,6 +18,7 @@ import ( "net/url" "os" "path/filepath" + "strconv" "strings" "sync" "time" @@ -504,6 +505,79 @@ func (c *Context) Param(key string) string { return c.Params.ByName(key) } +// ParamInt returns the URL param for the given key as an int. +func (c *Context) ParamInt(key string) (int, error) { + return strconv.Atoi(c.Param(key)) +} + +// ParamInt8 returns the URL param for the given key as an int8. +func (c *Context) ParamInt8(key string) (int8, error) { + value, err := strconv.ParseInt(c.Param(key), 10, 8) + return int8(value), err +} + +// ParamInt16 returns the URL param for the given key as an int16. +func (c *Context) ParamInt16(key string) (int16, error) { + value, err := strconv.ParseInt(c.Param(key), 10, 16) + return int16(value), err +} + +// ParamInt32 returns the URL param for the given key as an int32. +func (c *Context) ParamInt32(key string) (int32, error) { + value, err := strconv.ParseInt(c.Param(key), 10, 32) + return int32(value), err +} + +// ParamInt64 returns the URL param for the given key as an int64. +func (c *Context) ParamInt64(key string) (int64, error) { + return strconv.ParseInt(c.Param(key), 10, 64) +} + +// ParamUint returns the URL param for the given key as a uint. +func (c *Context) ParamUint(key string) (uint, error) { + value, err := strconv.ParseUint(c.Param(key), 10, 0) + return uint(value), err +} + +// ParamUint8 returns the URL param for the given key as a uint8. +func (c *Context) ParamUint8(key string) (uint8, error) { + value, err := strconv.ParseUint(c.Param(key), 10, 8) + return uint8(value), err +} + +// ParamUint16 returns the URL param for the given key as a uint16. +func (c *Context) ParamUint16(key string) (uint16, error) { + value, err := strconv.ParseUint(c.Param(key), 10, 16) + return uint16(value), err +} + +// ParamUint32 returns the URL param for the given key as a uint32. +func (c *Context) ParamUint32(key string) (uint32, error) { + value, err := strconv.ParseUint(c.Param(key), 10, 32) + return uint32(value), err +} + +// ParamUint64 returns the URL param for the given key as a uint64. +func (c *Context) ParamUint64(key string) (uint64, error) { + return strconv.ParseUint(c.Param(key), 10, 64) +} + +// ParamFloat32 returns the URL param for the given key as a float32. +func (c *Context) ParamFloat32(key string) (float32, error) { + value, err := strconv.ParseFloat(c.Param(key), 32) + return float32(value), err +} + +// ParamFloat64 returns the URL param for the given key as a float64. +func (c *Context) ParamFloat64(key string) (float64, error) { + return strconv.ParseFloat(c.Param(key), 64) +} + +// ParamBool returns the URL param for the given key as a boolean. +func (c *Context) ParamBool(key string) (bool, error) { + return strconv.ParseBool(c.Param(key)) +} + // AddParam adds param to context and // replaces path param key with given value for e2e testing purposes // Example Route: "/user/:id" diff --git a/context_test.go b/context_test.go index ef60379d77..6101e82baf 100644 --- a/context_test.go +++ b/context_test.go @@ -3352,6 +3352,113 @@ func TestContextAddParam(t *testing.T) { assert.Equal(t, value, v) } +func TestContextParamTyped(t *testing.T) { + tests := []struct { + name string + value string + call func(*Context) (any, error) + want any + }{ + { + name: "int", + value: "42", + call: func(c *Context) (any, error) { return c.ParamInt("value") }, + want: 42, + }, + { + name: "int8", + value: "127", + call: func(c *Context) (any, error) { return c.ParamInt8("value") }, + want: int8(127), + }, + { + name: "int16", + value: "32767", + call: func(c *Context) (any, error) { return c.ParamInt16("value") }, + want: int16(32767), + }, + { + name: "int32", + value: "2147483647", + call: func(c *Context) (any, error) { return c.ParamInt32("value") }, + want: int32(2147483647), + }, + { + name: "int64", + value: "9223372036854775807", + call: func(c *Context) (any, error) { return c.ParamInt64("value") }, + want: int64(9223372036854775807), + }, + { + name: "uint", + value: "42", + call: func(c *Context) (any, error) { return c.ParamUint("value") }, + want: uint(42), + }, + { + name: "uint8", + value: "255", + call: func(c *Context) (any, error) { return c.ParamUint8("value") }, + want: uint8(255), + }, + { + name: "uint16", + value: "65535", + call: func(c *Context) (any, error) { return c.ParamUint16("value") }, + want: uint16(65535), + }, + { + name: "uint32", + value: "4294967295", + call: func(c *Context) (any, error) { return c.ParamUint32("value") }, + want: uint32(4294967295), + }, + { + name: "uint64", + value: "18446744073709551615", + call: func(c *Context) (any, error) { return c.ParamUint64("value") }, + want: uint64(18446744073709551615), + }, + { + name: "float32", + value: "2.5", + call: func(c *Context) (any, error) { return c.ParamFloat32("value") }, + want: float32(2.5), + }, + { + name: "float64", + value: "2.5", + call: func(c *Context) (any, error) { return c.ParamFloat64("value") }, + want: float64(2.5), + }, + { + name: "bool", + value: "true", + call: func(c *Context) (any, error) { return c.ParamBool("value") }, + want: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &Context{Params: Params{{Key: "value", Value: tt.value}}} + got, err := tt.call(c) + assert.NoError(t, err) + assert.Equal(t, tt.want, got) + }) + } +} + +func TestContextParamTypedErrors(t *testing.T) { + c := &Context{Params: Params{{Key: "value", Value: "nope"}}} + _, err := c.ParamInt("value") + assert.Error(t, err) + + c = &Context{Params: Params{{Key: "value", Value: "-1"}}} + _, err = c.ParamUint("value") + assert.Error(t, err) +} + func TestCreateTestContextWithRouteParams(t *testing.T) { w := httptest.NewRecorder() engine := New()