Why `fmt.Println("%T\n", e)` where `e` is an error variable prints out <nil> and not its type? - go

I was recently playing with the Go language and I bumped into something a bit weird to say the least, let's consider a very simple function:
func main() {
n, e := fmt.Println(`He said: "Hello"`)
fmt.Printf("%T\n", n)
}
Which outputs what I was expecting:
He said: "Hello"
int
Now if I want to display the type of e:
func main() {
n, e := fmt.Println(`He said: "Hello"`)
fmt.Printf("%T\n", e)
}
and this time prints out:
He said: "Hello"
<nil>
I get the part that there is no error so e is an empty pointer: nil but I would have not expected to be a ~~type~~ on its own.
Why am I not getting the actual type?
If so, is there a workaround? (not saying my use case is a realistic one but curious if there is any possibility)

The Go Programming Language Specification
Errors
The predeclared type error is defined as
type error interface {
Error() string
}
It is the conventional interface for representing an error condition,
with the nil value representing no error.
Interface types
An interface type specifies a method set called its interface. A
variable of interface type can store a value of any type with a method
set that is any superset of the interface. Such a type is said to
implement the interface. The value of an uninitialized variable of
interface type is nil.
The zero value
When storage is allocated for a variable, either through a declaration
or a call of new, or when a new value is created, either through a
composite literal or a call of make, and no explicit initialization is
provided, the variable or value is given a default value. Each element
of such a variable or value is set to the zero value for its type: nil
for interfaces.
A zero-value error type, an interface, has no type.Its value is nil.

e is an empty pointer
Nope, error itself - interface, so you won't have type here.

Related

