Różnica między fmt.Println () i println () w Go

117

Jak pokazano poniżej, oba fmt.Println()i println()dają te same wyniki w Go:Hello world!

Ale: czym różnią się od siebie?

Snippet 1, używając fmtpakietu;

package main

import (
    "fmt"
)

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

Snippet 2, bez fmtpakietu;

package main

func main() {
    println("Hello world!")
}
YulCheney
źródło

Odpowiedzi:

98

printlnjest funkcją wbudowaną (w środowisku wykonawczym), która może zostać ostatecznie usunięta, gdy fmtpakiet znajduje się w bibliotece standardowej, która będzie trwała. Zobacz specyfikację na ten temat.

Dla programistów językowych przydatne jest posiadanie printlnbez zależności, ale sposobem jest użycie fmtpakietu lub czegoś podobnego ( logna przykład).

Jak można zobaczyć w realizacji te print(ln)funkcje nie są przeznaczone do nawet zdalnie obsługiwać inny tryb wyjścia i to przede wszystkim narzędzie do debugowania.

nemo
źródło
108

Opierając się na odpowiedzi nemo:

printlnto funkcja wbudowana w język. Znajduje się w sekcji Bootstrapping specyfikacji . Z linku:

Obecne implementacje zapewniają kilka wbudowanych funkcji przydatnych podczas ładowania początkowego. Funkcje te są udokumentowane pod kątem kompletności, ale nie gwarantuje się, że pozostaną w języku. Nie zwracają wyniku.

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

Dlatego są przydatne dla programistów, ponieważ brakuje im zależności (są wbudowane w kompilator), ale nie są w kodzie produkcyjnym. Ważne jest również, aby to zauważyć printi println zgłosić się stderr, że niestdout .

Rodziny dostarczone przez są fmtjednak zbudowane tak, aby były w kodzie produkcyjnym. Zgłaszają się w sposób przewidywalny stdout, chyba że określono inaczej. Są bardziej uniwersalne ( fmt.Fprint*mogą zgłosić się do dowolnego io.Writer, takich jak os.Stdout, os.Stderrczy nawetnet.Conn rodzaj.) I nie są specyficzne dla implementacji.

Większość pakietów odpowiedzialnych za dane wyjściowe ma fmtjako zależność, taką jak log. Jeśli twój program ma wypisywać cokolwiek w środowisku produkcyjnym, fmtnajprawdopodobniej jest to pakiet, którego potrzebujesz.

Alexander Bauer
źródło
3

Widzę tutaj różnicę:

rangeOverIntsAndStrings (1, 5)

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

// wynik

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

vs

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

// wynik

1
5
R Sun
źródło
1

Jeśli chodzi o różnicę, to jest przykład.

println() wypisuje wskaźnik do adresu testu funkcji.

fmt.Println() wypisuje adres funkcji.

Steven
źródło
11
Nie rozumiem tego, co próbujesz powiedzieć.
Pierrot
0

Ciekawy przykład:

  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

To jest różnica między printlni fmt.Printf.

g10guang
źródło