Go 語言 為何需要反射?

2023-03-14 16:59 更新

原文鏈接:https://gopl-zh.github.io/ch12/ch12-01.html


12.1. 為何需要反射?

有時(shí)候我們需要編寫一個(gè)函數(shù)能夠處理一類并不滿足普通公共接口的類型的值,也可能是因?yàn)樗鼈儾]有確定的表示方式,或者是在我們設(shè)計(jì)該函數(shù)的時(shí)候這些類型可能還不存在。

一個(gè)大家熟悉的例子是fmt.Fprintf函數(shù)提供的字符串格式化處理邏輯,它可以用來對任意類型的值格式化并打印,甚至支持用戶自定義的類型。讓我們也來嘗試實(shí)現(xiàn)一個(gè)類似功能的函數(shù)。為了簡單起見,我們的函數(shù)只接收一個(gè)參數(shù),然后返回和fmt.Sprint類似的格式化后的字符串。我們實(shí)現(xiàn)的函數(shù)名也叫Sprint。

我們首先用switch類型分支來測試輸入?yún)?shù)是否實(shí)現(xiàn)了String方法,如果是的話就調(diào)用該方法。然后繼續(xù)增加類型測試分支,檢查這個(gè)值的動(dòng)態(tài)類型是否是string、int、bool等基礎(chǔ)類型,并在每種情況下執(zhí)行相應(yīng)的格式化操作。

func Sprint(x interface{}) string {
    type stringer interface {
        String() string
    }
    switch x := x.(type) {
    case stringer:
        return x.String()
    case string:
        return x
    case int:
        return strconv.Itoa(x)
    // ...similar cases for int16, uint32, and so on...
    case bool:
        if x {
            return "true"
        }
        return "false"
    default:
        // array, chan, func, map, pointer, slice, struct
        return "???"
    }
}

但是我們?nèi)绾翁幚砥渌愃芠]float64、map[string][]string等類型呢?我們當(dāng)然可以添加更多的測試分支,但是這些組合類型的數(shù)目基本是無窮的。還有如何處理類似url.Values這樣的具名類型呢?即使類型分支可以識別出底層的基礎(chǔ)類型是map[string][]string,但是它并不匹配url.Values類型,因?yàn)樗鼈兪莾煞N不同的類型,而且switch類型分支也不可能包含每個(gè)類似url.Values的類型,這會(huì)導(dǎo)致對這些庫的依賴。

沒有辦法來檢查未知類型的表示方式,我們被卡住了。這就是我們需要反射的原因。



以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號