首頁 後端開發 Golang go語言eof錯誤是什麼

go語言eof錯誤是什麼

Feb 06, 2023 pm 02:10 PM
go語言 eof錯誤

在go語言中,eof是指檔案結尾錯誤,是Go語言中最重要的錯誤變量,存在於io套件中,用來表示輸入流的結尾。因為每個檔案都有一個結尾,所以「io.EOF」很多時候並不能算是一個錯誤,它更重要的是表示一個輸入流結束了。

go語言eof錯誤是什麼

本教學操作環境:windows7系統、GO 1.18版本、Dell G3電腦。

golang 檔案結尾錯誤(EOF)

函數經常會傳回多種錯誤,這對終端使用者來說可能會很有趣,但對程序而言,這使得情況變得複雜。很多時候,程式必須根據錯誤類型,做出不同的回應。讓我們考慮這樣一個例子:

從檔案讀取n個位元組。如果n等於檔案的長度,讀取過程的任何錯誤都表示失敗。如果n小於檔案的長度,呼叫者會重複的讀取固定大小的資料直到檔案結束。這會導致呼叫者必須分別處理由檔案結束引起的各種錯誤。

基於這樣的原因,io套件保證任何由檔案結束引起的讀取失敗都會回傳同一個錯誤-io.EOF,該錯誤在io套件中定義:

package io
import "errors"
// EOF is the error returned by Read when no more input is available.
var EOF = errors.New("EOF")
登入後複製

認識io.EOF

io.EOF是io套件中的變數, 表示檔案結束的錯誤:

package io23var EOF = errors.New("EOF")
登入後複製

#也透過以下指令查看詳細文件:

$ go doc io.EOF
var EOF = errors.New("EOF")
EOF is the error returned by Read when no more input is available. Functions
should return EOF only to signal a graceful end of input. If the EOF occurs
unexpectedly in a structured data stream, the appropriate error is either
ErrUnexpectedEOF or some other error giving more detail.
$
登入後複製

io.EOF大約可以算是Go語言中最重要的錯誤變數了, 它用來表示輸入流的結尾. 因為每個檔案都有一個結尾, 所以io.EOF很多時候並不能算是一個錯誤, 它更重要的是表示一個輸入流結束了。

io.EOF設計的缺陷

#可惜標準庫中的io.EOF的設計是有問題的. 首先EOF是End- Of-File的縮寫, 根據Go語言的習慣大寫字母縮寫一般表示常數. 可惜io.EOF被錯誤地定義成了變數, 這導致了API權限的擴散. 而最小化API權限是任何一個模組或函數設計的最高要求. 透過最小化的權限, 可以儘早發現程式碼中不必要的錯誤.

例如Go語言一個重要的安全設計就是禁止隱式的類型轉換. 因此這個設計我們就可以很容易發現程式的BUG. 另外Go語言禁止定義沒有被使用到的局部變數(函數參數除外, 因此函數參數是函數介面的一個部分)和禁止導入沒有用到的包都是最小化權限的最佳實務.這些最小API權限的設計不僅改進了程式的品質, 也提高了編譯工具的性能和輸出的目標檔案.

因為EOF被定義成一個變數, 這導致了該變數可能會被惡意改變. 下面的程式碼就是一種優雅的埋坑方式:

func init() {2    io.EOF = nil3}
登入後複製

這雖然是一個段子, 但是卻真實地暴漏了EOF接口的設計缺陷: 它存在嚴重的安全隱患. 變量的類型似乎也在暗示使用者可以放心地修改變數的值. 因此說EOF是一個不安全也不優雅的設計.

io.EOF改為常數

一個顯然的改進思路是將io.EOF定義為常數. 但是因為EOF對應一個表示error接口類型, 而Go語言目前的常量語法並不支持定義常量類型的接口. 但是我們可以通過一些技巧繞過這個限制.

Go語言的常數有bool/int/float/string/nil這幾種主要類型. 常數不僅僅不包含接口等複雜類型, 甚至連常量的數組或結構體都不支援! 不過常數有一個重要的擴充規則: 以bool/int/float/string/nil為基礎型別定義的新型別也支援常數.

例如, 我們重新定義一個字串型別, 它也可以支援常數的:

type MyString string2const name MyString = "chai2010"
登入後複製

