Return default value for generic type - go

How do you return nil for a generic type T?
func (list *mylist[T]) pop() T {
if list.first != nil {
data := list.first.data
list.first = list.first.next
return data
}
return nil
}
func (list *mylist[T]) getfirst() T {
if list.first != nil {
return list.first.data
}
return nil
}
I get the following compilation error:
cannot use nil as T value in return statement

You can't return nil for any type. If int is used as the type argument for T for example, returning nil makes no sense. nil is also not a valid value for structs.
What you may do–and what makes sense–is return the zero value for the type argument used for T. For example the zero value is nil for pointers, slices, it's the empty string for string and 0 for integer and floating point numbers.
How to return the zero value? Simply declare a variable of type T, and return it:
func getZero[T any]() T {
var result T
return result
}
Testing it:
i := getZero[int]()
fmt.Printf("%T %v\n", i, i)
s := getZero[string]()
fmt.Printf("%T %q\n", s, s)
p := getZero[image.Point]()
fmt.Printf("%T %v\n", p, p)
f := getZero[*float64]()
fmt.Printf("%T %v\n", f, f)
Which outputs (try it on the Go Playground):
int 0
string ""
image.Point (0,0)
*float64 <nil>

The *new(T) idiom
This has been suggested as the preferred option in golang-nuts. It is probably less readable but easier to find and replace if/when some zero-value builtin gets added to the language.
It also allows one-line assignments.
The new built-in allocates storage for a variable of any type and returns a pointer to it, so dereferencing *new(T) effectively yields the zero value for T. You can use a type parameter as the argument:
func Zero[T any]() T {
return *new(T)
}
In case T is comparable, this comes in handy to check if some variable is a zero value:
func IsZero[T comparable](v T) bool {
return v == *new(T)
}
var of type T
Straightforward and easier to read, though it always requires one line more:
func Zero[T any]() T {
var zero T
return zero
}
Named return types
If you don't want to explicitly declare a variable you can use named returns. Not everyone is fond of this syntax, though this might come in handy when your function body is more complex than this contrived example, or if you need to manipulate the value in a defer statement:
func Zero[T any]() (ret T) {
return
}
func main() {
fmt.Println(Zero[int]()) // 0
fmt.Println(Zero[map[string]int]()) // map[]
fmt.Println(Zero[chan chan uint64]()) // <nil>
}
It's not a chance that the syntax for named returns closely resembles that of var declarations.
Using your example:
func (list *mylist[T]) pop() (data T) {
if list.first != nil {
data = list.first.data
list.first = list.first.next
}
return
}
Return nil for non-nillable types
If you actually want to do this, as stated in your question, you can return *T explicitly.
This can be done when the type param T is constrained to something that excludes pointer types. In that case, you can declare the return type as *T and now you can return nil, which is the zero value of pointer types.
// constraint includes only non-pointer types
func getNilFor[T constraints.Integer]() *T {
return nil
}
func main() {
fmt.Println(reflect.TypeOf(getNilFor[int]())) // *int
fmt.Println(reflect.TypeOf(getNilFor[uint64]())) // *uint64
}
Let me state this again: this works best when T is NOT constrained to anything that admits pointer types, otherwise what you get is a pointer-to-pointer type:
// pay attention to this
func zero[T any]() *T {
return nil
}
func main() {
fmt.Println(reflect.TypeOf(zero[int]())) // *int, good
fmt.Println(reflect.TypeOf(zero[*int]())) // **int, maybe not what you want...
}

You can init a empty variable.
if l == 0 {
var empty T
return empty, errors.New("empty Stack")
}

Related

How to make a function with inferred nillable comparable generics?

Consider the following function:
func NilCompare[T comparable](a *T, b *T) bool {
if a == nil && b == nil {
// if both nil, we consider them equal
return true
}
if a == nil || b == nil {
// if either is nil, then they are clearly not equal
return false
}
return *a == *b
}
This function works. However, when I call it, I must supply the type, as Go cannot infer (cannot infer T) it, e.g. NilCompare[string](a, b), where a and b are *string.
If I modify T to be *comparable and a and b to be T, I get this error instead:
cannot use type comparable outside a type constraint: interface is (or embeds) comparable
I am using Go 1.19.2.
$ go version
go version go1.19.2 linux/amd64
Ironically, my IDE (GoLand 2022.2.3) believes that the above function should be inferrable.
Is there a way to make a function that take nillable comparable and make it inferrable? Or am I doing it correct, but I need to help the go function along?
Type inference just works, in this case. You simply can't infer T using literal nil, as NilCompare(nil, nil) because that doesn't really carry type information.
To test your function with nils do this:
package main
import "fmt"
func main() {
var a *string = nil
var b *string = nil
// a and b are explicitly typed
res := NilCompare(a, b) // T inferred
fmt.Println(res) // true
}
this also would work:
func main() {
// literal nil converted to *string
res := NilCompare((*string)(nil), (*string)(nil)) // T inferred
fmt.Println(res) // true
}

Get type of an uninitialized slice

I want to return a type of an interface{}, while the input value might be var m []*MyModel
I've managed to get to the type *MyModel, while MyModel not as a pointer seems to be unreachable to me.
func getType( m interface{} ) reflect.Type {
t := reflect.TypeOf( m );
v := reflect.ValueOf( m );
if t.Kind() == reflect.Ptr {
if v.IsValid() && !v.IsNil() {
return getType( v.Elem().Interface() );
}
panic( "We have a problem" );
}
if t.Kind() == reflect.Slice {
if v.Len() == 0 {
s := reflect.MakeSlice( t , 1 , 1 );
return getType( s.Interface() );
}
return getType( v.Index( 0 ).Interface() );
}
return t;
}
Is it possible?
You may use Type.Elem() to get the type's element type, which works for Array, Chan, Map, Ptr and Slice.
You may run a loop and "navigate" to the type's element type until the type is not a pointer nor a slice (nor array, chan, map if you need so).
So the simple solution is this:
func getElemType(a interface{}) reflect.Type {
for t := reflect.TypeOf(a); ; {
switch t.Kind() {
case reflect.Ptr, reflect.Slice:
t = t.Elem()
default:
return t
}
}
}
Testing it:
type MyModel struct{}
fmt.Println(getElemType(MyModel{}))
fmt.Println(getElemType(&MyModel{}))
fmt.Println(getElemType([]MyModel{}))
fmt.Println(getElemType([]*MyModel{}))
fmt.Println(getElemType(&[]*MyModel{}))
fmt.Println(getElemType(&[]****MyModel{}))
fmt.Println(getElemType(&[][]**[]*[]***MyModel{}))
var p *[][]**[]*[]***MyModel
fmt.Println(p) // It's nil!
fmt.Println(getElemType(p))
Output (try it on the Go Playground):
main.MyModel
main.MyModel
main.MyModel
main.MyModel
main.MyModel
main.MyModel
main.MyModel
<nil>
main.MyModel
As you can see, no matter how "deep" we go with slices and pointers (&[][]**[]*[]***MyModel{}), getElemType() is able to extract main.MyModel.
One thing to note is that in my solution I used reflect.Type and not reflect.Value. Go is a statically typed language, so the type information is there even if pointers and slice elements are not "populated", even if we pass a "typed" nil such as p, we're still able to navigate through the "type chain".
Note: The above getElemType() panics if called with an untyped nil value, e.g. getElemType(nil), because in this case there is no type information available. To defend this, you may add a simple check:
if a == nil {
return nil
}
Note #2: Since the implementation contains a loop without limiting iteration count, values of recursive types will drive it into an endless loop, such as:
type RecType []RecType
getElemType(RecType{}) // Endless loop!

This nil instance of a struct, that satisfies the error interface, is not showing as nil

