ch12-1: review

This commit is contained in:
chai2010 2016-01-21 22:52:31 +08:00
parent 3f094d9f0e
commit fbe8231327

View File

@ -1,10 +1,10 @@
## 12.1. 爲何需要反射? ## 12.1. 爲何需要反射?
有時候我們需要編寫一個函數能夠處理一類併不滿足普通公共接口的類型的值, 也可能它們併沒有確定的表示方式, 或者在我們設計該函數的時候還這些類型可能還不存在, 各種情況都有可能. 有時候我們需要編寫一個函數能夠處理一類併不滿足普通公共接口的類型的值,也可能是因为它們併沒有確定的表示方式,或者是在我們設計該函數的時候還這些類型可能還不存在,各種情況都有可能。
一個大家熟悉的例子是 fmt.Fprintf 函數提供的字符串格式化處理邏輯, 它可以用例對任意類型的值格式化打印, 甚至是用戶自定義的類型. 讓我們來嚐試實現一個類似功能的函數. 簡單起見, 我們的函數隻接收一個參數, 然後返迴和 fmt.Sprint 類似的格式化後的字符串, 我們的函數名也叫 Sprint. 一個大家熟悉的例子是fmt.Fprintf函數提供的字符串格式化處理邏輯它可以用例對任意類型的值格式化并打印甚至支持用戶自定義的類型。讓我們也來嚐試實現一個類似功能的函數。为了簡單起見我們的函數隻接收一個參數然後返迴和fmt.Sprint類似的格式化後的字符串。我們实现的函數名也叫Sprint。
我們使用了 switch 分支首先來測試輸入參數是否實現了 String 方法, 如果是的話就使用該方法. 然後繼續增加測試分支, 檢査是否是每個基於 string, int, bool 等基礎類型的動態類型, 併在每種情況下執行適當的格式化操作. 我們使用了switch类型分支首先來測試輸入參數是否實現了String方法如果是的話就使用該方法。然後繼續增加类型測試分支檢査是否是每個基於string、int、bool等基礎類型的動態類型併在每種情況下執行相应的格式化操作。
```Go ```Go
func Sprint(x interface{}) string { func Sprint(x interface{}) string {
@ -31,6 +31,6 @@ func Sprint(x interface{}) string {
} }
``` ```
但是我們如何處理其它類似 []float64, map[string][]string 等類型呢? 我們當然可以添加更多的測試分支, 但是這些組合類型的數目基本是無窮的. 還有如何處理 url.Values 等命令的類型呢? 雖然類型分支可以識别出底層的基礎類型是 map[string][]string, 但是它併不匹配 url.Values 類型, 因爲這是兩種不同的類型, 而且 switch 分支也不可能包含每個類似 url.Values 的類型, 這會導致對這些庫的依賴. 但是我們如何處理其它類似[]float64、map[string][]string等類型呢我們當然可以添加更多的測試分支但是這些組合類型的數目基本是無窮的。還有如何處理url.Values等命名的類型呢雖然類型分支可以識别出底層的基礎類型是map[string][]string但是它併不匹配url.Values類型因爲它们是兩種不同的類型而且switch类型分支也不可能包含每個類似url.Values的類型這會導致對這些庫的循环依賴。
沒有一種方法來檢査未知類型的表示方式, 我們被卡住了. 這就是我們爲何需要反射的原因. 沒有一種方法來檢査未知類型的表示方式,我們被卡住了。這就是我們爲何需要反射的原因。