mirror of
https://github.com/gopl-zh/gopl-zh.github.com.git
synced 2025-08-10 17:12:18 +00:00
回到简体
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
### 7.5.1. 警告:一個包含nil指針的接口不是nil接口
|
||||
### 7.5.1. 警告:一个包含nil指针的接口不是nil接口
|
||||
|
||||
一個不包含任何值的nil接口值和一個剛好包含nil指針的接口值是不同的。這個細微區别産生了一個容易絆倒每個Go程序員的陷阱。
|
||||
一个不包含任何值的nil接口值和一个刚好包含nil指针的接口值是不同的。这个细微区别产生了一个容易绊倒每个Go程序员的陷阱。
|
||||
|
||||
思考下面的程序。當debug變量設置爲true時,main函數會將f函數的輸出收集到一個bytes.Buffer類型中。
|
||||
思考下面的程序。当debug变量设置为true时,main函数会将f函数的输出收集到一个bytes.Buffer类型中。
|
||||
|
||||
```go
|
||||
const debug = true
|
||||
@@ -27,7 +27,7 @@ func f(out io.Writer) {
|
||||
}
|
||||
```
|
||||
|
||||
我們可能會預計當把變量debug設置爲false時可以禁止對輸出的收集,但是實際上在out.Write方法調用時程序發生了panic:
|
||||
我们可能会预计当把变量debug设置为false时可以禁止对输出的收集,但是实际上在out.Write方法调用时程序发生了panic:
|
||||
|
||||
```go
|
||||
if out != nil {
|
||||
@@ -35,13 +35,13 @@ if out != nil {
|
||||
}
|
||||
```
|
||||
|
||||
當main函數調用函數f時,它給f函數的out參數賦了一個\*bytes.Buffer的空指針,所以out的動態值是nil。然而,它的動態類型是\*bytes.Buffer,意思就是out變量是一個包含空指針值的非空接口(如圖7.5),所以防禦性檢査out!=nil的結果依然是true。
|
||||
当main函数调用函数f时,它给f函数的out参数赋了一个\*bytes.Buffer的空指针,所以out的动态值是nil。然而,它的动态类型是\*bytes.Buffer,意思就是out变量是一个包含空指针值的非空接口(如图7.5),所以防御性检查out!=nil的结果依然是true。
|
||||
|
||||

|
||||
|
||||
動態分配機製依然決定(\*bytes.Buffer).Write的方法會被調用,但是這次的接收者的值是nil。對於一些如\*os.File的類型,nil是一個有效的接收者(§6.2.1),但是\*bytes.Buffer類型不在這些類型中。這個方法會被調用,但是當它嚐試去獲取緩衝區時會發生panic。
|
||||
动态分配机制依然决定(\*bytes.Buffer).Write的方法会被调用,但是这次的接收者的值是nil。对于一些如\*os.File的类型,nil是一个有效的接收者(§6.2.1),但是\*bytes.Buffer类型不在这些类型中。这个方法会被调用,但是当它尝试去获取缓冲区时会发生panic。
|
||||
|
||||
問題在於盡管一個nil的\*bytes.Buffer指針有實現這個接口的方法,它也不滿足這個接口具體的行爲上的要求。特别是這個調用違反了(\*bytes.Buffer).Write方法的接收者非空的隱含先覺條件,所以將nil指針賦給這個接口是錯誤的。解決方案就是將main函數中的變量buf的類型改爲io.Writer,因此可以避免一開始就將一個不完全的值賦值給這個接口:
|
||||
问题在于尽管一个nil的\*bytes.Buffer指针有实现这个接口的方法,它也不满足这个接口具体的行为上的要求。特别是这个调用违反了(\*bytes.Buffer).Write方法的接收者非空的隐含先觉条件,所以将nil指针赋给这个接口是错误的。解决方案就是将main函数中的变量buf的类型改为io.Writer,因此可以避免一开始就将一个不完全的值赋值给这个接口:
|
||||
|
||||
```go
|
||||
var buf io.Writer
|
||||
@@ -51,4 +51,4 @@ if debug {
|
||||
f(buf) // OK
|
||||
```
|
||||
|
||||
現在我們已經把接口值的技巧都講完了,讓我們來看更多的一些在Go標準庫中的重要接口類型。在下面的三章中,我們會看到接口類型是怎樣用在排序,web服務,錯誤處理中的。
|
||||
现在我们已经把接口值的技巧都讲完了,让我们来看更多的一些在Go标准库中的重要接口类型。在下面的三章中,我们会看到接口类型是怎样用在排序,web服务,错误处理中的。
|
||||
|
Reference in New Issue
Block a user