This should be a gimme for someone. Why do I not get what I expect ("Error is not nil") here?
http://play.golang.org/p/s8CWQxobVL
type Goof struct {}
func (goof *Goof) Error() string {
return fmt.Sprintf("I'm a goof")
}
func TestError(err error) {
if err == nil {
fmt.Println("Error is nil")
} else {
fmt.Println("Error is not nil")
}
}
func main() {
var g *Goof // nil
TestError(g) // expect "Error is nil"
}
This is, it turns out, a Frequently Asked Question about Go, and the short answer is that interface comparisons compare the type and the value, and (*Goof)(nil) and error(nil) have different types.
Since if err != nil is standard, you want a return value that'll work with it. You could declare var err error instead of var g *Goof: err's zero value is conveniently error(nil)
Or, if your func returns an error, return nil will return what you want.
For more background, here's the start of the FAQ's answer:
Under the covers, interfaces are implemented as two elements, a type and a value. The value, called the interface's dynamic value, is an arbitrary concrete value and the type is that of the value. For the int value 3, an interface value contains, schematically, (int, 3).
An interface value is nil only if the inner value and type are both unset, (nil, nil). In particular, a nil interface will always hold a nil type. If we store a pointer of type *int inside an interface value, the inner type will be *int regardless of the value of the pointer: (*int, nil). Such an interface value will therefore be non-nil even when the pointer inside is nil.
And == is strictly checking if the types are identical, not if a type (*Goof) implements an interface (error). Check out the original for more.
If it helps clarify, this doesn't only happen with nil: in this example, the data underlying the x and y variables is obviously 3, but they have different types. When you put x and y into interface{}s, they compare as unequal:
package main
import "fmt"
type Bob int
func main() {
var x int = 3
var y Bob = 3
var ix, iy interface{} = x, y
fmt.Println(ix == iy)
}

How do I type-assert that a value is a pointer (to a string)?

I'm trying to create a method that will return the length of a generic type. If we have a string, we call len(string), or if its an array of interface{} type, we call len() on that as well. This works well, however, it doesnt work in you pass in a pointer to a string (I'm assuming I'd have the same problem with arrays and slices as well). So how can I check if I have a pointer, and dereference it?
func (s *Set) Len(i interface{}) int {
if str, ok := i.(string); ok {
return len(str)
}
if array, ok := i.([]interface{}); ok {
return len(array)
}
if m, ok := i.(map[interface{}]interface{}); ok {
return len(m)
}
return 0
}
You can do the same thing as for the other types:
if str, ok := i.(*string); ok {
return len(*str)
}
At this point you may want to use a type switch instead of the more verbose ifs:
switch x := i.(type) {
case string:
return len(x)
case *string:
return len(*x)
…
}

Can't return nil, but zero value of slice

I am having the case in which a function with the following code:
func halfMatch(text1, text2 string) []string {
...
if (condition) {
return nil // That's the final code path)
}
...
}
is returning []string(nil) instead of nil. At first, I thought that perhaps returning nil in a function with a particular return type would just return an instance of a zero-value for that type. But then I tried a simple test and that is not the case.
Does anybody know why would nil return an empty string slice?
Nil is not a type. It is a description of the zero value for maps, chans, pointers, functions, slices, and interfaces.
When you put "nil" in your program, go gives it a type depending on the context. For the most part, you never need to explicitly type your nil. This is no exception, the compiler knows it must be a []string(nil) because the type returned is []string.
A nil string slice is a slice with no backing array and a length/capacity of zero. You may compare it to the literal "nil" and can get its length and capacity. It is a []string, just empty. If you wish to have an empty []string that is not nil, return []string{}. This creates a backing array (of length zero) and makes it no longer equivalent to nil.
I believe I know what's going on. The assert library I am using (github.com/bmizerany/assert) is using internally a reflect.DeepEqual.
The return value of func halfMatch(text1, text2 string) []string is always of type []string, but if it returns nil and is compared to a nil value via the == operator, it will return true. However, if reflect.DeepEqual is used, the type will matter and it won't consider both values the same.
playgound link with the test
I think maybe you are being confused by the output of print. (playground link)
package main
import "fmt"
func f() []string {
return nil // That's the final code path)
}
func main() {
result := f()
fmt.Printf("result = %v\n", result)
fmt.Printf("result = %v\n", result == nil)
}
Which produces
result = []
result = true
So I think the output really is nil
Go will return an enpty slice if condition is true.
There is a problem with your "test" because if you try to compare [] with nil, you get true.
I have modified your test to show you what I mean
package main
import "fmt"
func main() {
//fmt.Println(test1("") == nil)
fmt.Println(test1("")) // prints []
}
func test1(text1 string) []string {
if len(text1) > 0 {
return []string{text1}
}
return nil
}

Resources