mirror of
https://github.com/gopl-zh/gopl-zh.github.com.git
synced 2025-08-14 02:22:50 +00:00
回到简体
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
## 7.10. 類型斷言
|
||||
## 7.10. 类型断言
|
||||
|
||||
類型斷言是一個使用在接口值上的操作。語法上它看起來像x.(T)被稱爲斷言類型,這里x表示一個接口的類型和T表示一個類型。一個類型斷言檢査它操作對象的動態類型是否和斷言的類型匹配。
|
||||
类型断言是一个使用在接口值上的操作。语法上它看起来像x.(T)被称为断言类型,这里x表示一个接口的类型和T表示一个类型。一个类型断言检查它操作对象的动态类型是否和断言的类型匹配。
|
||||
|
||||
這里有兩種可能。第一種,如果斷言的類型T是一個具體類型,然後類型斷言檢査x的動態類型是否和T相同。如果這個檢査成功了,類型斷言的結果是x的動態值,當然它的類型是T。換句話説,具體類型的類型斷言從它的操作對象中獲得具體的值。如果檢査失敗,接下來這個操作會拋出panic。例如:
|
||||
这里有两种可能。第一种,如果断言的类型T是一个具体类型,然后类型断言检查x的动态类型是否和T相同。如果这个检查成功了,类型断言的结果是x的动态值,当然它的类型是T。换句话说,具体类型的类型断言从它的操作对象中获得具体的值。如果检查失败,接下来这个操作会抛出panic。例如:
|
||||
|
||||
```go
|
||||
var w io.Writer
|
||||
@@ -11,9 +11,9 @@ f := w.(*os.File) // success: f == os.Stdout
|
||||
c := w.(*bytes.Buffer) // panic: interface holds *os.File, not *bytes.Buffer
|
||||
```
|
||||
|
||||
第二種,如果相反斷言的類型T是一個接口類型,然後類型斷言檢査是否x的動態類型滿足T。如果這個檢査成功了,動態值沒有獲取到;這個結果仍然是一個有相同類型和值部分的接口值,但是結果有類型T。換句話説,對一個接口類型的類型斷言改變了類型的表述方式,改變了可以獲取的方法集合(通常更大),但是它保護了接口值內部的動態類型和值的部分。
|
||||
第二种,如果相反断言的类型T是一个接口类型,然后类型断言检查是否x的动态类型满足T。如果这个检查成功了,动态值没有获取到;这个结果仍然是一个有相同类型和值部分的接口值,但是结果有类型T。换句话说,对一个接口类型的类型断言改变了类型的表述方式,改变了可以获取的方法集合(通常更大),但是它保护了接口值内部的动态类型和值的部分。
|
||||
|
||||
在下面的第一個類型斷言後,w和rw都持有os.Stdout因此它們每個有一個動態類型*os.File,但是變量w是一個io.Writer類型隻對外公開出文件的Write方法,然而rw變量也隻公開它的Read方法。
|
||||
在下面的第一个类型断言后,w和rw都持有os.Stdout因此它们每个有一个动态类型*os.File,但是变量w是一个io.Writer类型只对外公开出文件的Write方法,然而rw变量也只公开它的Read方法。
|
||||
|
||||
```go
|
||||
var w io.Writer
|
||||
@@ -23,14 +23,14 @@ w = new(ByteCounter)
|
||||
rw = w.(io.ReadWriter) // panic: *ByteCounter has no Read method
|
||||
```
|
||||
|
||||
如果斷言操作的對象是一個nil接口值,那麽不論被斷言的類型是什麽這個類型斷言都會失敗。我們幾乎不需要對一個更少限製性的接口類型(更少的方法集合)做斷言,因爲它表現的就像賦值操作一樣,除了對於nil接口值的情況。
|
||||
如果断言操作的对象是一个nil接口值,那么不论被断言的类型是什么这个类型断言都会失败。我们几乎不需要对一个更少限制性的接口类型(更少的方法集合)做断言,因为它表现的就像赋值操作一样,除了对于nil接口值的情况。
|
||||
|
||||
```go
|
||||
w = rw // io.ReadWriter is assignable to io.Writer
|
||||
w = rw.(io.Writer) // fails only if rw == nil
|
||||
```
|
||||
|
||||
經常地我們對一個接口值的動態類型是不確定的,併且我們更願意去檢驗它是否是一些特定的類型。如果類型斷言出現在一個預期有兩個結果的賦值操作中,例如如下的定義,這個操作不會在失敗的時候發生panic但是代替地返迴一個額外的第二個結果,這個結果是一個標識成功的布爾值:
|
||||
经常地我们对一个接口值的动态类型是不确定的,并且我们更愿意去检验它是否是一些特定的类型。如果类型断言出现在一个预期有两个结果的赋值操作中,例如如下的定义,这个操作不会在失败的时候发生panic但是代替地返回一个额外的第二个结果,这个结果是一个标识成功的布尔值:
|
||||
|
||||
```go
|
||||
var w io.Writer = os.Stdout
|
||||
@@ -38,9 +38,9 @@ f, ok := w.(*os.File) // success: ok, f == os.Stdout
|
||||
b, ok := w.(*bytes.Buffer) // failure: !ok, b == nil
|
||||
```
|
||||
|
||||
第二個結果常規地賦值給一個命名爲ok的變量。如果這個操作失敗了,那麽ok就是false值,第一個結果等於被斷言類型的零值,在這個例子中就是一個nil的*bytes.Buffer類型。
|
||||
第二个结果常规地赋值给一个命名为ok的变量。如果这个操作失败了,那么ok就是false值,第一个结果等于被断言类型的零值,在这个例子中就是一个nil的*bytes.Buffer类型。
|
||||
|
||||
這個ok結果經常立卽用於決定程序下面做什麽。if語句的擴展格式讓這個變的很簡潔:
|
||||
这个ok结果经常立即用于决定程序下面做什么。if语句的扩展格式让这个变的很简洁:
|
||||
|
||||
```go
|
||||
if f, ok := w.(*os.File); ok {
|
||||
@@ -48,7 +48,7 @@ if f, ok := w.(*os.File); ok {
|
||||
}
|
||||
```
|
||||
|
||||
當類型斷言的操作對象是一個變量,你有時會看見原來的變量名重用而不是聲明一個新的本地變量,這個重用的變量會覆蓋原來的值,如下面這樣:
|
||||
当类型断言的操作对象是一个变量,你有时会看见原来的变量名重用而不是声明一个新的本地变量,这个重用的变量会覆盖原来的值,如下面这样:
|
||||
|
||||
```go
|
||||
if w, ok := w.(*os.File); ok {
|
||||
|
Reference in New Issue
Block a user