Go語言的反射reflect使用大全
前言
Go語言作為一個高性能的靜態(tài)語言,我們在寫函數(shù)的時候,由于go語言的特性,我們需要定義變量類型,大多情況下,變量類型是固定結(jié)構(gòu)體,這就會導(dǎo)致我們想做一個適配性較高的函數(shù)的時候,則需要將變量以及返回值用interface{}接口實現(xiàn)
一、映射的基本用法
1.獲取類型信息
使用`reflect.TypeOf()`可以獲取任何值的類型信息
var x float64 = 3.4 fmt.Println("type:", reflect.TypeOf(x))
2.獲取值
使用`reflect.ValueOf()`可以獲取reflect.Value類型表示的實際值:
var x float64 = 3.4 v := reflect.ValueOf(x) fmt.Println("value:", v) fmt.Println("type:", v.Type()) fmt.Println("kind:", v.Kind())
3.讀取和設(shè)置值
通過reflect可以對變量的值進行讀取和設(shè)置:
var x float64 = 3.4 p := reflect.ValueOf(&x) // 注意這里必須要傳遞x的地址 v := p.Elem() v.SetFloat(7.1)
4.使用Kind來區(qū)分類型
`reflect.Kind`可以用來區(qū)分基本類型:
v := reflect.ValueOf(x) if v.Kind() == reflect.Float64 { // x是float64類型 }
5.操作結(jié)構(gòu)體
可以通過`reflect`包來動態(tài)地讀取和設(shè)置結(jié)構(gòu)體的字段,甚至可以調(diào)用方法:
type MyStruct struct { Field1 int Field2 string } s := MyStruct{Field1: 10, Field2: "Hello"} v := reflect.ValueOf(s) typeOfS := v.Type() for i := 0; i < v.NumField(); i++ { field := v.Field(i) fmt.Printf("%d: %s %s = %v ", i, typeOfS.Field(i).Name, field.Type(), field.Interface()) }
6.創(chuàng)建新實例
type MyStruct struct { Field1 int } var msType reflect.Type = reflect.TypeOf(MyStruct{}) msValue := reflect.New(msType).Elem() msValue.Field(0).SetInt(10)
7.調(diào)用方法
//動態(tài)調(diào)用方法 v := reflect.ValueOf(s) m := v.MethodByName("MethodName") args := []reflect.Value{reflect.ValueOf(arg1), reflect.ValueOf(arg2)} result := m.Call(args)
8.調(diào)用方法
對于映射、切片和數(shù)組類型,`reflect`包提供了額外的函數(shù)來動態(tài)操作它們;例如可以通過`reflect.Append`、`reflect.MakeSlice`等創(chuàng)建和操作切片:
a := []int{1,2,3} v := reflect.ValueOf(a) newValue := reflect.Append(v, reflect.ValueOf(4)) fmt.Println(newValue.Interface()) // [1 2 3 4]
二、使用實例
在GIN+GROM框架中我建立了一個表模板
type TempGeo struct { BSM string `gorm:"type:varchar(255);primary_key"` TBMJ float64 MAC string `gorm:"type:varchar(255)"` Name string `gorm:"type:varchar(255)"` Date string `gorm:"type:varchar(255)"` Geom string `gorm:"type:geometry(MultiPolygon,4326)"` }
我寫了一個接口,想將這個表轉(zhuǎn)換為Geojson
func (uc *UserController) ShowTempGeo(c *gin.Context) { bsm := c.Query("bsm") var mytable []models.TempGeo DB := models.DB DB.Where("bsm = ?", bsm).Find(&mytable) data := methods.MakeGeoJSON(mytable) c.JSON(http.StatusOK, data) }
其中的MakeGeoJSON函數(shù)就是使用了映射實現(xiàn)的,如果不使用映射,就會出現(xiàn)如果我重新造一個表,那么我就需要重寫一個MakeGeoJSON函數(shù)并新定義變量,這是靜態(tài)語言很麻煩的一個事情,還好go在這方面有一個映射的口子,讓我們能寫出泛用性函數(shù)。以下代碼就是將數(shù)據(jù)都通過映射實現(xiàn)。
func MakeGeoJSON(items interface{}) interface{} { var FeaturesList []*geojson.Feature FeaturesList = []*geojson.Feature{} var sliceValue reflect.Value if reflect.TypeOf(items).Kind() == reflect.Slice { sliceValue = reflect.ValueOf(items) } else { sliceValue = reflect.MakeSlice(reflect.SliceOf(reflect.TypeOf(items)), 1, 1) sliceValue.Index(0).Set(reflect.ValueOf(items)) } for i := 0; i < sliceValue.Len(); i++ { t := sliceValue.Index(i).Interface() v := reflect.ValueOf(t) tt := reflect.TypeOf(t) geomField := v.FieldByName("Geom") if !geomField.IsValid() { continue } geomStr, _ := geomField.Interface().(string) properties := make(map[string]interface{}) for i := 0; i < v.NumField(); i++ { if tt.Field(i).Name != "Geom" { properties[strings.ToLower(tt.Field(i).Name)] = v.Field(i).Interface() } } wkbBytes, _ := hex.DecodeString(strings.Trim(geomStr, " ")) geom, _ := wkb.Unmarshal(wkbBytes) feature := geojson.NewFeature(geom) feature.Properties = properties FeaturesList = append(FeaturesList, feature) } features := geojson.NewFeatureCollection() features.Features = FeaturesList GeoJSON, _ := json.Marshal(features) var obj interface{} json.Unmarshal(GeoJSON, &obj) return obj }
總結(jié)
在Go語言中,`reflect`包被用來在運行時動態(tài)地操作對象。盡管這個包非常強大,但是它通常不建議用于日常編程,因為它會使代碼更難理解和維護,同時也會減慢程序運行速度。但是當(dāng)你需要編寫通用代碼或者框架,或者需要處理未知類型的數(shù)據(jù)時,`reflect` 包就顯得非常有用。
到此這篇關(guān)于Go語言的反射reflect使用大全的文章就介紹到這了,更多相關(guān)Go語言 反射reflect內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
一文帶大家了解Go語言中的內(nèi)聯(lián)優(yōu)化
內(nèi)聯(lián)優(yōu)化是一種常見的編譯器優(yōu)化策略,通俗來講,就是把函數(shù)在它被調(diào)用的地方展開,這樣可以減少函數(shù)調(diào)用所帶來的開銷,本文主要為大家介紹了Go中內(nèi)聯(lián)優(yōu)化的具體使用,需要的可以參考下2023-05-05