2

The "nil" value for a string "" makes sense to me but 0 is a legitimate number. For instance, the number of people in a room can be 0 but a person's name cannot be "". What was the reasoning behind this convention?

(Edit) Additional info:

What I would like to do is have a way of testing if a value has been set for a number. Having someone's name set to "" is obviously not correct, whereas having an integer set to zero may have been legitimate. Is there a typical way of working around this sort of occurrence in go?

Winston Guess
  • 87
  • 1
  • 7
  • 5
    `""` is also a legitimate string. In Go, only pointer and interface values can be nil, so there really is no way to make a number nil. – Peter Oct 11 '17 at 08:02
  • 6
    Perhaps what you mean is [`zero value`](https://golang.org/ref/spec#The_zero_value) for number? – putu Oct 11 '17 at 08:03
  • 2
    `nil` (or `null`/`NULL` in other languages) is not the same or a replacement of the empty string or of zero. It is a concept that represents the absence of any value, a value that is not known or a value that doesn't matter in the context. The empty string is an invalid person name but `nil` might be a perfectly valid value. It means the name is not known yet. – axiac Oct 11 '17 at 08:19

4 Answers4

9

The "nil" value for a string "" makes sense to me but 0 is a legitimate number.

There are two obvious problems with your statement:

  1. There is no such thing as a "nil" value for a string.
  2. "" is a perfectly legitimate string.

You seem to be confusing Go's concept of a "zero value" with nil. These concepts are almost entirely unrelated.

  • The zero value for a string is "".
  • The zero value for a number is 0.
  • The zero value for a pointer or interface is nil. This is the only place where nil and "zero values" really relate to each other.

Further strings, numbers, and other concrete types cannot ever be nil in Go. (Pointers to these types can be, but that's obviously distinct). So talking about a "nil value for a string" or "nil value for a number" doesn't even make sense.


In response to your edit, this question has already been answered in various contexts. See here for an example relating to JSON unmarshaling. In short, though, you must use something other than a number/string type. Use a pointer, or a wrapper type (such as a sql.NullInt64).

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
5

A designated value from the set of valid values of the type have to be chosen. What else could qualify more for the position to be the zero-value?

nil is not a valid value of numerical types (such as int, uint, int32 etc.), so that's out of the question.

0 has the benefit that in binary representation it's full zeros. It's name is also in line with "zero value".

Maybe -1? -1 in binary representation is full ones (using 2's complement representation). -1 is not any more special.

Then maybe the min value? In case of int32 that would be -1 << 31 which is -2147483648. But if the type is unsigned, e.g. uint32, that would again be 0. Moreover, taking the type int the min value is not even a constant as it depends on the target architecture (may be -1 << 31 and -1 << 63).

If 0 is a value you use and you want to differentiate whether it has already been set (or if the value is just being the zero value), use a pointer (e.g. *int) which may have a nil value (the zero value) indicating it has not yet been set.

Another option is to use a second variable (may be of type bool), it's true value indicating the number has been set.

Also more techniques (choosing a clever, non-used valid value), check out How do I represent an Optional String in Go?

icza
  • 389,944
  • 63
  • 907
  • 827
3

For string, the default value is ""; for bool, the default value is false; for int, the default value is 0.

You can use pointer.

var num *int
if num == nil {
    // num is not set
} else {
    // num is set
    if *num == 0 {
        // num is set to 0
    } else {
        // num is set to another integer
    }
}

In the same way, you can judge if a boolean value is set or not.

littlepoint
  • 114
  • 6
0

Is there a typical way of working around this sort of occurrence in go?

Whether an empty string or a zero is a valid/invalid value depends on the application. An empty name might be invalid for your application, but it might be valid in other cases.

A way to handle this in Go is by creating a struct and in there represent whether you have the value or not. For example:

type Person struct {
  Name    string
  HasName bool
  Age     int
  HasAge  bool
}

This seems a bit cumbersome for such a contrived example, but in more complex scenarios the overhead of having the extra field is minimal.

Hector Correa
  • 26,290
  • 8
  • 57
  • 73