iT邦幫忙

2022 iThome 鐵人賽

DAY 24
0
Software Development

你知道Go是什麼嗎?系列 第 24

Day24 - Reflection - Golang

  • 分享至 

  • xImage
  •  

今天出了點意外,不一定有時間趕完昨天WebSocket的東西,所以先把之前研究到一半的文章先丟出來,萬分抱歉

Reflection

反射Reflection是一種為了能在「執行期間」獲取對象方法或屬性的一種能力。雖然反射較為吃效能,但可以幫助抽象及簡化程式碼,提高開發效率。

直接使用一次看看吧,反射相關功能都定義在reflect package

import "reflect"

TypeOf()

使用TypeOf()可以獲取一個實體的型別,在取得TypeOf之後可以進行一系列的操作,官方的Type內有完整的程式碼可以看。

func main() {

    var a int
    var b string
    var m (map[string]string)

    typeOf_A := reflect.TypeOf(a)
    typeOf_B := reflect.TypeOf(b)
    typeOf_M := reflect.TypeOf(m)

    fmt.Println("typeff_A:", typeOf_A)
    fmt.Println("typeOf_B:", typeOf_B)
    fmt.Println("typeOf_M:", typeOf_M)
}

output:

typeff_A: int
typeOf_B: string
typeOf_M: map[string]string

Name()、Kind()

Name可以獲得自訂型別的名稱,Kind可以獲得該類別的名稱,以map與自訂型別Student試一次

func main() {
    type Student struct {
    	Name   string
    	Height float64
    }
    ming := Student{"Ming", 172.0} 
    
    m := map[string]int{
    	"ming":   172,
    	"BenLee": 169,
    }
    
    typeOfMing := reflect.TypeOf(ming)
    typeOfM := reflect.TypeOf(m)
    fmt.Println("typeOfMing Name:", typeOfMing.Name(), "Kind:", typeOfMing.Kind())
	fmt.Println("typeOfM Name:", typeOfM.Name(), "Kind:", typeOfM.Kind())
}

output:

typeOfMing Name: Student Kind: struct
typeOfM Name: Kind: map

NumField()

透過NumField獲取結構內的資料

func main() {
    type Student struct {
    	Name   string
    	Height float64
    	Weight int
    }
    ming := Student{"Ming", 170.0, 75}    
    
    typeOfMing := reflect.TypeOf(ming)

    for i := 0; i < typeOfMing.NumField(); i++ {
    	file := typeOfMing.Field(i)
    	fmt.Println(file.Name, file.Type)
    }
}

output:

Name string
Height float64
Weight int

Type()的部分先到這邊,還有很多功能我也沒什麼頭緒,之後如果用到再回來補充QQ

Valueof()

若是想取得資料的值,則需要使用reflect.ValueOf()獲取Value物件後進行操作。Value的官方內容。

func main() {
    type Student struct {
    	Name   string
    	Height float64
    	Weight int
    }
    ming := Student{"Ming", 170.0, 75}

    valueOfMing := reflect.ValueOf(ming)

    fmt.Println("print all:",valueOfMing)
    fmt.Println("name:", valueOfMing.FieldByName("Name"))
    fmt.Println("height:", valueOfMing.FieldByName("Height"))
    fmt.Println("weight:", valueOfMing.FieldByName("Weight"))
}

output:

print all: {Ming 170 75}
print name: Ming
print height: 170
print weight: 75

Elem()

若傳入的是指標類型,則必須使用Elem()來取得資料,繼續原本的例子

func main() {
    type Student struct {
    	Name   string
    	Height float64
    	Weight int
    }
    ming := &Student{"Ming", 170.0, 75}

    valueOfMing := reflect.ValueOf(ming).Elem()

    fmt.Println("print all:", valueOfMing)
    fmt.Println("name:", valueOfMing.FieldByName("Name"))
}

可以交叉比對一下沒使用Elem(),以及傳入指標的差距。


介紹的這麼沒底過,看好久還是看不出reflect可以用在什麼地方,一直不斷地介紹用法而已,明天會繼續回歸WebSocket的應用


參考資料


上一篇
Day23 - WebSocket - Golang
下一篇
Day25 - WebSocket簡易聊天室 - Golang
系列文
你知道Go是什麼嗎?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

1
usnp2001
iT邦新手 4 級 ‧ 2023-08-25 10:38:05

我覺得 Reflection 可以用在資料 Model 對應的時候很好用,實作 ORM 架構

我要留言

立即登入留言