Differenza tra fmt.Println () e println () in Go


117

Come illustrato di seguito, entrambi fmt.Println()e println()danno lo stesso output in Go:Hello world!

Ma: come si differenziano l'uno dall'altro?

Snippet 1, utilizzando il fmtpacchetto;

package main

import (
    "fmt"
)

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

Snippet 2, senza il fmtpacchetto;

package main

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

Risposte:


98

printlnè una funzione incorporata (nel runtime) che può eventualmente essere rimossa, mentre il fmtpacchetto è nella libreria standard, che persisterà. Vedi le specifiche su quell'argomento.

Per gli sviluppatori di linguaggi è utile avere un printlnsenza dipendenze, ma la strada da percorrere è usare il fmtpacchetto o qualcosa di simile ( logad esempio).

Come puoi vedere nell'implementazione, le print(ln)funzioni non sono progettate per supportare nemmeno in remoto una diversa modalità di output e sono principalmente uno strumento di debug.


108

Per basarsi sulla risposta di nemo:

printlnè una funzione incorporata nella lingua. È nella sezione Bootstrapping delle specifiche . Dal link:

Le attuali implementazioni forniscono diverse funzioni integrate utili durante il bootstrap. Queste funzioni sono documentate per completezza ma non è garantito che rimangano nella lingua. Non restituiscono un risultato.

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

Pertanto, sono utili per gli sviluppatori, perché mancano di dipendenze (essendo incorporate nel compilatore), ma non nel codice di produzione. È anche importante notare che printe println riferire a stderr, nostdout .

La famiglia fornita da fmt, invece, è costruita per essere in codice di produzione. Riferiscono prevedibilmente a stdout, se non diversamente specificato. Sono più versatile ( fmt.Fprint*può riferire a qualsiasi io.Writer, come ad esempio os.Stdout, os.Stderro anche unnet.Conn tipo.) E non sono un'implementazione specifica.

La maggior parte dei pacchetti che sono responsabili dell'output hanno fmtcome dipendenza, come log. Se il tuo programma emetterà qualcosa in produzione, fmtmolto probabilmente è il pacchetto che desideri.


3

Posso vedere la differenza qui:

rangeOverIntsAndStrings (1, 5)

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

// produzione

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

vs

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

// produzione

1
5

1

Per quanto riguarda la differenza, questo è un esempio.

println() stampa un puntatore che punta all'indirizzo del test di funzione.

fmt.Println() stampa l'indirizzo della funzione.


11
Non capisco quello che stai cercando di dire.
Pierrot

0

Esempio 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

È qualcosa di diverso tra printlne fmt.Printf.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.