欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go輸入與輸出格式化案例詳解

 更新時間:2025年10月10日 09:36:31   作者:數(shù)據(jù)知道  
Go語言的輸入與輸出格式化功能非常強大,通過 fmt 包和 bufio 包,可以滿足各種輸入輸出需求,本文給大家介紹Go輸入與輸出格式化案例,感興趣的朋友一起看看吧

一、Go語言輸入與輸出概述

Go語言中,輸入與輸出(I/O)操作主要通過 fmt 包和 bufio 包實現(xiàn)。fmt 包提供了基本的格式化輸入輸出功能,而 bufio 包則用于更高效的緩沖讀寫操作。

二、輸出格式化詳解

2.1 常用輸出函數(shù)

Go語言中,fmt 包提供了以下常用輸出函數(shù):

  • fmt.Print(a ...interface{}):打印參數(shù),不添加換行。
  • fmt.Println(a ...interface{}):打印參數(shù),自動添加空格和換行。
  • fmt.Printf(format string, a ...interface{}):按格式化字符串打印。
  • fmt.Sprintf(format string, a ...interface{}):返回格式化后的字符串,不打印。
  • fmt.Fprintf(w io.Writer, format string, a ...interface{}):將格式化內(nèi)容寫入 io.Writer。

2.2 格式化動詞(Verbs)

格式化動詞用于控制輸出格式,常用動詞包括:

動詞說明
%v值的默認格式
%+v類似 %v,但輸出結(jié)構(gòu)體時會添加字段名
%#v值的 Go 語法表示
%T值的類型
%%百分號
%d十進制整數(shù)
%b二進制整數(shù)
%x十六進制整數(shù)(小寫)
%f浮點數(shù)
%s字符串
%p指針地址

2.3 案例

package main
import (
	"fmt"
	"os"
)
type Person struct {
	Name string
	Age  int
}
func main() {
	// 基本輸出
	fmt.Print("Hello, ")
	fmt.Println("World!")
	// 格式化輸出
	name := "Alice"
	age := 25
	fmt.Printf("Name: %s, Age: %d\n", name, age)
	// 結(jié)構(gòu)體格式化
	person := Person{Name: "Bob", Age: 30}
	fmt.Printf("Person: %v\n", person)         // 輸出: Person: {Bob 30}
	fmt.Printf("Person: %+v\n", person)        // 輸出: Person: {Name:Bob Age:30}
	fmt.Printf("Person: %#v\n", person)        // 輸出: Person: main.Person{Name:"Bob", Age:30}
	// 返回格式化字符串
	formattedStr := fmt.Sprintf("Name: %s, Age: %d", name, age)
	fmt.Println("Formatted string:", formattedStr)
	// 寫入文件
	file, err := os.Create("output.txt")
	if err != nil {
		fmt.Println("Error creating file:", err)
		return
	}
	defer file.Close()
	fmt.Fprintf(file, "This is written to a file. Name: %s, Age: %d\n", name, age)
	fmt.Println("Data written to file.")
}

三、輸入格式化詳解

3.1 常用輸入函數(shù)

Go語言中,fmt 包提供了以下常用輸入函數(shù):

  • fmt.Scan(a ...interface{}):從標準輸入讀取數(shù)據(jù),按空格分隔。
  • fmt.Scanln(a ...interface{}):類似 Scan,但讀取到換行符時停止。
  • fmt.Scanf(format string, a ...interface{}):按格式化字符串讀取輸入。

3.2 案例

package main
import (
	"bufio"
	"fmt"
	"os"
	"strings"
)
func main() {
	// 使用 fmt.Scan 讀取輸入
	var name string
	var age int
	fmt.Print("Enter your name and age (separated by space): ")
	fmt.Scan(&name, &age)
	fmt.Printf("Name: %s, Age: %d\n", name, age)
	// 使用 fmt.Scanln 讀取輸入
	fmt.Print("Enter your name: ")
	fmt.Scanln(&name)
	fmt.Printf("Name: %s\n", name)
	// 使用 fmt.Scanf 讀取格式化輸入
	fmt.Print("Enter your name and age (format: Name Age): ")
	fmt.Scanf("%s %d", &name, &age)
	fmt.Printf("Name: %s, Age: %d\n", name, age)
	// 使用 bufio 讀取整行輸入
	reader := bufio.NewReader(os.Stdin)
	fmt.Print("Enter a sentence: ")
	sentence, _ := reader.ReadString('\n')
	sentence = strings.TrimSpace(sentence)
	fmt.Printf("You entered: %s\n", sentence)
}

代碼說明

  1. 輸出部分
    • PrintPrintln 用于簡單輸出,后者會自動換行。
    • Printf 支持格式化動詞,可以靈活控制輸出格式。
    • Sprintf 返回格式化后的字符串,不直接打印。
    • Fprintf 將格式化內(nèi)容寫入 io.Writer,如文件。
  2. 輸入部分
    • ScanScanln 用于讀取標準輸入,按空格或換行符分隔。
    • Scanf 支持格式化輸入,適用于特定格式的數(shù)據(jù)讀取。
    • bufio.NewReader 提供更高效的緩沖讀取功能,適合讀取整行輸入。

四、Go語言bufio詳解

bufio 是 “buffered I/O” 的縮寫,它通過在 I/O 操作中引入緩沖區(qū)來提升性能。這個包包裝了 io.Readerio.Writer 對象,創(chuàng)建了新的、帶緩沖的 ReaderWriter 實例,提供了額外的功能。

4.1 為什么需要bufio?(核心思想)

想象一下沒有緩沖區(qū)的 I/O 操作,就像用一個非常小的勺子(比如一次只能裝一個字節(jié))從一個大水桶(文件或網(wǎng)絡連接)里取水。每次取水都需要一個完整的“伸手-舀水-收回”的動作,這個過程的開銷很大。
bufio 的作用就是引入一個“水杯”(緩沖區(qū))?,F(xiàn)在你的操作變成了:

  1. 用勺子從水桶里快速舀滿一杯水(一次性讀取一大塊數(shù)據(jù)到緩沖區(qū))。
  2. 需要用水時,直接從水杯里倒(從緩沖區(qū)讀取數(shù)據(jù)給程序)。
    這個過程大大減少了“伸手-舀水-收回”的次數(shù),從而顯著提高了 I/O 效率,尤其是在處理大量小數(shù)據(jù)塊或網(wǎng)絡通信時。

核心優(yōu)勢:

  • 減少系統(tǒng)調(diào)用:將多次小的讀/寫操作合并為少數(shù)幾次大的操作,減少了昂貴的系統(tǒng)調(diào)用次數(shù)。
  • 提供高級功能:除了性能提升,bufio 還提供了許多便捷的方法,如按行讀取、按單詞讀取等。

4.2bufio.Reader:帶緩沖的讀取器

bufio.Reader 是一個結(jié)構(gòu)體,它包裝了一個 io.Reader 接口。

1、創(chuàng)建 bufio.Reader:使用 bufio.NewReader 函數(shù)創(chuàng)建

func NewReader(rd io.Reader) *Reader

示例: 從標準輸入創(chuàng)建一個緩沖讀取器。

package main
import (
	"bufio"
	"fmt"
	"os"
)
func main() {
	// os.Stdin 實現(xiàn)了 io.Reader 接口
	reader := bufio.NewReader(os.Stdin)
	fmt.Printf("創(chuàng)建了一個緩沖區(qū)大小為 %d 字節(jié)的 Reader\n", reader.Size())
}

2、核心方法bufio.Reader 提供了一系列強大的讀取方法。

a) ReadString(delim byte) - 按分隔符讀取
這是最常用的方法之一。它會讀取數(shù)據(jù),直到遇到指定的分隔符 delim,然后返回包含分隔符在內(nèi)的字符串。

func (b *Reader) ReadString(delim byte) (string, error)

示例: 逐行讀取用戶輸入,直到用戶輸入 “exit”。

package main
import (
	"bufio"
	"fmt"
	"os"
	"strings"
)
func main() {
	reader := bufio.NewReader(os.Stdin)
	fmt.Println("請輸入內(nèi)容(輸入 'exit' 退出):")
	for {
		fmt.Print("> ")
		// 讀取直到遇到換行符 '\n'
		input, err := reader.ReadString('\n')
		if err != nil {
			fmt.Println("讀取錯誤:", err)
			return
		}
		// 去除字符串兩端的空白字符(包括換行符)
		input = strings.TrimSpace(input)
		if input == "exit" {
			fmt.Println("程序退出。")
			break
		}
		fmt.Println("你輸入了:", input)
	}
}

b) ReadBytes(delim byte) - 按分隔符讀取字節(jié)切片
ReadString 類似,但返回的是 []byte 類型,在處理二進制數(shù)據(jù)或需要更高性能時非常有用。

func (b *Reader) ReadBytes(delim byte) ([]byte, error)

c) ReadLine() - 讀取一行(不包含行尾符)
這是一個底層方法,它會讀取一行,但不包含行尾的 \r\n。它返回三個值:line (內(nèi)容), isPrefix (是否過長), err (錯誤)。通常我們更常用 ReadString('\n'),因為它更簡單直觀。

d) ReadSlice(delim byte) - 讀取到分隔符的切片

這個方法返回的是對緩沖區(qū)內(nèi)部數(shù)據(jù)的引用,而不是拷貝。這意味著下一次讀取操作可能會覆蓋這次返回的數(shù)據(jù)。它性能更高,但使用起來需要更小心。

e) Peek(n int) - 預覽數(shù)據(jù)
Peek 返回緩沖區(qū)接下來的 n 個字節(jié),但不會移動讀取指針。也就是說,下次調(diào)用 Read 或其他讀取方法時,仍然會從這次 Peek 的位置開始讀。非常適合用于“偷看”一下接下來的內(nèi)容是什么。

func (b *Reader) Peek(n int) ([]byte, error)

f) Read(p []byte) - 實現(xiàn) io.Reader 接口
bufio.Reader 本身也實現(xiàn)了 io.Reader 接口。當你調(diào)用它的 Read 方法時,它會嘗試從自己的緩沖區(qū)中填滿你提供的字節(jié)切片 p。如果緩沖區(qū)空了,它會從底層的 io.Reader 中讀取數(shù)據(jù)來填滿緩沖區(qū),然后再滿足你的請求。

4.3bufio.Writer:帶緩沖的寫入器

bufio.Writer 包裝了一個 io.Writer 接口,將寫入操作先存入內(nèi)存緩沖區(qū),當緩沖區(qū)滿了或被顯式刷新時,才一次性寫入底層的 io.Writer。

創(chuàng)建 bufio.Writer:使用 bufio.NewWriter 函數(shù)創(chuàng)建:

func NewWriter(w io.Writer) *Writer

示例: 創(chuàng)建一個寫入標準輸出的緩沖寫入器。

package main
import (
	"bufio"
	"fmt"
	"os"
)
func main() {
	// os.Stdout 實現(xiàn)了 io.Writer 接口
	writer := bufio.NewWriter(os.Stdout)
	fmt.Printf("創(chuàng)建了一個緩沖區(qū)大小為 %d 字節(jié)的 Writer\n", writer.Size())
}

核心方法
a) Write(p []byte) - 寫入字節(jié)切片
這是最核心的寫入方法。它將數(shù)據(jù)寫入緩沖區(qū)。如果緩沖區(qū)有足夠空間,數(shù)據(jù)就暫存于此;如果空間不足,它會先將緩沖區(qū)的內(nèi)容刷到底層 Writer,然后再寫入新數(shù)據(jù)。
b) WriteString(s string) - 寫入字符串
WriteString 是一個便捷方法,內(nèi)部也是調(diào)用 Write。
c) Flush() - 強制刷新
這是 bufio.Writer 最重要的方法。它會將緩沖區(qū)中所有(無論是否已滿)的數(shù)據(jù)都寫入到底層的 io.Writer 中。

為什么 Flush 如此重要?
因為如果不調(diào)用 Flush(),當程序結(jié)束時,緩沖區(qū)里可能還有未寫入的數(shù)據(jù),這些數(shù)據(jù)就會丟失!

示例: 向文件寫入多行內(nèi)容。

