Différence entre fmt.Println () et println () dans Go

117

Comme illustré ci-dessous, les deux fmt.Println()et println()donnent le même résultat dans Go:Hello world!

Mais: en quoi diffèrent-ils les uns des autres?

Extrait 1, en utilisant le fmtpackage;

package main

import (
    "fmt"
)

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

Extrait 2, sans le fmtpackage;

package main

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

Réponses:

98

printlnest une fonction intégrée (dans le runtime) qui peut éventuellement être supprimée, tandis que le fmtpaquet est dans la bibliothèque standard, qui persistera. Voir les spécifications sur ce sujet.

Pour les développeurs de langage, il est pratique d'avoir un printlnsans dépendances, mais la voie à suivre est d'utiliser le fmtpackage ou quelque chose de similaire ( logpar exemple).

Comme vous pouvez le voir dans l'implémentation, les print(ln)fonctions ne sont pas conçues pour prendre en charge même à distance un mode de sortie différent et sont principalement un outil de débogage.

nemo
la source
108

Pour construire sur la réponse de Nemo:

printlnest une fonction intégrée à la langue. C'est dans la section Bootstrapping de la spécification . Depuis le lien:

Les implémentations actuelles fournissent plusieurs fonctions intégrées utiles lors de l'amorçage. Ces fonctions sont documentées par souci d'exhaustivité mais ne sont pas garanties de rester dans la langue. Ils ne renvoient pas de résultat.

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

Ainsi, ils sont utiles aux développeurs, car ils manquent de dépendances (en cours de construction dans le compilateur), mais pas dans le code de production. Il est également important de le noter printet d'en faire println rapport stderr, nonstdout .

La famille fournie par fmt, cependant, est conçue pour être en code de production. Ils font rapport de manière prévisible à stdout, sauf indication contraire. Ils sont plus polyvalents ( fmt.Fprint*peut signaler à tout io.Writer, comme os.Stdout, os.Stderrou même le net.Conntype.) Et ne sont pas spécifiques de mise en œuvre.

La plupart des packages responsables de la sortie ont fmt une dépendance, telle que log. Si votre programme doit produire quelque chose en production, fmtc'est probablement le package que vous souhaitez.

Alexander Bauer
la source
3

Je peux voir la différence ici:

rangeOverIntsAndStrings (1, 5)

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

// production

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

contre

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

// production

1
5
Soleil R
la source
1

Quant à la différence, ceci est un exemple.

println() imprime un pointeur vers l'adresse du test de fonction.

fmt.Println() imprime l'adresse de la fonction.

Steven
la source
11
Je ne comprends pas ce que vous essayez de dire.
Pierrot
0

Exemple intéressant:

  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

C'est quelque chose de différent entre printlnet fmt.Printf.

g10guang
la source