go byte转uint_面试官问我go反射,我怀疑他让我写ORM框架
該文章始發于公眾號【邁莫coding】
地址:https://mp.weixin.qq.com/s/lgZykTL8ls6aG0OMNSbZMw
目錄
- 概念
- ValueOf使用格式
- 反射獲取值對象(ValueOf)
- 通過canSet方法修改值
- 判斷及獲取元素的相關方法
- 值修改相關方法
- 值修改條件:可尋址
- 結構體值的非導出字段不能通過反射來修改
- 通過ValueOf訪問成員對象
- 閑聊
- 歡迎加入我的公眾號【邁莫coding】 一起pk大廠
概念
在程序運行期間,如果想要獲取某個接口所代表的值,那么可以使用 reflect.ValueOf 進行獲取,使用方式和 reflect.TypeOf 函數使用方式類型,都是傳入一個interface{}接口的參數。當我們將一個接口值傳遞給一個 reflect.ValueOf 調用時,此調用返回的是代表著此接口值的動態值的一個reflect.Value值。 我們必須通過間接的途徑獲得一個代表一個接口值的 reflect.Value 值。
ValueOf使用格式
當調用 reflect.ValueOf 函數時,他會返回一個 reflect.Value 對象,如果我們想要獲取原值,則可通過具體方法來進行獲取,具體方法如下:
| 方法名 | 說 明 |
| Interface() | 將值以 interface{} 類型返回,可以通過類型斷言轉換為指定類型 |
| Int() int64 | 將值以 int 類型返回,所有有符號整型均可以此方式返回 |
| Uint() uint64 | 將值以 uint 類型返回,所有無符號整型均可以此方式返回 |
| Float() float64 | 將值以雙精度(float64)類型返回,所有浮點數(float32、float64)均可以此方式返回 |
| Bool() bool | 將值以 bool 類型返回 |
| Bytes() []bytes | 將值以字節數組 []bytes 類型返回 |
| String() string | 將值以字符串類型返回 |
演示
package mainimport ("fmt""reflect" )func main() {var a int = 56value := reflect.ValueOf(a)fmt.Println(value.Interface())fmt.Println(value.Interface().(int))結果:
56代碼說明:
- 第9行:定義變量a并賦值為56 - 第10行:通過reflect.ValueOf函數獲取值對象 - 第11行:獲取值對象的原型值 - 第12行:通過斷言獲取原型值通過ValueOf訪問成員對象
反射值對象(reflect.Value)提供對結構體訪問的方法,通過這些方法可以完成對結構體任意值的訪問,如下表所示。
| 方 法 | 備 注 |
| Field(i int) Value | 根據索引,返回索引對應的結構體成員字段的反射值對象。當值不是結構體或索引超界時發生宕機 |
| NumField() int | 返回結構體成員字段數量。當值不是結構體或索引超界時發生宕機 |
| FieldByName(name string) Value | 根據給定字符串返回字符串對應的結構體字段。沒有找到時返回零值,當值不是結構體或索引超界時發生宕機 |
| FieldByIndex(index []int) Value | 多層成員訪問時,根據 []int 提供的每個結構體的字段索引,返回字段的值。 沒有找到時返回零值,當值不是結構體或索引超界時發生宕機 |
| FieldByNameFunc(match func(string) bool) Value | 根據匹配函數匹配需要的字段。找到時返回零值,當值不是結構體或索引超界時發生宕機 |
演示
package mainimport ("fmt""reflect" )type Turbo struct {Name stringAge int }func main() {turbo := &Turbo{Name: "邁莫coding",Age: 1,}value := reflect.ValueOf(turbo)if value.Kind() == reflect.Ptr {value = value.Elem()for i := 0; i < value.NumField(); i++ {field := value.Field(i)fmt.Printf("字段類型:%v, 字段值:%vn", field.Type(), field.Interface())}st := value.FieldByName("Name")fmt.Printf("%vn", st.Interface())}結果:
字段類型:string, 字段值:邁莫coding 字段類型:int, 字段值:1 邁莫coding代碼說明:
- 第8行:定義結構體Turbo - 第14行:初始化Turbo結構體對象 - 第18行:通過reflect.ValueOf函數獲取Value對象 - 第19行:判斷反射類型對象種類是否為指針 - 第20行:獲取指針指向的元素 - 第21行:遍歷循環結構體中的字段屬性 - 第22行:獲取某個字段屬性的Value對象 - 第23行:獲取某個字段類型和字段原值通過canSet方法修改值
一個 reflect.Value 值的 CanSet 方法將返回此 reflect.Value 值代表的Go值是否可以被修改(可以被賦值)。 如果一個Go值可以被修改,則我們可以調用對應的 reflect.Value 值的Set方法來修改此Go值。 注意: reflect.ValueOf 函數直接返回的 reflect.Value 值都是不可修改的。
判定及獲取元素的相關方法
使用 reflect.Value 取元素、取地址及修改值的屬性方法請參考下表。
| 方法名 | 備 注 |
| Elem() Value | 取值指向的元素值,類似于語言層*操作。當值類型不是指針或接口時發生宕 機,空指針時返回 nil 的 Value |
| Addr() Value | 對可尋址的值返回其地址,類似于語言層&操作。當值不可尋址時發生宕機 |
| CanAddr() bool | 表示值是否可尋址 |
| CanSet() bool | 返回值能否被修改。要求值可尋址且是導出的字段 |
值修改相關方法
使用 reflect.Value 修改值的相關方法如下表所示。
| Set(x Value) | 將值設置為傳入的反射值對象的值 |
| Setlnt(x int64) | 使用 int64 設置值。當值的類型不是 int、int8、int16、 int32、int64 時會發生宕機 |
| SetUint(x uint64) | 使用 uint64 設置值。當值的類型不是 uint、uint8、uint16、uint32、uint64 時會發生宕機 |
| SetFloat(x float64) | 使用 float64 設置值。當值的類型不是 float32、float64 時會發生宕機 |
| SetBool(x bool) | 使用 bool 設置值。當值的類型不是 bod 時會發生宕機 |
| SetBytes(x []byte) | 設置字節數組 []bytes值。當值的類型不是 []byte 時會發生宕機 |
| SetString(x string) | 設置字符串值。當值的類型不是 string 時會發生宕機 |
值修改條件:可尋址
通過反射修改變量值的前提條件之一:這個值必須可以被尋址。簡單地說就是這個變量必須能被修改。
- 可尋址,可被修改
結果:
返回值是否被修改?false, 表示值是否可尋址?false 返回值是否被修改?false, 表示值是否可尋址?false 邁莫coding正式運營一個月代碼說明:
- 第9行:定義字符串n - 第11行:通過reflect.ValueOf函數獲取Value對象 - 第13行:取得vp的底層指針值引用的值的代表值 - 第15行:通過set()方法設置新值- 非指針地址數據不可被修改
結果:
panic: reflect: reflect.Value.SetInt using unaddressable value通過反射對非指針數據進行修改時,會拋出異常。
結構體值的非導出字段不能通過反射來修改
package mainimport ("fmt""reflect" )type Turbo struct {Name interface{}age interface{} } func main() {vs := reflect.ValueOf(&Turbo{})vs = reflect.Indirect(vs)vx, vy := vs.Field(0), vs.Field(1)fmt.Println(vx.CanSet(), vx.CanAddr())fmt.Println(vy.CanSet(), vy.CanAddr())vb := reflect.ValueOf(123)vx.Set(vb)vy.Set(vb) // 會造成恐慌,因為vy代表的值是不可修改的。fmt.Println(vx.IsNil(), vy.IsNil())結果:
true true false true panic: reflect: reflect.Value.Set using value obtained using unexported field false true代碼說明:
- 第8行:定義一個結構體類型Turbo - 第14行:如果vs代表著一個指針,下一行等價于"vs := vs.Elem()" - 第15行:分別取出結構體對象中的字段屬性值 - 第17行:vy為是地址類型但不可被修改 - 第19行:判斷vx,vy是否為空值 - 第20行:vx代表的值是可修改的,可暴露的字段 - 第21行:vy代表的值是不可修改的,會Panic異常閑聊
- 讀完文章,自己是不是和反射的cp率又提高了
- 我是邁莫,歡迎大家和我交流
歡迎加入我的公眾號【邁莫coding】 一起pk大廠
- 邁莫coding歡迎客官的到來
總結
以上是生活随笔為你收集整理的go byte转uint_面试官问我go反射,我怀疑他让我写ORM框架的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 4元一把0.14A 1400转的散热风扇
- 下一篇: 「重点」光绪21年是公元哪一年