這個例子中MyString是一個新定義的類型, 可以定義這種類型的常數, 因為它的底層的string類型是支援常數的.

那麼io.EOF的底層型別是什麼呢? EOF是透過errors.New("EOF")定義的, 下面是這個函數的實現:

package errors 
// New returns an error that formats as the given text. 
func New(text string) error {
    return &errorString{text} 
} 

// errorString is a trivial implementation of error. 
type errorString struct {
    s string
}

func (e *errorString) Error() string {
    return e.s
}
登入後複製

因此io.EOF底層的型別是errors .errorString結構體. 而結構體類型是不支援定義常數的. 不過errors.errorString結構體中只有一個字串型別, io.EOF對應的錯誤字串正是"EOF".

我們可以為EOF重新實作一個以字串為底層類型的新錯誤類型:

package io

type errorString string

func (e errorString) Error() string {
    return string(e)
}
登入後複製

這個新的io.errorString實作了兩個特性: 首先是滿足了error介面; 其次它是基於string類型重新定義, 因此支援定義常數. 因此我們可以基於errorString重新將io.EOF定義為常數:

const EOF = errorString("EOF")
登入後複製

這樣EOF就變成了編譯時可以確定的常數類型, 常數的值依然是“EOF”字串. 但是也帶來了新的問題: EOF已經不再是一個介面類型, 它會破壞舊程式碼的兼容性嗎?

【相關推薦:Go影片教學程式設計教學

以上是go語言eof錯誤是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Go語言中用於浮點數運算的庫有哪些? Go語言中用於浮點數運算的庫有哪些? Apr 02, 2025 pm 02:06 PM

Go語言中用於浮點數運算的庫介紹在Go語言(也稱為Golang)中,進行浮點數的加減乘除運算時,如何確保精度是�...

Go的爬蟲Colly中Queue線程的問題是什麼? Go的爬蟲Colly中Queue線程的問題是什麼? Apr 02, 2025 pm 02:09 PM

Go爬蟲Colly中的Queue線程問題探討在使用Go語言的Colly爬蟲庫時,開發者常常會遇到關於線程和請求隊列的問題。 �...

GoLand中自定義結構體標籤不顯示怎麼辦? GoLand中自定義結構體標籤不顯示怎麼辦? Apr 02, 2025 pm 05:09 PM

GoLand中自定義結構體標籤不顯示怎麼辦?在使用GoLand進行Go語言開發時,很多開發者會遇到自定義結構體標籤在�...

在 Go 語言中,為什麼使用 Println 和 string() 函數打印字符串會出現不同的效果? 在 Go 語言中,為什麼使用 Println 和 string() 函數打印字符串會出現不同的效果? Apr 02, 2025 pm 02:03 PM

Go語言中字符串打印的區別:使用Println與string()函數的效果差異在Go...

在Go語言中使用Redis Stream實現消息隊列時,如何解決user_id類型轉換問題? 在Go語言中使用Redis Stream實現消息隊列時,如何解決user_id類型轉換問題? Apr 02, 2025 pm 04:54 PM

Go語言中使用RedisStream實現消息隊列時類型轉換問題在使用Go語言與Redis...

Go語言中`var`和`type`關鍵字定義結構體的區別是什麼? Go語言中`var`和`type`關鍵字定義結構體的區別是什麼? Apr 02, 2025 pm 12:57 PM

Go語言中結構體定義的兩種方式:var與type關鍵字的差異Go語言在定義結構體時,經常會看到兩種不同的寫法:一�...

Go語言中哪些庫是由大公司開發或知名的開源項目提供的? Go語言中哪些庫是由大公司開發或知名的開源項目提供的? Apr 02, 2025 pm 04:12 PM

Go語言中哪些庫是大公司開發或知名開源項目?在使用Go語言進行編程時,開發者常常會遇到一些常見的需求,�...

在Go編程中,如何正確管理Mysql和Redis的連接與釋放資源? 在Go編程中,如何正確管理Mysql和Redis的連接與釋放資源? Apr 02, 2025 pm 05:03 PM

Go編程中的資源管理:Mysql和Redis的連接與釋放在學習Go編程過程中,如何正確管理資源,特別是與數據庫和緩存�...

See all articles