为什么在Go语言中,reflect.ValueOf()在被调用的函数和调用函数中的输出不同?

huangapple go评论87阅读模式
英文:

Why reflect.ValueOf() gives different output in called function and calling function in golang?

问题

为什么尽管起始值相同,s和s1的输出不同?帮助我理解。

package main

import (
	"fmt"
	"reflect"
)

type Auth struct {
	a, b interface{}
}

func main() {
	fmt.Println("--------p1,s1--------")
	p1 := Auth{}
	fmt.Println(p1)
	s1 := reflect.ValueOf(p1)
	fmt.Println(s1)

	fmt.Println("-------s---------")
	callFunc(p1)

}

func callFunc(a ...interface{}) {
	s := reflect.ValueOf(a)
	fmt.Println(s)

}

运行上述代码(go run nil.go)后的输出为:

为什么在Go语言中,reflect.ValueOf()在被调用的函数和调用函数中的输出不同?

英文:

Why the outputs of s and s1 differs although the starting value is same ? Help me understand

package main

import (
	"fmt"
	"reflect"
)

type Auth struct {
	a, b interface{}
}

func main() {
	fmt.Println("--------p1,s1--------")
	p1 := Auth{}
	fmt.Println(p1)
	s1 := reflect.ValueOf(p1)
	fmt.Println(s1)

	fmt.Println("-------s---------")
	callFunc(p1)

}

func callFunc(a ...interface{}) {
	s := reflect.ValueOf(a)
	fmt.Println(s)

}

Ps. Filename is nil.go
On running the code using :go run nil.go
The output is :

为什么在Go语言中,reflect.ValueOf()在被调用的函数和调用函数中的输出不同?

答案1

得分: 0

fmt 包的文档说明了在打印 reflect.Value 值时,它会打印包裹在其中的值:

> 除非使用 %T 和 %p 动词打印,否则对实现了特定接口的操作数应用特殊的格式化考虑。应用顺序如下:
> 1. 如果操作数是 reflect.Value,则操作数被替换为它所持有的具体值,并继续按照下一个规则打印。
>
> [...]

callFunc() 有一个可变参数:

func callFunc(a ...interface{}) 

这意味着 a 是一个切片。因此,当打印 reflect.ValueOf(a) 时,你将得到打印的切片。而且 fmt 包也说明了:

> 对于复合对象,元素将按照这些规则递归地打印,布局如下:
>
> 结构体: {字段0 字段1 ...}
> 数组、切片: [元素0 元素1 ...]
> 映射: map[键1:值1 键2:值2 ...]
> 上述类型的指针: &{}, &[], &map[]

切片将被打印在方括号中。

请注意,如果 callFunc() 不是可变参数的话:

func callFunc(a interface{}) {
	s := reflect.ValueOf(a)
	fmt.Println(s)
}

那么输出将是相同的(在 Go Playground 上尝试一下):

--------p1,s1--------
{<nil> <nil>}
{<nil> <nil>}
-------s---------
{<nil> <nil>}
英文:

The fmt package documents that when printing reflect.Value values, it prints the value wrapped inside them:

> Except when printed using the verbs %T and %p, special formatting considerations apply for operands that implement certain interfaces. In order of application:
> 1. If the operand is a reflect.Value, the operand is replaced by the concrete value that it holds, and printing continues with the next rule.
>
> [...]

callFunc() has a variadic parameter:

func callFunc(a ...interface{}) 

This means a is a slice. So when printing reflect.ValueOf(a), you'll get the slice printed. And the fmt package also documents that:

> For compound objects, the elements are printed using these rules, recursively, laid out like this:
>
> struct: {field0 field1 ...}
> array, slice: [elem0 elem1 ...]
> maps: map[key1:value1 key2:value2 ...]
> pointer to above: &{}, &[], &map[]

Slices are printed enclosed in square brackets.

Note that if callFunc() would not be variadic:

func callFunc(a interface{}) {
	s := reflect.ValueOf(a)
	fmt.Println(s)
}

Then output would be the same (try it on the Go Playground):

--------p1,s1--------
{&lt;nil&gt; &lt;nil&gt;}
{&lt;nil&gt; &lt;nil&gt;}
-------s---------
{&lt;nil&gt; &lt;nil&gt;}

huangapple
  • 本文由 发表于 2022年9月5日 18:35:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/73608029.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定