C語言中文網 目錄
首頁 > Go語言教程 > Go語言反射 閱讀:2,455

Go語言通過反射獲取結構體的成員類型

任意值通過 reflect.TypeOf() 獲得反射對象信息后,如果它的類型是結構體,可以通過反射值對象(reflect.Type)的 NumField() 和 Field() 方法獲得結構體成員的詳細信息。與成員獲取相關的 reflect.Type 的方法如下表所示。

結構體成員訪問的方法列表
方法 說明
Field(i int) StructField 根據索引,返回索引對應的結構體字段的信息。當值不是結構體或索引超界時發生宕機
NumField() int 返回結構體成員字段數量。當類型不是結構體或索引超界時發生宕機
FieldByName(name string) (StructField, bool) 根據給定字符串返回字符串對應的結構體字段的信息。沒有找到時 bool 返回 false,當類型不是結構體或索引超界時發生宕機
FieldByIndex(index []int) StructField 多層成員訪問時,根據 []int 提供的每個結構體的字段索引,返回字段的信息。沒有找到時返回零值。當類型不是結構體或索引超界時 發生宕機
FieldByNameFunc( match func(string) bool) (StructField,bool) 根據匹配函數匹配需要的字段。當值不是結構體或索引超界時發生宕機

結構體字段類型

reflect.Type 的 Field() 方法返回 StructField 結構,這個結構描述結構體的成員信息,通過這個信息可以獲取成員與結構體的關系,如偏移、索引、是否為匿名字段、結構體標簽(Struct Tag)等,而且還可以通過 StructField 的 Type 字段進一步獲取結構體成員的類型信息。StructField 的結構如下:
type StructField struct {
    Name string          // 字段名
    PkgPath string       // 字段路徑
    Type      Type       // 字段反射類型對象
    Tag       StructTag  // 字段的結構體標簽
    Offset    uintptr    // 字段在結構體中的相對偏移
    Index     []int      // Type.FieldByIndex中的返回的索引值
    Anonymous bool       // 是否為匿名字段
}
字段說明如下。
  • Name:為字段名稱。
  • PkgPath:字段在結構體中的路徑。
  • Type:字段本身的反射類型對象,類型為 reflect.Type,可以進一步獲取字段的類型信息。
  • Tag:結構體標簽,為結構體字段標簽的額外信息,可以單獨提取。
  • Index:FieldByIndex 中的索引順序。
  • Anonymous:表示該字段是否為匿名字段。

獲取成員反射信息

下面代碼中,實例化一個結構體并遍歷其結構體成員,再通過 reflect.Type 的 FieldByName() 方法查找結構體中指定名稱的字段,直接獲取其類型信息。

反射訪問結構體成員類型及信息:
package main

import (
    "fmt"
    "reflect"
)

func main() {

    // 聲明一個空結構體
    type cat struct {
        Name string

        // 帶有結構體tag的字段
        Type int `json:"type" id:"100"`
    }

    // 創建cat的實例
    ins := cat{Name: "mimi", Type: 1}

    // 獲取結構體實例的反射類型對象
    typeOfCat := reflect.TypeOf(ins)

    // 遍歷結構體所有成員
    for i := 0; i < typeOfCat.NumField(); i++ {

        // 獲取每個成員的結構體字段類型
        fieldType := typeOfCat.Field(i)

        // 輸出成員名和tag
        fmt.Printf("name: %v  tag: '%v'\n", fieldType.Name, fieldType.Tag)
    }

    // 通過字段名, 找到字段類型信息
    if catType, ok := typeOfCat.FieldByName("Type"); ok {

        // 從tag中取出需要的tag
        fmt.Println(catType.Tag.Get("json"), catType.Tag.Get("id"))
    }
}
代碼輸出如下:
name: Name  tag: ''
name: Type  tag: 'json:"type" id:"100"'
type 100

代碼說明如下:
  • 第 11 行,聲明了帶有兩個成員的 cat 結構體。
  • 第 15 行,Type 是 cat 的一個成員,這個成員類型后面帶有一個以`開始和結尾的字符串。這個字符串在 Go 語言中被稱為 Tag(標簽)。一般用于給字段添加自定義信息,方便其他模塊根據信息進行不同功能的處理。
  • 第 19 行,創建 cat 實例,并對兩個字段賦值。結構體標簽屬于類型信息,無須且不能賦值。
  • 第 22 行,獲取實例的反射類型對象。
  • 第 25 行,使用 reflect.Type 類型的 NumField() 方法獲得一個結構體類型共有多少個字段。如果類型不是結構體,將會觸發宕機錯誤。
  • 第 28 行,reflect.Type 中的 Field() 方法和 NumField 一般都是配對使用,用來實現結構體成員的遍歷操作。
  • 第 31 行,使用 reflect.Type 的 Field() 方法返回的結構不再是 reflect.Type 而是StructField 結構體。
  • 第 35 行,使用 reflect.Type 的 FieldByName() 根據字段名查找結構體字段信息,cat Type 表示返回的結構體字段信息,類型為 StructField,ok 表示是否找到結構體字段的信息。
  • 第 38 行中,使用 StructField 中 Tag 的 Get() 方法,根據 Tag 中的名字進行信息獲取。

精美而實用的網站,提供C語言C++STLLinuxShellJavaGo語言等教程,以及socketGCCviSwing設計模式JSP等專題。

Copyright ?2011-2018 biancheng.net, 陜ICP備15000209號

底部Logo