Sili
Sili

Reputation: 957

Why Golang display different values when use different output function

I try to check when Golang return a local value as nil, then I use this code.

package main

import (
    "fmt"
)

type S struct{}

func InitEfacePointer() interface{} {
    var s *S
    println(s)
    return s
}

func main() {
    s := InitEfacePointer()
    fmt.Println(s)
    //println(s)
}

The output is 0x0

But when I just use println to output value.

package main

type S struct{}

func InitEfacePointer() interface{} {
    var s *S
    println(s)
    return s
}

func main() {
    s := InitEfacePointer()
    println(s)
}

The output changed to 0x0 (0x93d40,0x0)

Could anyone explain the mechanism of this behavior? Thanks!

Upvotes: 1

Views: 579

Answers (2)

Marc
Marc

Reputation: 21035

You shouldn't be using the builtin println, it clearly states:

The println built-in function formats its arguments in an implementation-specific way and writes the result to standard error. Spaces are always added between arguments and a newline is appended. Println is useful for bootstrapping and debugging; it is not guaranteed to stay in the language.

And the spec also mentions:

Current implementations provide several built-in functions useful during bootstrapping. These functions are documented for completeness but are not guaranteed to stay in the language. They do not return a result.

Implementation restriction: print and println need not accept arbitrary argument types, but printing of boolean, numeric, and string types must be supported.

This is it. print and println are useful debugging tools but should not be relied upon to:

  • provide a specific output
  • provide the same output on different platforms
  • provide the same output over time
  • exist

That said, I'm guessing that in your case it is printing the internal interface fields: a pointer to a type, and a value.

Upvotes: 3

leaf bebop
leaf bebop

Reputation: 8212

First of all, fmt.Println and builtin println are very different matteres: they are different both in implentation and in purpose. fmt.Println deals with many complex cases using reflect while println only deal with some base cases and is only for "bootstrap or debug" (as the spec says).

In this specific case, you are printing an interface{} you returned from InitEfacePointer(). The fmt.Println looks into the interface using reflect and gets the underlying data: a nil pointer to a string and it then prints it out: 0x0. On the other hand, builtin println takes the interface and by magic of the compiler (or not), it recognize it is an interface. As this post, golang interface are auctually two pointers, one to information about the type stored and one to the underlying data. So the builtin printlngoes into the interface details, 0x93d40 being the "type info" and 0x0 being the underlying data. (The first 0x0 is from the function call).

Furthermore, testing whether the returned interface is nil seems like a common mistake. Read here: https://golang.org/doc/faq#nil_error

Upvotes: 1

Related Questions