如何在Go中打印数组项的类型?

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

How to print type of array items in Go?

问题

当我尝试对一些代码进行单元测试时,我有一些像这样的断言:

expected := []interface{}{1}
actual := []interface{}{float64(1)}

if !reflect.DeepEqual(expected, actual); {
    t.Errorf("期望值 <%T> %#v 与实际值 <%T> %#v 不相等", actual, actual, expected, expected);
}

并且得到了以下输出:

期望值 <[]interface {}> []interface {}{1} 与实际值 <[]interface {}> []interface {}{1}

我该如何打印这个消息以使其更明确?

谢谢!

英文:

When I try to unit test some code, I have some assertion like this:

expected := []interface{}{1}
actual := []interface{}{float64(1)}

if !reflect.DeepEqual(expected, actual); {
    t.Errorf(&quot;Expected &lt;%T&gt; %#v to equal &lt;%T&gt; %#v&quot;, actual, actual, expected, expected);
}

And got this output:

Expected &lt;[]interface {}&gt; []interface {}{1} to equal &lt;[]interface {}&gt; []interface {}{1}

How can I print this message to be more explicit?

Thanks!

<iframe src="http://play.golang.org/p/JigknXTcdx" frameborder="0" style="width: 100%; height: 100%"><a href="http://play.golang.org/p/JigknXTcdx">see this code in play.golang.org</a></iframe>

答案1

得分: 3

你正在打印切片的类型,而不是元素的类型。切片的类型是[]interface{},这就是你看到的结果。

如果你想要看到元素的动态类型(它们的静态类型始终是interface{}),那么可以打印元素的类型:

fmt.Printf("Expected element type: %T, got: %T", expected[0], actual[0])

这将输出:

Expected element type: int, got: float64

注意:

上面的代码假设你正在比较包含1个元素的两个切片。如果你不想检查切片的长度,并且想处理任意长度的切片,你可以使用其他的格式化动词。例如,你可以使用%t动词,它期望一个bool值,并打印truefalse。请注意,这只是一种实现决策,并不是保证,但是使用%t将打印所有切片元素;如果元素的类型是bool,则打印相应的bool值;如果元素的类型不是bool,则打印元素的动态类型和值。

示例:

data := []interface{}{1, float64(2), "3", time.Now()}
fmt.Printf("%t", data)

输出:

[%!t(int=1) %!t(float64=2) %!t(string=3) {%!t(int64=63393490800) %!t(int32=0) %!t(*time.Location=&{ [] [] 0 0 <nil>})}]

这看起来有点丑,但包含了许多有用的信息(例如类型、值)。

英文:

You are printing the types of the slices, not the types of the elements. And types of the slices are []interface{}. That's why you see that.

If you want to see the dynamic types of the elements (their static type is always interface{}), then print the types of the elements:

fmt.Printf(&quot;Expected element type: %T, got: %T&quot;, expected[0], actual[0])

Which will output:

Expected element type: int, got: float64

Note:

The above code assumes you are comparing 2 slices with 1 element. If you don't want to check slice length and you want to handle slices with any length, you can use other verbs. For example you can use the %t verb which expects a bool value and wants to print true or false. Note that this is just an implementation decision and not guaranteed, but using %t for example will print all the slice elements; printing the respective bool value if it is of type bool, and will print the dynamic type and value of the element if the it is not of type bool.

Example:

data := []interface{}{1, float64(2), &quot;3&quot;, time.Now()}
fmt.Printf(&quot;%t&quot;, data)

Output:

[%!t(int=1) %!t(float64=2) %!t(string=3)
    {%!t(int64=63393490800) %!t(int32=0) %!t(*time.Location=&amp;{ [] [] 0 0 &lt;nil&gt;})}]

It's a bit ugly, but contains many useful info (e.g. types, values).

huangapple
  • 本文由 发表于 2015年9月18日 21:21:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/32653109.html
匿名

发表评论

匿名网友

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

确定