为什么Golang在使用不同的输出功能时会显示不同的值

时间:2018-01-24 10:51:35

标签: go

我尝试检查Golang何时将本地值返回为nil,然后我使用此代码。

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)
}

输出是 为0x0

但是当我只使用println输出值时。

package main

type S struct{}

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

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

输出更改为 为0x0 (0x93d40,0x0)

有人能解释一下这种行为的机制吗?谢谢!

2 个答案:

答案 0 :(得分:3)

你不应该使用builtin println,它明确指出:

  

println内置函数将其参数格式化为   特定于实现的方式并将结果写入标准错误。   始终在参数之间添加空格,并附加换行符。   Println对于引导和调试很有用;它不是   保证保持语言。

spec也提到:

  

当前的实现提供了几个有用的内置函数   在自举期间。记录这些功能是为了完整性   但不保证保持语言。他们没有返回   结果

     

实施限制:不需要打印和打印   接受任意参数类型,但打印boolean,numeric和   必须支持字符串类型。

就是这样。 printprintln是有用的调试工具,但不应该依赖于:

  • 提供特定输出
  • 在不同平台上提供相同的输出
  • 随时间提供相同的输出
  • 存在

那就是说,我猜你的情况是打印内部接口字段:指向类型的指针和值。

答案 1 :(得分:1)

首先,fmt.Println和内置println是完全不同的问题:它们在实现和目的上都是不同的。 fmt.Println使用反射处理许多复杂的情况,println只处理一些基本情况,仅用于“引导或调试”(如规范所述)。

在这种特定情况下,您正在打印从interface{}返回的InitEfacePointer()fmt.Println使用reflect查看接口并获取基础数据:指向字符串的nil指针,然后将其打印出来:0x0。另一方面,内置println采用接口和编译器的魔力(或不是),它识别它是一个接口。作为this post,golang接口实际上是两个指针,一个指向存储类型的信息,另一个指向底层数据。因此内置println进入界面细节,0x93d40是“类型信息”,0x0是底层数据。 (第一个0x0来自函数调用)。

此外,测试返回的接口是否为nil似乎是一个常见的错误。请在此处阅读:https://golang.org/doc/faq#nil_error