ความแตกต่างระหว่าง fmt.Println () และ println () ใน Go


117

ดังภาพประกอบด้านล่างทั้งสองfmt.Println()และprintln()ให้ผลลัพธ์เดียวกันใน Go:Hello world!

แต่: พวกเขาแตกต่างจากกันอย่างไร?

ตัวอย่างข้อมูล 1 โดยใช้fmtแพ็คเกจ

package main

import (
    "fmt"
)

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

Snippet 2 ไม่มีfmtแพ็คเกจ

package main

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

คำตอบ:


98

printlnเป็นฟังก์ชันในตัว (ในรันไทม์) ซึ่งอาจถูกลบออกในที่สุดในขณะที่fmtแพ็กเกจอยู่ในไลบรารีมาตรฐานซึ่งจะยังคงอยู่ ดูข้อมูลจำเพาะของหัวข้อนั้น

สำหรับนักพัฒนาภาษามันเป็นเรื่องสะดวกที่จะมีการprintlnอ้างอิง แต่วิธีที่จะไปคือการใช้fmtแพคเกจหรือสิ่งที่คล้ายกัน ( logเช่น)

ขณะที่คุณสามารถเห็นในการดำเนินการprint(ln)ฟังก์ชั่นที่ไม่ได้ออกแบบมาเพื่อได้จากระยะไกลสนับสนุนโหมดการส่งออกที่แตกต่างกันและส่วนใหญ่จะเป็นเครื่องมือในการแก้ปัญหา


108

เพื่อสร้างคำตอบของนีโม:

printlnเป็นฟังก์ชันที่สร้างขึ้นในภาษา มันมีอยู่ในส่วนร่วมมือของสเปค จากลิงค์:

การใช้งานในปัจจุบันมีฟังก์ชันในตัวหลายอย่างที่เป็นประโยชน์ในระหว่างการบูตเครื่อง ฟังก์ชันเหล่านี้ได้รับการบันทึกไว้เพื่อความสมบูรณ์ แต่ไม่รับประกันว่าจะอยู่ในภาษา พวกเขาไม่ส่งคืนผลลัพธ์

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

ดังนั้นจึงมีประโยชน์สำหรับนักพัฒนาเนื่องจากไม่มีการอ้างอิง (ถูกสร้างไว้ในคอมไพเลอร์) แต่ไม่อยู่ในรหัสการผลิต มันยังเป็นสิ่งสำคัญที่จะทราบว่าprintและprintln รายงานไปยังstderrstdoutไม่

อย่างไรก็ตามตระกูลที่จัดหาให้fmtนั้นสร้างขึ้นเพื่อให้อยู่ในรหัสการผลิต รายงานโดยคาดการณ์ได้stdoutเว้นแต่จะระบุไว้เป็นอย่างอื่น พวกเขามีความอเนกประสงค์ ( fmt.Fprint*สามารถรายงานใด ๆio.Writerเช่นos.Stdout, os.Stderrหรือแม้กระทั่งnet.Connประเภท.) และไม่ได้ดำเนินการเฉพาะ

แพ็กเกจส่วนใหญ่ที่รับผิดชอบเอาต์พุตมีfmtการพึ่งพาเช่นlog. หากโปรแกรมของคุณกำลังจะแสดงผลอะไรก็ตามในการผลิตfmtส่วนใหญ่มักจะเป็นแพ็คเกจที่คุณต้องการ


3

ฉันเห็นความแตกต่างที่นี่:

rangeOverIntsAndStrings (1, 5)

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

// เอาต์พุต

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

VS

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

// เอาต์พุต

1
5

1

สำหรับความแตกต่างนี้เป็นตัวอย่าง

println() พิมพ์จุดชี้ไปยังที่อยู่ของการทดสอบฟังก์ชัน

fmt.Println() พิมพ์ที่อยู่ของฟังก์ชัน


11
ฉันไม่เข้าใจในสิ่งที่คุณพยายามจะพูด
Pierrot

0

ตัวอย่างที่น่าสนใจ:

  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

มันเป็นสิ่งที่แตกต่างระหว่างและprintlnfmt.Printf

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.