溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

go語言eof錯誤指的是什么

發(fā)布時間:2023-02-07 10:24:15 來源:億速云 閱讀:330 作者:iii 欄目:編程語言

這篇文章主要介紹了go語言eof錯誤指的是什么的相關(guān)知識,內(nèi)容詳細(xì)易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇go語言eof錯誤指的是什么文章都會有所收獲,下面我們一起來看看吧。

在go語言中,eof是指文件結(jié)尾錯誤,是Go語言中最重要的錯誤變量,存在于io包中,用于表示輸入流的結(jié)尾。因?yàn)槊總€文件都有一個結(jié)尾,所以“io.EOF”很多時候并不能算是一個錯誤,它更重要的是表示一個輸入流結(jié)束了。

golang 文件結(jié)尾錯誤(EOF)

函數(shù)經(jīng)常會返回多種錯誤,這對終端用戶來說可能會很有趣,但對程序而言,這使得情況變得復(fù)雜。很多時候,程序必須根據(jù)錯誤類型,作出不同的響應(yīng)。讓我們考慮這樣一個例子:

從文件中讀取n個字節(jié)。如果n等于文件的長度,讀取過程的任何錯誤都表示失敗。如果n小于文件的長度,調(diào)用者會重復(fù)的讀取固定大小的數(shù)據(jù)直到文件結(jié)束。這會導(dǎo)致調(diào)用者必須分別處理由文件結(jié)束引起的各種錯誤。

基于這樣的原因,io包保證任何由文件結(jié)束引起的讀取失敗都返回同一個錯誤——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")

認(rèn)識io.EOF

io.EOF是io包中的變量, 表示文件結(jié)束的錯誤:

package io23var EOF = errors.New("EOF")

也通過以下命令查看詳細(xì)文檔:

$ 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語言中最重要的錯誤變量了, 它用于表示輸入流的結(jié)尾. 因?yàn)槊總€文件都有一個結(jié)尾, 所以io.EOF很多時候并不能算是一個錯誤, 它更重要的是表示一個輸入流結(jié)束了。

io.EOF設(shè)計(jì)的缺陷

可惜標(biāo)準(zhǔn)庫中的io.EOF的設(shè)計(jì)是有問題的. 首先EOF是End-Of-File的縮寫, 根據(jù)Go語言的習(xí)慣大寫字母縮寫一般表示常量. 可惜io.EOF被錯誤地定義成了變量, 這導(dǎo)致了API權(quán)限的擴(kuò)散. 而最小化API權(quán)限是任何一個模塊或函數(shù)設(shè)計(jì)的最高要求. 通過最小化的權(quán)限, 可以盡早發(fā)現(xiàn)代碼中不必要的錯誤.

比如Go語言一個重要的安全設(shè)計(jì)就是禁止隱式的類型轉(zhuǎn)換. 因此這個設(shè)計(jì)我們就可以很容易發(fā)現(xiàn)程序的BUG. 此外Go語言禁止定義沒有被使用到的局部變量(函數(shù)參數(shù)除外, 因此函數(shù)參數(shù)是函數(shù)接口的一個部分)和禁止導(dǎo)入沒有用到的包都是最小化權(quán)限的最佳實(shí)踐. 這些最小API權(quán)限的設(shè)計(jì)不僅僅改進(jìn)了程序的質(zhì)量, 也提高了編譯工具的性能和輸出的目標(biāo)文件.

因?yàn)镋OF被定義成一個變量, 這導(dǎo)致了該變量可能會被惡意改變. 下面的代碼就是一種優(yōu)雅的埋坑方式:

func init() {2    io.EOF = nil3}

這雖然是一個段子, 但是卻真實(shí)地暴漏了EOF接口的設(shè)計(jì)缺陷: 它存在嚴(yán)重的安全隱患. 變量的類型似乎也在暗示用戶可以放心地修改變量的值. 因此說EOF是一個不安全也不優(yōu)雅的設(shè)計(jì).

io.EOF改為常量

一個顯然的改進(jìn)思路是將io.EOF定義為常量. 但是因?yàn)镋OF對應(yīng)一個表示error接口類型, 而Go語言目前的常量語法并不支持定義常量類型的接口. 但是我們可以通過一些技巧繞過這個限制.

Go語言的常量有bool/int/float/string/nil這幾種主要類型. 常量不僅僅不包含接口等復(fù)雜類型, 甚至連常量的數(shù)組或結(jié)構(gòu)體都不支持! 不過常量有一個重要的擴(kuò)展規(guī)則: 以bool/int/float/string/nil為基礎(chǔ)類型定義的新類型也支持常量.

比如, 我們重新定義一個字符串類型, 它也可以支持常量的:

type MyString string2const name MyString = "chai2010"

這個例子中MyString是一個新定義的類型, 可以定義這種類型的常量, 因?yàn)樗牡讓拥膕tring類型是支持常量的.

那么io.EOF的底層類型是什么呢? EOF是通過errors.New("EOF")定義的, 下面是這個函數(shù)的實(shí)現(xiàn):

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結(jié)構(gòu)體. 而結(jié)構(gòu)體類型是不支持定義常量的. 不過errors.errorString結(jié)構(gòu)體中只有一個字符串類型, io.EOF對應(yīng)的錯誤字符串正是"EOF".

我們可以為EOF重新實(shí)現(xiàn)一個以字符串為底層類型的新錯誤類型:

package io

type errorString string

func (e errorString) Error() string {
    return string(e)
}

這個新的io.errorString實(shí)現(xiàn)了兩個特性: 首先是滿足了error接口; 其次它是基于string類型重新定義, 因此支持定義常量. 因此我們可以基于errorString重新將io.EOF定義為常量:

const EOF = errorString("EOF")

這樣EOF就變成了編譯時可以確定的常量類型, 常量的值依然是“EOF”字符串. 但是也帶來了新的問題: EOF已經(jīng)不再是一個接口類型, 它會破壞舊代碼的兼容性嗎?

關(guān)于“go語言eof錯誤指的是什么”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對“go語言eof錯誤指的是什么”知識都有一定的了解,大家如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI