Sự khác biệt giữa fmt.Println () và println () trong Go


116

Như minh họa bên dưới, cả hai fmt.Println()println()cho cùng một đầu ra trong Go:Hello world!

Nhưng: chúng khác nhau như thế nào?

Đoạn 1, sử dụng fmtgói;

package main

import (
    "fmt"
)

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

Đoạn 2, không có fmtgói;

package main

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

Câu trả lời:


98

printlnlà một hàm tích hợp (vào thời gian chạy) cuối cùng có thể bị xóa, trong khi fmtgói nằm trong thư viện chuẩn, sẽ tồn tại. Xem thông số kỹ thuật về chủ đề đó.

Đối với các nhà phát triển ngôn ngữ, thật tiện lợi khi printlnkhông có sự phụ thuộc, nhưng cách để đi là sử dụng fmtgói hoặc một cái gì đó tương tự ( logví dụ).

Như bạn có thể thấy trong quá trình thực hiện, các print(ln)chức năng không được thiết kế để thậm chí hỗ trợ từ xa một chế độ đầu ra khác và chủ yếu là một công cụ gỡ lỗi.


108

Để xây dựng dựa trên câu trả lời của nemo:

printlnlà một chức năng được xây dựng trong ngôn ngữ. Nó nằm trong phần Bootstrapping của thông số kỹ thuật . Từ liên kết:

Các triển khai hiện tại cung cấp một số chức năng tích hợp hữu ích trong quá trình bootstrapping. Các chức năng này được ghi lại cho đầy đủ nhưng không được bảo đảm trong ngôn ngữ. Họ không trả lại kết quả.

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

Vì vậy, chúng hữu ích cho các nhà phát triển, vì họ thiếu phụ thuộc (được tích hợp vào trình biên dịch), nhưng không có trong mã sản xuất. Nó cũng quan trọng để lưu ý rằng printprintln báo cáo stderr, khôngstdout .

Gia đình được cung cấp bởi fmt, tuy nhiên, được xây dựng để được trong mã sản xuất. Họ báo cáo dự đoán stdout, trừ khi có quy định khác. Chúng được linh hoạt hơn ( fmt.Fprint*có thể báo cáo bất kỳ io.Writer, chẳng hạn như os.Stdout, os.Stderrhoặc thậm chí là một net.Connloại.) Và không thực hiện cụ thể.

Hầu hết các gói chịu trách nhiệm đầu ra đều có fmtsự phụ thuộc, chẳng hạn như log. Nếu chương trình của bạn sẽ xuất ra bất cứ thứ gì trong sản xuất, fmtrất có thể là gói mà bạn muốn.


3

Tôi có thể thấy sự khác biệt ở đây:

phạm viOverIntsAndStrings (1, 5)

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

// đầu ra

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

đấu với

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

// đầu ra

1
5

1

Đối với sự khác biệt, đây là một ví dụ.

println() in một điểm con trỏ đến địa chỉ kiểm tra chức năng.

fmt.Println() in địa chỉ của hàm.


11
Tôi không hiểu những gì bạn đang cố nói.
Pierrot

0

Ví dụ thú vị:

  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

Đó là một cái gì đó khác biệt giữa printlnfmt.Printf.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.