package main
import (
	"bufio"
	"fmt"
	"log"
	"os"
)
func main() {
	// 1. 創(chuàng)建文件
	file, err := os.Create("output.txt")
	if err != nil {
		log.Fatal(err)
	}
	// 確保文件在函數(shù)結(jié)束時關(guān)閉
	defer file.Close()
	// 2. 創(chuàng)建緩沖寫入器
	writer := bufio.NewWriter(file)
	// 3. 寫入數(shù)據(jù)(此時數(shù)據(jù)在內(nèi)存緩沖區(qū)中)
	fmt.Fprintln(writer, "這是第一行。")
	fmt.Fprintln(writer, "這是第二行。")
	writer.WriteString("這是第三行,使用 WriteString。\n")
	// 4. **必須刷新緩沖區(qū),將數(shù)據(jù)寫入文件**
	err = writer.Flush()
	if err != nil {
		log.Fatal("刷新緩沖區(qū)失敗:", err)
	}
	fmt.Println("數(shù)據(jù)已成功寫入 output.txt")
}

在這個例子中,如果注釋掉 writer.Flush(),output.txt 文件將是空的。

4.4bufio.Scanner:更高級的讀取工具

從 Go 1.1 開始,bufio 包引入了 Scanner 類型,它提供了一個更簡單、更健壯的方式來讀取數(shù)據(jù),特別是按“token”(標記)分割數(shù)據(jù)。核心思想:
Scanner 的核心是 SplitFunc 類型的函數(shù),它定義了如何將輸入流分割成一個個標記。默認的分割函數(shù)是 ScanLines,即按行分割。

使用步驟

  1. 創(chuàng)建 Scanner: bufio.NewScanner(r io.Reader)
  2. (可選)設置分割函數(shù): scanner.Split(customSplitFunc)
  3. 循環(huán)掃描: 使用 scanner.Scan() 作為循環(huán)條件,它會嘗試讀取下一個標記。
  4. 獲取標記: 在循環(huán)體內(nèi),使用 scanner.Text() (返回 string) 或 scanner.Bytes() (返回 []byte) 獲取當前標記的內(nèi)容。
  5. 檢查錯誤: 循環(huán)結(jié)束后,使用 scanner.Err() 檢查是否發(fā)生了錯誤。

案例1:逐行讀取文件
使用 Scanner 逐行讀取文件比 Reader.ReadString 更簡潔,且能更好地處理行尾符。

package main
import (
	"bufio"
	"fmt"
	"log"
	"os"
	"strings"
)
func main() {
	// 1. 打開文件
	file, err := os.Open("my_file.txt")
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()
	// 2. 創(chuàng)建 Scanner
	scanner := bufio.NewScanner(file)
	lineCount := 0
	wordCount := 0
	// 3. 循環(huán)掃描
	for scanner.Scan() {
		line := scanner.Text()
		lineCount++
		// 簡單地按空格分割來計算單詞數(shù)
		words := strings.Fields(line)
		wordCount += len(words)
		fmt.Printf("行 %d: %s\n", lineCount, line)
	}
	// 4. 檢查錯誤
	if err := scanner.Err(); err != nil {
		log.Fatal("掃描時出錯:", err)
	}
	fmt.Printf("\n掃描完成。共 %d 行,%d 個單詞。\n", lineCount, wordCount)
}

案例2:自定義分割函數(shù)
Scanner 的強大之處在于可以自定義分割邏輯。例如,我們可以按單詞讀取。
示例: 使用 ScanWords 分割函數(shù)按單詞讀取。

// ... (前面的代碼相同)
scanner := bufio.NewScanner(strings.NewReader("Hello world, this is a test."))
// 設置分割函數(shù)為按單詞分割
scanner.Split(bufio.ScanWords)
for scanner.Scan() {
	fmt.Println(scanner.Text())
}
if err := scanner.Err(); err != nil {
    // ...
}

輸出:

Hello
world,
this
is
a
test.

4.5 使用對比

類型適用場景優(yōu)點注意事項
bufio.Reader需要精細控制讀取過程,如讀取固定字節(jié)數(shù)、預覽數(shù)據(jù)、讀取到特定分隔符。功能強大,控制力強,性能高。API 相對底層,使用時需注意錯誤處理。
bufio.Writer需要頻繁進行小塊寫入,以減少系統(tǒng)調(diào)用,提高性能。顯著提升寫入性能。必須記得調(diào)用 Flush(),否則數(shù)據(jù)可能丟失。
bufio.Scanner需要方便地按行、按單詞等“標記”來處理文本流。API 簡潔易用,代碼可讀性高,錯誤處理方便。功能相對固定,不如 Reader 靈活。不適合讀取二進制流。

