When using fmt.Print to print a reflect.Value v, v.Elem() is printed instead. Why?

113 views
Skip to first unread message

tapi...@gmail.com

unread,
Feb 25, 2021, 11:00:37 PM2/25/21
to golang-nuts

Kurtis Rader

unread,
Feb 25, 2021, 11:11:52 PM2/25/21
to tapi...@gmail.com, golang-nuts
On Thu, Feb 25, 2021 at 8:01 PM tapi...@gmail.com <tapi...@gmail.com> wrote:


You need to clarify your question. I don't see any obvious problem with the output of your program. The reflect.Value.Elem() call is defined to return a reflect.Elem object. But that observation might be irrelevant since you have not clearly stated the problem. 

--
Kurtis Rader
Caretaker of the exceptional canines Junior and Hank

tapi...@gmail.com

unread,
Feb 26, 2021, 1:42:32 AM2/26/21
to golang-nuts
What I mean is

    fmt.Println(v3)

and

    fmt.Println(v3.Elem())

print the same thing. Is it an intended design?

tapi...@gmail.com

unread,
Feb 26, 2021, 3:07:05 AM2/26/21
to golang-nuts
It looks, the fmt package makes some special handling for reflect.Value:

package main

import "reflect"
import "fmt"

func main() {
    var v1 = reflect.ValueOf(0)
    var p1 = &v1
    var v2 = 0
    var p2 = &v2
    var v3 interface{} = 0
    var p3 = &v3
    fmt.Println(p1)  // <int Value>
    fmt.Println(p2)  // 0xc0000b6020
    fmt.Println(p3)  // 0xc00009e220
}

clba...@gmail.com

unread,
Feb 26, 2021, 8:29:15 AM2/26/21
to golang-nuts
Yes.  You have to understand how "fmt.Print," etc., handle types with String() methods.  From the docs:

package fmt - 

5. If an operand implements method String() string, that method will be invoked to convert the object to a string, which will then be formatted as required by the verb (if any).

package reflect - 

func (Value) Elem
func (v Value) Elem() Value

Elem returns the value that the interface v contains or that the pointer v points to. It panics if v's Kind is not Interface or Ptr. It returns the zero Value if v is nil.

func (Value) String

func (v Value) String() string

String returns the string v's underlying value, as a string. String is a special case because of Go's String method convention. Unlike the other getters, it does not panic if v's Kind is not String. Instead, it returns a string of the form "<T value>" where T is v's type. The fmt package treats Values specially. It does not call their String method implicitly but instead prints the concrete values they hold.

Charles Banning

unread,
Feb 26, 2021, 10:16:38 AM2/26/21
to golang-nuts
Yes.  You need to understand how "fmt" handles types with String() methods.  From the docs:

func (Value) Elem
func (v Value) Elem() Value

Elem returns the value that the interface v contains or that the pointer v points to. It panics if v's Kind is not Interface or Ptr. It returns the zero Value if v is nil.

func (Value) String
func (v Value) String() string

String returns the string v's underlying value, as a string. String is a special case because of Go's String method convention. Unlike the other getters, it does not panic if v's Kind is not String. Instead, it returns a string of the form "<T value>" where T is v's type. The fmt package treats Values specially. It does not call their String method implicitly but instead prints the concrete values they hold.


On Thursday, February 25, 2021 at 11:42:32 PM UTC-7 tapi...@gmail.com wrote:

tapi...@gmail.com

unread,
Feb 26, 2021, 12:05:21 PM2/26/21
to golang-nuts
Thanks for the info.

The info does verify that reflect.Values are specially handled in fmt.Print,
and it also clearly sates String() method of the argument reflect.Values
are not called in fmt.Print:

    The fmt package treats Values specially.  It does not call their String method
    implicitly but instead prints the concrete values they hold.

It looks the docs is too simple, if not very accurate. It doesn't specify clearly
whether or not the "prints" operation in "but instead prints the concrete values they hold"
will call the String methods of the concrete values if the the concrete values
are also reflect.Values (a.k.a., indirect reflect.Values). The fact is it calls indeed.

IMHO, the design is some confusing.
Reply all
Reply to author
Forward
0 new messages