form icon indicating copy to clipboard operation
form copied to clipboard

Pointer to int and zero value

Open badoux opened this issue 5 years ago • 6 comments

type Request struct {
	TestInt        *int        `form:"test_int"`
	TestString  *string   `form:"test_string"`
}

When providing empty value for "test_string" parameter(r.Form["test_string"]=""), Request.TestString will be not nil and set with the zero value "" as wanted.

But when "test_int" is provided with an empty string value(r.Form["test_int"]=""), Request.TestInt is still nil and shloud rather be set to the zero value 0.

It works great with Gorilla Schema

badoux avatar Oct 12 '20 09:10 badoux

@badoux could you provide a more complete example? I'm not 100% clear on the issue you are describing.

deankarn avatar Oct 12 '20 15:10 deankarn

Hi @deankarn

Here is a full example :

package main

import (
	"fmt"
	"net/url"

	"github.com/go-playground/form/v4"
)

type Request struct {
	ID  *int    `form:"id"`
	Str *string `form:"str"`
}

func main() {
	r := &Request{}
	values := url.Values{}
	values.Set("id", "")
	values.Set("str", "")

	decoder := form.NewDecoder()
	err := decoder.Decode(r, values)
	if err != nil {
		panic(err)
	}

	fmt.Printf("%+v", r)
}
$ go run test.go 
&{ID:<nil> Str:0xc000010270}

r.Str is not nil with an empty string as value (zero value of the type string) • r.ID is still nil and i expect it to be set to 0 (zero value of the type int)

badoux avatar Oct 12 '20 15:10 badoux

Gorilla schema has a ZeroEmpty method to deal with this case : https://godoc.org/github.com/gorilla/schema#Decoder.ZeroEmpty

badoux avatar Oct 14 '20 09:10 badoux

why you expect the r.ID to be 0? i expect that default value of *int is nil bcs no way to parse "" to any of int, and how you differentiate between id "0" and id ""?

gunawanwijaya avatar Oct 22 '20 02:10 gunawanwijaya

Hey @badoux

As @gunawanwijaya eluded to if the key exists with no value, the value IS blank. There is no way to differentiate using URL.Values

But for an int, if it’s not a valid int then we can differentiate.

I’m not sure I want to add an option like that at this time. If you want the int to be 0 even if no value is sent you can change your strict from +int to just int as the default value will be 0.

deankarn avatar Oct 22 '20 06:10 deankarn

@gunawanwijaya

Simply because i need to know if a value is given or not. If no value is given it's nil, otherwise it's the given value or 0 if parsing is not possible.

So if the value of r.ID is 0 i can know that the user given me an "empty" value ("" or "0") and want to set this value to NULL in database, if the pointer is still nil i can't know

It's already the same behaviour with a *string. If no value is given it's nil, otherwise it's the given string or "". It's about consistency.

Like @deankarn said "if the key exists with no value, the value IS blank", and if it's blank... it's not nil.

Seems logical to me but i can understand, i will stick to gorilla/schema for this usecase cause i need it and its the default behaviour.

badoux avatar Oct 28 '20 17:10 badoux