Go語(yǔ)言反射獲取類型屬性和方法示例
reflect.StructField 和 reflect.Method
如果變量是一個(gè)結(jié)構(gòu)體,我們還可以通過(guò)結(jié)構(gòu)體域類型對(duì)象 reflect.StructField 來(lái)獲取結(jié)構(gòu)體下字段的類型屬性。Type 接口下提供了不少用于獲取字段結(jié)構(gòu)體域類型對(duì)象的方法,我們主要介紹以下幾個(gè)接口:
// 獲取一個(gè)結(jié)構(gòu)體內(nèi)的字段數(shù)量 NumField() int // 根據(jù) index 獲取結(jié)構(gòu)體內(nèi)的成員字段類型對(duì)象 Field(i int) StructField // 根據(jù)字段名獲取結(jié)構(gòu)體內(nèi)的成員字段類型對(duì)象 FieldByName(name string) (StructField, bool)
通過(guò)以上的 3 個(gè)方法,我們可以輕易地拿到一個(gè)結(jié)構(gòu)體變量?jī)?nèi)的所有成員字段的類型對(duì)象 reflect.StructField。通過(guò) reflect.StructField,我們可以知道成員字段所屬的類型和種類,其內(nèi)主要由以下的屬性:
type StructField struct { // 成員字段的名稱 Name string // 成員字段 Type Type Type // Tag Tag StructTag // 字節(jié)偏移 Offset uintptr // 成員字段的 index Index []int // 成員字段是否公開(kāi) Anonymous bool }
StructField
StructField 中提供了 Type 用于獲取字段的的類型信息,而 StructTag 一般用來(lái)描述結(jié)構(gòu)體成員字段的額外信息,比如在 JSON 進(jìn)行序列化和對(duì)象映射時(shí)會(huì)被使用。StructTag 一般由一個(gè)或者多個(gè)鍵值對(duì)組成,一個(gè)簡(jiǎn)單的例子如下:
ID string `json:"id"`
鍵與值使用 : 分隔,值用 "" 括起來(lái), 鍵值對(duì)之間使用空格分隔。上面例子中說(shuō)明 ID 字段在 JSON 序列化時(shí)會(huì)被變成 id 。
遍歷 Hero 結(jié)構(gòu)體
接下來(lái),我們通過(guò)遍歷 Hero 結(jié)構(gòu)體,獲取其內(nèi)字段的類型并輸出,代碼如下所示:
func main() { typeOfHero := reflect.TypeOf(Hero{}) // 通過(guò) #NumField 獲取結(jié)構(gòu)體字段的數(shù)量 for i := 0 ; i < typeOfHero.NumField(); i++{ fmt.Printf("field' name is %s, type is %s, kind is %s\n", typeOfHero.Field(i).Name, typeOfHero.Field(i).Type, typeOfHero.Field(i).Type.Kind()) } // 獲取名稱為 Name 的成員字段類型對(duì)象 nameField, _ := typeOfHero.FieldByName("Name") fmt.Printf("field' name is %s, type is %s, kind is %s\n", nameField.Name, nameField.Type, nameField.Type.Kind()) }
預(yù)期的結(jié)果如下所示:
field' name is Name, type is string, kind is string
field' name is Age, type is int, kind is int
field' name is Speed, type is int, kind is int
field' name is Name, type is string, kind is string
上述代碼中先使用 Type#NumField 獲取 Hero 結(jié)構(gòu)體中字段的數(shù)量,再通過(guò) typeOfHero#Field 根據(jù) index 獲取每個(gè)字段域類型對(duì)象并打印它們的類型信息。代碼最后還演示如何通過(guò) typeOfHero#FieldByName 獲取了字段名為 Name 的字段域類型對(duì)象。
Method
除了獲取結(jié)構(gòu)體下的字段域類型對(duì)象,Type 還提供方法獲取接口下方法的方法類型對(duì)象 Method,接口方法描述如下:
// 根據(jù) index 查找方法 Method(int) Method // 根據(jù)方法名查找方法 MethodByName(string) (Method, bool) // 獲取類型中公開(kāi)的方法數(shù)量 NumMethod() int
獲取到的方法類型描述對(duì)象 Method 描述了方法的基本信息,包括方法名,方法類型等,代碼如下所示:
type Method struct { // 方法名 Name string // 方法類型 Type Type // 反射對(duì)象,可用于調(diào)用方法 Func Value // 方法的index Index int }
在 Method 中 Func 字段是一個(gè)反射值對(duì)象,可用于進(jìn)行方法的調(diào)用。如果 Method 是來(lái)自于接口類型反射得到的 Type ,那么 Func 傳遞的第一個(gè)參數(shù)需要為實(shí)現(xiàn)方法的接收器,這部分區(qū)別我們將在 Value 中進(jìn)行具體的介紹。
我們可以通過(guò) Type 中提供的方法獲取接口 Person 中方法的方法類型對(duì)象,代碼如下所示:
func main() { // 聲明一個(gè) Person 接口,并用 Hero 作為接收器 var person Person = &Hero{} // 獲取接口Person的類型對(duì)象 typeOfPerson := reflect.TypeOf(person) // 打印Person的方法類型和名稱 for i := 0 ; i < typeOfPerson.NumMethod(); i++{ fmt.Printf("method is %s, type is %s, kind is %s.\n", typeOfPerson.Method(i).Name, typeOfPerson.Method(i).Type, typeOfPerson.Method(i).Type.Kind()) } method, _ := typeOfPerson.MethodByName("Run") fmt.Printf("method is %s, type is %s, kind is %s.\n", method.Name, method.Type, method.Type.Kind()) }
預(yù)期的輸出結(jié)果如下所示:
method is Run, type is func(*main.Hero), kind is func
method is SayHello, type is func(*main.Hero, string), kind is func
method is Run, type is func(*main.Hero) string, kind is func.
除了通過(guò) typeOfPerson#Method 根據(jù) index 獲取方法類型對(duì)象,還可以使用 typeOfPerson#MethodByName 根據(jù)方法名查找對(duì)應(yīng)的方法類型對(duì)象。從輸出結(jié)果可以看出,方法的種類均為 func,而類型則為方法的聲明。
小結(jié)
本文主要介紹了 Go 語(yǔ)言的反射基礎(chǔ) reflect.StructField 和 reflect.Method。通過(guò)反射,我們可以拿到類型信息和定義的方法等,Go 的反射實(shí)現(xiàn)了反射的大多數(shù)功能,獲取類型信息需要配合使用標(biāo)準(zhǔn)庫(kù)中的詞法、語(yǔ)法解析器和抽象語(yǔ)法數(shù)對(duì)源碼進(jìn)行掃描。下一篇文章將會(huì)繼續(xù)介紹 Go 語(yǔ)言的反射 reflect.Value 反射值對(duì)象相關(guān)內(nèi)容。
以上就是Go語(yǔ)言反射獲取類型屬性和方法示例的詳細(xì)內(nèi)容,更多關(guān)于Go反射獲取類型屬性方法的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Golang上下文Context的常見(jiàn)應(yīng)用場(chǎng)景
Golang?context主要用于定義超時(shí)取消,取消后續(xù)操作,在不同操作中傳遞值。本文通過(guò)簡(jiǎn)單易懂的示例進(jìn)行說(shuō)明,感興趣的可以了解一下2023-04-04go語(yǔ)言實(shí)現(xiàn)并發(fā)網(wǎng)絡(luò)爬蟲(chóng)的示例代碼
本文主要介紹了go語(yǔ)言實(shí)現(xiàn)并發(fā)網(wǎng)絡(luò)爬蟲(chóng)的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03Golang defer延遲語(yǔ)句的實(shí)現(xiàn)
defer擁有注冊(cè)延遲調(diào)用的機(jī)制,本文主要介紹了Golang defer延遲語(yǔ)句的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-07-07Go語(yǔ)言中函數(shù)的參數(shù)傳遞與調(diào)用的基本方法
這篇文章主要介紹了Go語(yǔ)言中函數(shù)的參數(shù)傳遞與調(diào)用的基本方法,是golang入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-10-10解決golang sync.Wait()不執(zhí)行的問(wèn)題
這篇文章主要介紹了解決golang sync.Wait()不執(zhí)行的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12