Go println()、fmt.Println()7个不同的地方

698 阅读2分钟

差异对比

下面的println()指代内置的println()和print(),fmt.Pritnln()指代fmt.Println()、fmt.Printf()和fmt.Print()。

例子

第一行使用fmt.Println(),第二行使用println()。输出的第一行红色的是println()第二行白色的是fmt.Println()。

package main

import (
	"fmt"
)

func main() {
	fmt.Println("Hello fmt.Println()!")
	println("Hello println!")
}

image.png

1、所在包不同

println()在builtin包下,因此可以直接使用;而fmt.Println()不在builtin包下,因此需要import才可以使用。

2、返回值不同

func Println(a ...interface{}) (n int, err error) // fmt.Pritnln()
func println(args ...Type) // println()

fmt.Pritnln()会返回写入的字节数量和写的时候发生的任何错误;而println()没有返回值。

3、输出流不同

fmt.Pritnln()写入的流是标准输出流因此是白色的;而println()写入的流是标准错误流因此是红色的。

4、接收的参数类型不同

println()不能接受数组和结构体参数。

5、格式化方式不同

fmt.Pritnln()输出的是字面值(每个成员的值);而println()输出的是值(参数的值);

package main

import (
   "fmt"
   "reflect"
)

type test struct {
   a int
   b *string
}

func main() {
   b := "x"
   t := &test{
      a: 1,
      b: &b,
   }
   println(t)
   fmt.Println(t)
   fmt.Printf("0x%x\n", reflect.ValueOf(t).Pointer())
}

第一行println();第二行fmt.Println();第三行t的值(也就是地址值)。 image.png

如果参数有实现Stringer接口,那么fmt.Println()会调用这个参数的String()方法:

package main

import (
   "fmt"
   "reflect"
)

type test struct {
   a int
   b *string
}

func (s *test) String() string {
   return fmt.Sprintf("%d : %s", s.a, *s.b)
}

func main() {
   b := "x"
   t := &test{
      a: 1,
      b: &b,
   }
   println(t)
   fmt.Println(t)
   fmt.Printf("0x%x\n", reflect.ValueOf(t).Pointer())
}

image.png

6、参数逃逸不同

对于标准编译器,调用println()函数不会使调用参数引用的值逃逸到堆上,而fmt.Println()函数将使调用参数引用的值逃逸到堆上

7、兼容性不同

println()方法不保证在Go后续版本继续存在。

总结

平时使用fmt.Println()方法即可,println()用于底层代码的引导和调试。

参考

gfw.go101.org/article/uno…