println
是一个内置函数(在运行时中),最终可能会被删除,而 fmt
包在标准库中,它将持续存在。请参阅关于该主题的 the spec。
对于语言开发人员来说,拥有一个没有依赖关系的 println
很方便,但要走的路是使用 fmt
包或类似的东西(例如 log
)。
如您所见,see in the implementation print(ln)
函数甚至不是为远程支持不同的输出模式而设计的,它主要是一个调试工具。
以尼莫的回答为基础:
println
是语言中内置的函数。它位于 spec 的引导部分。从链接:
当前的实现提供了几个在引导期间有用的内置函数。这些功能已记录在案以确保完整性,但不保证保留在该语言中。他们不返回结果。 Function Behavior print 打印所有参数;参数的格式是特定于实现的 println,如 print,但在参数和末尾的换行符之间打印空格
因此,它们对开发人员很有用,因为它们缺少依赖项(内置在编译器中),但在生产代码中却没有。还需要注意的是,print
和 println
报告给 stderr
,而不是 stdout
。
但是,fmt
提供的系列是在生产代码中构建的。除非另有说明,否则它们可预测地向 stdout
报告。它们更加通用(fmt.Fprint*
可以向任何 io.Writer
报告,例如 os.Stdout
、os.Stderr
甚至 net.Conn
类型。)并且不是特定于实现的。
大多数负责输出的包都有 fmt
作为依赖项,例如 log
。如果您的程序要在生产中输出任何内容,那么 fmt
很可能是您想要的包。
我可以在这里看到区别:
rangeOverIntsAndStrings(1, 5)
func rangeOverIntsAndStrings(args ...interface{}) {
for _, v := range args {
println(v)
}
}
// 输出
(0x108f060,0x10c5358)
(0x108f060,0x10c5360)
对比
func rangeOverIntsAndStrings(args ...interface{}) {
for _, v := range args {
fmt.Println(v)
}
}
// 输出
1
5
有趣的例子:
➜ netpoll git:(develop) ✗ cat test.go
package main
import "fmt"
func main() {
a := new(struct{})
b := new(struct{})
println(a, b, a == b)
c := new(struct{})
d := new(struct{})
fmt.Printf("%v %v %v\n", c, d, c == d)
}
➜ netpoll git:(develop) ✗ go run test.go
0xc000074f47 0xc000074f47 false
&{} &{} true
➜ netpoll git:(develop) ✗ go run -gcflags="-m" test.go
# command-line-arguments
./test.go:12:12: inlining call to fmt.Printf
./test.go:6:10: new(struct {}) does not escape
./test.go:7:10: new(struct {}) does not escape
./test.go:10:10: new(struct {}) escapes to heap
./test.go:11:10: new(struct {}) escapes to heap
./test.go:12:35: c == d escapes to heap
./test.go:12:12: []interface {} literal does not escape
<autogenerated>:1: .this does not escape
0xc000074f47 0xc000074f47 false
&{} &{} true
println
和 fmt.Printf
之间有些不同。
println
与fmt.Println
进行比较?