mirror of
https://github.com/gopl-zh/gopl-zh.github.com.git
synced 2026-01-16 20:27:15 +08:00
回到简体
This commit is contained in:
@@ -1,20 +1,20 @@
|
||||
## 12.9. 幾點忠告
|
||||
## 12.9. 几点忠告
|
||||
|
||||
雖然反射提供的API遠多於我們講到的,我們前面的例子主要是給出了一個方向,通過反射可以實現哪些功能。反射是一個強大併富有表達力的工具,但是它應該被小心地使用,原因有三。
|
||||
虽然反射提供的API远多于我们讲到的,我们前面的例子主要是给出了一个方向,通过反射可以实现哪些功能。反射是一个强大并富有表达力的工具,但是它应该被小心地使用,原因有三。
|
||||
|
||||
第一個原因是,基於反射的代碼是比較脆弱的。對於每一個會導致編譯器報告類型錯誤的問題,在反射中都有與之相對應的問題,不同的是編譯器會在構建時馬上報告錯誤,而反射則是在眞正運行到的時候才會拋出panic異常,可能是寫完代碼很久之後的時候了,而且程序也可能運行了很長的時間。
|
||||
第一个原因是,基于反射的代码是比较脆弱的。对于每一个会导致编译器报告类型错误的问题,在反射中都有与之相对应的问题,不同的是编译器会在构建时马上报告错误,而反射则是在真正运行到的时候才会抛出panic异常,可能是写完代码很久之后的时候了,而且程序也可能运行了很长的时间。
|
||||
|
||||
以前面的readList函數(§12.6)爲例,爲了從輸入讀取字符串併填充int類型的變量而調用的reflect.Value.SetString方法可能導致panic異常。絶大多數使用反射的程序都有類似的風險,需要非常小心地檢査每個reflect.Value的對於值的類型、是否可取地址,還有是否可以被脩改等。
|
||||
以前面的readList函数(§12.6)为例,为了从输入读取字符串并填充int类型的变量而调用的reflect.Value.SetString方法可能导致panic异常。绝大多数使用反射的程序都有类似的风险,需要非常小心地检查每个reflect.Value的对于值的类型、是否可取地址,还有是否可以被修改等。
|
||||
|
||||
避免這種因反射而導致的脆弱性的問題的最好方法是將所有的反射相關的使用控製在包的內部,如果可能的話避免在包的API中直接暴露reflect.Value類型,這樣可以限製一些非法輸入。如果無法做到這一點,在每個有風險的操作前指向額外的類型檢査。以標準庫中的代碼爲例,當fmt.Printf收到一個非法的操作數是,它併不會拋出panic異常,而是打印相關的錯誤信息。程序雖然還有BUG,但是會更加容易診斷。
|
||||
避免这种因反射而导致的脆弱性的问题的最好方法是将所有的反射相关的使用控制在包的内部,如果可能的话避免在包的API中直接暴露reflect.Value类型,这样可以限制一些非法输入。如果无法做到这一点,在每个有风险的操作前指向额外的类型检查。以标准库中的代码为例,当fmt.Printf收到一个非法的操作数是,它并不会抛出panic异常,而是打印相关的错误信息。程序虽然还有BUG,但是会更加容易诊断。
|
||||
|
||||
```Go
|
||||
fmt.Printf("%d %s\n", "hello", 42) // "%!d(string=hello) %!s(int=42)"
|
||||
```
|
||||
|
||||
反射同樣降低了程序的安全性,還影響了自動化重構和分析工具的準確性,因爲它們無法識别運行時才能確認的類型信息。
|
||||
反射同样降低了程序的安全性,还影响了自动化重构和分析工具的准确性,因为它们无法识别运行时才能确认的类型信息。
|
||||
|
||||
避免使用反射的第二個原因是,卽使對應類型提供了相同文檔,但是反射的操作不能做靜態類型檢査,而且大量反射的代碼通常難以理解。總是需要小心翼翼地爲每個導出的類型和其它接受interface{}或reflect.Value類型參數的函數維護説明文檔。
|
||||
避免使用反射的第二个原因是,即使对应类型提供了相同文档,但是反射的操作不能做静态类型检查,而且大量反射的代码通常难以理解。总是需要小心翼翼地为每个导出的类型和其它接受interface{}或reflect.Value类型参数的函数维护说明文档。
|
||||
|
||||
第三個原因,基於反射的代碼通常比正常的代碼運行速度慢一到兩個數量級。對於一個典型的項目,大部分函數的性能和程序的整體性能關繫不大,所以使用反射可能會使程序更加清晰。測試是一個特别適合使用反射的場景,因爲每個測試的數據集都很小。但是對於性能關鍵路徑的函數,最好避免使用反射。
|
||||
第三个原因,基于反射的代码通常比正常的代码运行速度慢一到两个数量级。对于一个典型的项目,大部分函数的性能和程序的整体性能关系不大,所以使用反射可能会使程序更加清晰。测试是一个特别适合使用反射的场景,因为每个测试的数据集都很小。但是对于性能关键路径的函数,最好避免使用反射。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user