what does reflect.TypeOf((*error)(nil)).Elem()` mean?

func (s *service) registerMethods() {
s.method = make(map[string]*methodType)
for i := 0; i < s.typ.NumMethod(); i++ {
method := s.typ.Method(i)
mType := method.Type
if mType.NumIn() != 3 || mType.NumOut() != 1 {
continue
}
if mType.Out(0) != reflect.TypeOf((*error)(nil)).Elem() {
continue
}
argType, replyType := mType.In(1), mType.In(2)
if !isExportedOrBuiltinType(argType) || !isExportedOrBuiltinType(replyType) {
continue
}
s.method[method.Name] = &methodType{
method: method,
ArgType: argType,
ReplyType: replyType,
}
log.Printf("rpc server: register %s.%s\n", s.name, method.Name)
}
}
what does reflect.TypeOf((*error)(nil)).Elem() mean in this code? I know if mType.Out(0) != reflect.TypeOf((*error)(nil)).Elem() is trying to determine if the method's return type is error not not. But for me, reflect.TypeOf((error)(nil)) will intuitively will do the same, but unfortunately not. When I try to compile this code, it says type error is not an expression, what does it mean in this context? Does not reflect.Typeof() accepts a argument of certain type? I found that (*error)(nil) is equivalent to *error = nil. I am confused with this expression in the context above.
TL;DR; reflect.TypeOf((*error)(nil)).Elem() is an expression used to obtain the reflect.Type type descriptor of the interface type error. Using reflect.TypeOf(error(nil)) cannot be used for the same purpose (read the why below).
reflect.TypeOf((*error)(nil)).Elem() achieves its goal by using a typed nil pointer value of type *error, passing it to reflect.TypeOf() to get the reflect.Type descriptor of the type *error, and uses Type.Elem() to get the type descriptor of the element (base) type of *error, which is error.
reflect.TypeOf() expects an interface{} value:
func TypeOf(i interface{}) Type
Basically whatever value you pass to reflect.TypeOf(), if it's not already an interface value, it will be wrapped in an interface{} implicitly. If the passed value is already an interface value, then the concrete value stored in it will be passed as interface{}.
So if you try to pass an error value to it, since error is an interface type, the concrete value stored in it will be "repacked" into an interface{} value. The interface type error will not be retained / transferred!
If you pass a nil value of type error, e.g. error(nil), since the interface value itself is nil, it contains no concrete value and type, a nil interface{} value will be passed, that will result in nil reflect.Type returned. Quoting from reflect.TypeOf():
TypeOf returns the reflection Type that represents the dynamic type of i. If i is a nil interface value, TypeOf returns nil.
If you pass a value of type *error (which may be a nil pointer), it's not an interface value, it's a pointer value (a pointer to interface). So it will be wrapped in an interface{} value, and the concrete value stored in it will be of type *error. Using Type.Elem() you can access the pointed type, that is error.
This is one of the rare cases when using a pointer to interface makes sense, and in fact inevitable.
See related questions:
Get the reflect.Kind of a type which is based on a primitive type
What is the difference between reflect.ValueOf() and Value.Elem() in go?
Hiding nil values, understanding why golang fails here

Why is it recommended to return with the `error` interface in go rather than with the concrete error type?

The go FQA states:
It's a good idea for functions that return errors always to use the error type in their signature (as we did above) rather than a concrete type such as *MyError, to help guarantee the error is created correctly. As an example, os.Open returns an error even though, if not nil, it's always of concrete type *os.PathError.
But this article claims that sometimes it is OK to return with a concrete type:
(It's usually a mistake to pass back the concrete type of an error rather than error, for reasons discussed in the Go FAQ, but it's the right thing to do here because ServeHTTP is the only place that sees the value and uses its contents.)
My question is, what are the benefits of returning with error rather than the concrete type, how does it help guarantee that the error is created correctly, and why is it okay to return the concrete type when the error is not used in different places?
This is related to error being an interface. An interface contains a pointer to the value it contains and the type of that value. An interface is nil only if both of those values are nil. So, if you return a concrete error type from a function, and then return an error, that error will not be nil.
live on the Go playground
type MyError string
func (e MyError) Error() string {return string(e)}
func f() *MyError {
return nil
}
func g() error {
return f()
}
func main() {
x:=g()
if x==nil {
fmt.Println("nil")
}
}
In the example above, even though *MyError value is nil, the return value of g() is not, because it contains an interface with type *MyError and value nil.
This is a problem for all functions returning an interface value, and most commonly observed with error types. So do not declare functions returning concrete error values unless those functions have very limited use, such as unexported functions.

How does Go bind methods to Objects?

I just started learning Go a few days ago.Today, we were debugging a piece of code for a while when we found something that seem counterintuitive of Go to do.
First we defined an interface and a data structure that implements it.
type Executer interface {
Execute()
}
type whatever struct {
name string
}
func (this *whatever) Execute() {
log.Println(this.name)
}
Now consider that I have a nil pointer to whatever and I try to call the method Execute. In other object-oriented languages I have used so far, this would call a null pointer error at the point of calling the method (i.e. w.Execute()) since the object pointer is null. Interestingly, in Go, the method is invoked, the null pointer error occurs at the Execute method when I try to dereference this.name. Why not at the point of calling the method?
func main() {
var w *whatever
w.Execute()
}
So, what I'm seeking to understand now is how is this possible? Does this mean that Go only does early method binding at compile time and at runtime there is no binding of the method with a specific object?
The receiver is just an "ordinary" argument to the function. Ordinary parameters may be of pointer types. When then are, you are allowed to pass nil as the argument, which is perfectly valid. All you need to keep in mind is not to dereference nil pointer arguments. The same applies to the special receiver parameter too. If it's a pointer, it may be nil, you just must not dereference it.
Spec: Method declarations:
The receiver is specified via an extra parameter section preceding the method name.
... The method is said to be bound to its receiver base type and the method name is visible only within selectors for type T or *T.
Allowing nil receiver values is not just something not forbidden, it has practical uses. For an example, see Test for nil values in nested stucts.
In Java you can call static methods on null objects too. It's true you can't do the same in Go, because Go does not have modifiers like static, public, private etc. In Go there are only exported and non-exported methods (implied by the first latter of their name).
But Go offers something similar too: Method expressions and Method values. If you have a method m with T receiver type, the expression T.m will be a function value whose signature contains the parameters and result types of m "prefixed" with the receiver type.
For example:
type Foo int
func (f Foo) Bar(s string) string { return fmt.Sprint(s, f) }
func main() {
fooBar := Foo.Bar // A function of type: func(Foo, string) string
res := fooBar(1, "Go")
fmt.Println(res)
}
Foo.Bar will be a function with type func (Foo, string) string, and you can call it like any other ordinary function; and you also have to pass the receiver as the first argument. The above app outputs (try it on the Go Playground):
Go1
Going a little "forward", we are not required to store Foo.Bar in a variable, we can directly call Foo.Bar:
fmt.Println(Foo.Bar(1, "Go"))
Which outputs the same (try it on the Go Playground). Now this almost looks like a static method call in Java.
And as the "final" step, when we use the above expression on a value of Foo itself (instead of the type identifier), we arrive at the method values, which saves the receiver and so the type of a method value does not include the receiver, its signature will be that of the method, and we can call it without having to pass a receiver:
var f Foo = Foo(1)
bar := f.Bar
fmt.Println(bar("Go"))
This again will output the same, try it on the Go Playground.
See related questions:
Pass method argument to function
golang function alias on method receiver

Why does reflecting the name (or package path) of the error type cause a panic in Go?

Using reflection to get the name or package path of the error type in Golang causes the program to panic (with panic: runtime error: invalid memory address or nil pointer dereference).
What is the reasoning for this behaviour? (Doing the same operation for other built in types returns the type name and an empty string for the package path.)
I'm interested in terms of the design of the language - I can't figure out why it's desirable for this to behave differently for error types over other built in types.
E.g:
package main
import (
"fmt"
"reflect"
)
func main() {
var str string
strType := reflect.TypeOf(str)
fmt.Println(strType.Name()) // OK
fmt.Println(strType.PkgPath()) // OK
var err error
errType := reflect.TypeOf(err)
fmt.Println(errType.Name()) // panics
fmt.Println(errType.PkgPath()) // also panics
}
Go playground here: https://play.golang.org/p/JBMhMkjGPEV
error is not special, except that it's an interface.
reflect.TypeOf takes a single argument of type interface{}. If you call it with a non-interface value, the value and its type is wrapped in an interface{}. If you call it with an interface value, the underlying value and type is extracted from the interface, and wrapped in a new interface{} value. If you call it with an empty interface (like you're doing here, since error is an interface and it's zero-initialized), then there's no underlying value and type, and the argument to reflect.TypeOf is a new nil interface{} value. reflect.TypeOf is defined to return nil in this case, leading to your nil problems.
I think your confusion is that the TypeOf of an interface value is the type of its underlying value, which is never an interface. You would like TypeOf of an interface value to be the interface type itself, but that's not how it works.

How to convert value type by another value's reflect.Type in Golang

How to convert value type by another value's reflect.Type in Golang
maybe like this:
func Scan(value interface{}, b string) error {
converted := value.(reflect.TypeOf(b)) // do as "value.(string)"
return nil
}
How can do this properly in golang?
The only way to get a typed value out of an interface is to use a type assertion, and the syntax is value.(T) where T is a type. There's a good reason for this, because it makes the type of the type assertion expression computable: value.(T) has type T. If instead, you allowed value.(E) where E is some expression that evaluates to a reflect.Type (which I think is the gist of your question), then the compiler has no way to (in general) statically determine the type of value.(E) since it depends on the result of an arbitrary computation.

Resources