Diferença entre fmt.Println () e println () no Go

117

Conforme ilustrado abaixo, ambos fmt.Println()e println()fornecem a mesma saída em Go:Hello world!

Mas: como eles diferem um do outro?

Snippet 1, usando o fmtpacote;

package main

import (
    "fmt"
)

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

Snippet 2, sem o fmtpacote;

package main

func main() {
    println("Hello world!")
}
YulCheney
fonte

Respostas:

98

printlné uma função embutida (no tempo de execução) que pode eventualmente ser removida, enquanto o fmtpacote está na biblioteca padrão, que irá persistir. Veja as especificações sobre esse tópico.

Para desenvolvedores de linguagens, é útil ter um printlnsem dependências, mas o jeito é usar o fmtpacote ou algo semelhante ( logpor exemplo).

Como você pode ver na implementação, as print(ln)funções não foram projetadas para suportar nem mesmo remotamente um modo de saída diferente e são principalmente uma ferramenta de depuração.

nemo
fonte
108

Para desenvolver a resposta do nemo:

printlné uma função incorporada à linguagem. Ele está na seção Bootstrapping da especificação . Do link:

As implementações atuais fornecem várias funções integradas úteis durante a inicialização. Essas funções são documentadas para integridade, mas não é garantido que permaneçam no idioma. Eles não retornam um resultado.

Function   Behavior

print      prints all arguments; formatting of arguments is implementation-specific
println    like print but prints spaces between arguments and a newline at the end

Portanto, eles são úteis para os desenvolvedores, porque não possuem dependências (sendo construídas no compilador), mas não no código de produção. Também é importante observar isso printe println informar stderr, nãostdout .

A família fornecida por fmt, no entanto, é construída para estar em código de produção. Eles se reportam previsivelmente stdout, a menos que especificado de outra forma. Eles são mais versátil ( fmt.Fprint*pode denunciar a qualquer io.Writer, como os.Stdout, os.Stderr, ou mesmo um net.Conntipo.) E não são a implementação específica.

A maioria dos pacotes que são responsáveis ​​pela saída possuem fmtuma dependência, como log. Se o seu programa vai gerar qualquer coisa em produção, fmtprovavelmente é o pacote que você deseja.

Alexander Bauer
fonte
3

Eu posso ver a diferença aqui:

rangeOverIntsAndStrings (1, 5)

func rangeOverIntsAndStrings(args ...interface{}) {
    for _, v := range args {
        println(v)
    }
}

// resultado

(0x108f060,0x10c5358)
(0x108f060,0x10c5360)

vs

func rangeOverIntsAndStrings(args ...interface{}) {
    for _, v := range args {
        fmt.Println(v)
    }
}

// resultado

1
5
R Sun
fonte
1

Quanto à diferença, este é um exemplo.

println() imprime um ponteiro para o endereço do teste de função.

fmt.Println() imprime o endereço da função.

Steven
fonte
11
Eu não entendo o que você está tentando dizer.
Pierrot,
0

Exemplo interessante:

  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

É algo diferente entre printlne fmt.Printf.

g10guang
fonte