Go語言的輸入與輸出格式化功能非常強大,通過 fmt 包和 bufio 包,可以滿足各種輸入輸出需求。掌握這些函數(shù)和格式化動詞,有助于編寫清晰、易讀的 Go 程序。

到此這篇關(guān)于Go基礎(chǔ):輸入與輸出格式化詳解的文章就介紹到這了,更多相關(guān)Go輸入與輸出格式化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語言中內(nèi)建函數(shù)make的使用

    Go語言中內(nèi)建函數(shù)make的使用

    在Go語言編程中,make函數(shù)是一個重要的內(nèi)建函數(shù),它用于創(chuàng)建和初始化切片、映射和通道,握 make 的使用方法,可以幫助我們更高效地管理內(nèi)存和數(shù)據(jù)結(jié)構(gòu)
    2024-09-09
  • Go語言實現(xiàn)新春祝福二維碼的生成

    Go語言實現(xiàn)新春祝福二維碼的生成

    二維碼現(xiàn)在是隨處度可以看到,買東西,支付,添加好友只要你掃一掃就能完成整個工作,簡單且方便。所以利用這個新春佳節(jié)做一個帶著新春祝福的二維碼吧
    2023-02-02
  • go各種import的使用方法講解

    go各種import的使用方法講解

    今天小編就為大家分享一篇關(guān)于go各種import的使用方法講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-04-04
  • Go 語言中的指針的使用

    Go 語言中的指針的使用

    在Go語言中,指針是存儲另一變量內(nèi)存地址的變量,通過&操作符獲取變量地址,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-09-09
  • golang敏感詞過濾的實現(xiàn)

    golang敏感詞過濾的實現(xiàn)

    本文主要介紹了golang敏感詞過濾的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-01-01
  • Go語言中Struct與繼承與匿名字段和內(nèi)嵌結(jié)構(gòu)體全面詳解

    Go語言中Struct與繼承與匿名字段和內(nèi)嵌結(jié)構(gòu)體全面詳解

    這篇文章主要介紹了Go語言中Struct與繼承與匿名字段和內(nèi)嵌結(jié)構(gòu)體,Go語言中通過結(jié)構(gòu)體的內(nèi)嵌再配合接口比面向?qū)ο缶哂懈叩臄U展性和靈活性,感興趣的可以了解一下
    2023-04-04
  • Go語言正則表達式示例

    Go語言正則表達式示例

    這篇文章主要介紹了Go語言正則表達式,結(jié)合實例形式分析了Go語言正則表達式實現(xiàn)字符串的匹配、查找等相關(guān)操作技巧,需要的朋友可以參考下
    2017-01-01
  • Golang內(nèi)存管理之內(nèi)存分配器詳解

    Golang內(nèi)存管理之內(nèi)存分配器詳解

    Go內(nèi)存分配器的設計思想來源于TCMalloc,全稱是Thread-Caching?Malloc,核心思想是把內(nèi)存分為多級管理,下面就來和大家深入聊聊Go語言內(nèi)存分配器的使用吧
    2023-06-06
  • Go操作Kafka的實現(xiàn)示例(kafka-go)

    Go操作Kafka的實現(xiàn)示例(kafka-go)

    本文介紹了使用kafka-go庫在Go語言中與Kafka進行交互,涵蓋了kafka-go的安裝、API使用、消息發(fā)送與消費方法,以及如何通過DockerCompose快速搭建Kafka環(huán)境,文章還比較了其他兩個常用的Kafka客戶端庫,感興趣的可以了解一下
    2024-10-10
  • Go 語言中靜態(tài)類型和動態(tài)類型的使用

    Go 語言中靜態(tài)類型和動態(tài)類型的使用

    本文主要介紹了Go語言中的靜態(tài)類型和動態(tài)類型,靜態(tài)類型在編譯時確定,提供了類型安全,性能優(yōu)化和代碼清晰,而動態(tài)類型在運行時確定,提供了更高的靈活性,但可能引發(fā)運行時錯誤,下面就來介紹一下,感興趣的可以了解一下
    2024-10-10

最新評論