【问题标题】:Why Golang display different values when use different output function为什么 Golang 在使用不同的输出函数时显示不同的值
【发布时间】:2018-01-24 10:51:35
【问题描述】:

我尝试检查 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)

谁能解释这种行为的机制?谢谢!

【问题讨论】:

    标签: go


    【解决方案1】:

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

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

    spec 还提到:

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

    实现限制:print 和 println 不需要 接受任意参数类型,但打印布尔值、数字和 必须支持字符串类型。

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

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

    也就是说,我猜在你的情况下它正在打印内部接口字段:一个指向类型的指针和一个值。

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-20
        • 2014-01-09
        • 2018-08-18
        • 1970-01-01
        相关资源
        最近更新 更多