Diferencia entre fmt.Println () y println () en Go

117

Como se ilustra a continuación, ambos fmt.Println()y println()dan el mismo resultado en Go:Hello world!

Pero, ¿en qué se diferencian entre sí?

Fragmento 1, usando el fmtpaquete;

package main

import (
    "fmt"
)

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

Fragmento 2, sin el fmtpaquete;

package main

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

Respuestas:

98

printlnes una función incorporada (en el tiempo de ejecución) que eventualmente se puede eliminar, mientras que el fmtpaquete está en la biblioteca estándar, que persistirá. Consulte las especificaciones sobre ese tema.

Para los desarrolladores de lenguajes es útil tener un printlnsin dependencias, pero el camino a seguir es usar el fmtpaquete o algo similar ( logpor ejemplo).

Como puede ver en la implementación, las print(ln)funciones no están diseñadas para admitir ni remotamente un modo de salida diferente y son principalmente una herramienta de depuración.

nemo
fuente
108

Para construir sobre la respuesta de nemo:

printlnes una función integrada en el lenguaje. Está en la sección Bootstrapping de la especificación . Desde el enlace:

Las implementaciones actuales proporcionan varias funciones integradas útiles durante el arranque. Estas funciones están documentadas para que estén completas, pero no se garantiza que permanezcan en el idioma. No devuelven un 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

Por lo tanto, son útiles para los desarrolladores, porque carecen de dependencias (están integradas en el compilador), pero no en el código de producción. También es importante tener en cuenta eso printe println informar stderr, nostdout .

fmtSin embargo, la familia proporcionada por está construida para estar en código de producción. Informan previsiblemente a stdout, a menos que se especifique lo contrario. Ellos son más versátiles ( fmt.Fprint*pueden informar a cualquiera io.Writer, como por ejemplo os.Stdout, os.Stderro incluso un net.Conntipo.) Y no son específicos de la aplicación.

La mayoría de los paquetes que son responsables de la salida tienen fmtuna dependencia, como log. Si su programa va a generar algo en producción, fmtlo más probable es que sea el paquete que desea.

Alexander Bauer
fuente
3

Puedo ver la diferencia aquí:

rangeOverIntsAndStrings (1, 5)

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

// salida

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

vs

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

// salida

1
5
R Sol
fuente
1

En cuanto a la diferencia, este es un ejemplo.

println() imprime un puntero a la dirección de la función de prueba.

fmt.Println() imprime la dirección de la función.

Steven
fuente
11
No entiendo lo que intentas decir.
Pierrot
0

Ejemplo interesante:

  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

Es algo diferente entre printlny fmt.Printf.

g10guang
fuente