變數的內在機制
型別資訊:是靜態的元資訊,是預先定義好的
值資訊:是程式運行程序中動態改變的
反射的使用
獲取型別資訊:reflect.TypeOf,是靜態的
獲取值資訊:reflect.ValueOf,是動態的
反射獲取interface值資訊
package main
import (
"fmt"
"reflect"
)
//反射獲取interface值資訊
func reflect_value(a interface{}) {
v := reflect.ValueOf(a)
fmt.Println(v)
k := v.Kind()
fmt.Println(k)
switch k {
case reflect.Float64:
fmt.Println("a是:", v.Float())
}
}
func main() {
var x float64 = 3.4
reflect_value(x)
}
反射修改值資訊
package main
import (
"fmt"
"reflect"
)
//反射修改值
func reflect_set_value(a interface{}) {
v := reflect.ValueOf(a)
k := v.Kind()
switch k {
case reflect.Float64:
// 反射修改值
v.SetFloat(6.9)
fmt.Println("a is ", v.Float())
case reflect.Ptr:
// Elem()獲取地址指向的值
v.Elem().SetFloat(7.9)
fmt.Println("case:", v.Elem().Float())
// 地址
fmt.Println(v.Pointer())
}
}
func main() {
var x float64 = 3.4
// 反射認為下面是指標型別,不是float型別
reflect_set_value(&x)
fmt.Println("main:", x)
}
結構體與反射
查看型別、欄位和方法
package main
import (
"fmt"
"reflect"
)
// 定義結構體
type User struct {
Id int
Name string
Age int
}
// 綁方法
func (u User) Hello() {
fmt.Println("Hello")
}
// 傳入interface{}
func Poni(o interface{}) {
t := reflect.TypeOf(o)
fmt.Println("型別:", t)
fmt.Println("字串型別:", t.Name())
// 獲取值
v := reflect.ValueOf(o)
fmt.Println(v)
// 可以獲取所有屬性
// 獲取結構體欄位個數:t.NumField()
for i := 0; i < t.NumField(); i++ {
// 取每個欄位
f := t.Field(i)
fmt.Printf("%s : %v", f.Name, f.Type)
// 獲取欄位的值資訊
// Interface():獲取欄位對應的值
val := v.Field(i).Interface()
fmt.Println("val :", val)
}
fmt.Println("=================方法====================")
for i := 0; i < t.NumMethod(); i++ {
m := t.Method(i)
fmt.Println(m.Name)
fmt.Println(m.Type)
}
}
func main() {
u := User{1, "zs", 20}
Poni(u)
}
查看匿名欄位
package main
import (
"fmt"
"reflect"
)
// 定義結構體
type User struct {
Id int
Name string
Age int
}
// 匿名欄位
type Boy struct {
User
Addr string
}
func main() {
m := Boy{User{1, "zs", 20}, "bj"}
t := reflect.TypeOf(m)
fmt.Println(t)
// Anonymous:匿名
fmt.Printf("%#v\n", t.Field(0))
// 值資訊
fmt.Printf("%#v\n", reflect.ValueOf(m).Field(0))
}
修改結構體的值
package main
import (
"fmt"
"reflect"
)
// 定義結構體
type User struct {
Id int
Name string
Age int
}
// 修改結構體值
func SetValue(o interface{}) {
v := reflect.ValueOf(o)
// 獲取指標指向的元素
v = v.Elem()
// 取欄位
f := v.FieldByName("Name")
if f.Kind() == reflect.String {
f.SetString("kuteng")
}
}
func main() {
u := User{1, "5lmh.com", 20}
SetValue(&u)
fmt.Println(u)
}
呼叫方法
package main
import (
"fmt"
"reflect"
)
// 定義結構體
type User struct {
Id int
Name string
Age int
}
func (u User) Hello(name string) {
fmt.Println("Hello:", name)
}
func main() {
u := User{1, "5lmh.com", 20}
v := reflect.ValueOf(u)
// 獲取方法
m := v.MethodByName("Hello")
// 構建一些引數
args := []reflect.Value{reflect.ValueOf("6666")}
// 沒引數的情況下:var args2 []reflect.Value
// 呼叫方法,需要傳入方法的引數
m.Call(args)
}
獲取欄位的tag
package main
import (
"fmt"
"reflect"
)
type Student struct {
Name string `json:"name1" db:"name2"`
}
func main() {
var s Student
v := reflect.ValueOf(&s)
// 型別
t := v.Type()
// 獲取欄位
f := t.Elem().Field(0)
fmt.Println(f.Tag.Get("json"))
fmt.Println(f.Tag.Get("db"))
}
實體
方法
package common
import (
"errors"
"reflect"
"strconv"
"time"
)
//根據結構體中sql標簽映射資料到結構體中并且轉換型別
func DataToStructByTagSql(data map[string]string, obj interface{}) {
objValue := reflect.ValueOf(obj).Elem()
for i := 0; i < objValue.NumField(); i++ {
//獲取sql對應的值
value := data[objValue.Type().Field(i).Tag.Get("sql")]
//獲取對應欄位的名稱
name := objValue.Type().Field(i).Name
//獲取對應欄位型別
structFieldType := objValue.Field(i).Type()
//獲取變數型別,也可以直接寫"string型別"
val := reflect.ValueOf(value)
var err error
if structFieldType != val.Type() {
//型別轉換
val, err = TypeConversion(value, structFieldType.Name()) //型別轉換
if err != nil {
}
}
//設定型別值
objValue.FieldByName(name).Set(val)
}
}
//型別轉換
func TypeConversion(value string, ntype string) (reflect.Value, error) {
if ntype == "string" {
return reflect.ValueOf(value), nil
} else if ntype == "time.Time" {
t, err := time.ParseInLocation("2006-01-02 15:04:05", value, time.Local)
return reflect.ValueOf(t), err
} else if ntype == "Time" {
t, err := time.ParseInLocation("2006-01-02 15:04:05", value, time.Local)
return reflect.ValueOf(t), err
} else if ntype == "int" {
i, err := strconv.Atoi(value)
return reflect.ValueOf(i), err
} else if ntype == "int8" {
i, err := strconv.ParseInt(value, 10, 64)
return reflect.ValueOf(int8(i)), err
} else if ntype == "int32" {
i, err := strconv.ParseInt(value, 10, 64)
return reflect.ValueOf(int64(i)), err
} else if ntype == "int64" {
i, err := strconv.ParseInt(value, 10, 64)
return reflect.ValueOf(i), err
} else if ntype == "float32" {
i, err := strconv.ParseFloat(value, 64)
return reflect.ValueOf(float32(i)), err
} else if ntype == "float64" {
i, err := strconv.ParseFloat(value, 64)
return reflect.ValueOf(i), err
}
//else if .......增加其他一些型別的轉換
return reflect.ValueOf(value), errors.New("未知的型別:" + ntype)
}
呼叫
package main
import (
"fmt"
"github.com/student/1129/common"
)
//Product Product定義一個結構體
type Product struct {
ID int64 `json:"id" sql:"id"`
ProductClass string `json:"ProductClass" sql:"ProductClass"`
ProductName string `json:"ProductName" sql:"productName"`
ProductNum int64 `json:"ProductNum" sql:"productNum"`
ProductImage string `json:"ProductImage" sql:"productImage"`
ProductURL string `json:"ProductUrl" sql:"productUrl" `
}
func main() {
//這塊是模擬mysql獲取單條的資料反射到結構體
data := map[string]string{"id": "1", "ProductClass": "blog", "productName": "5lmh.com", "productNum": "40", "productImage": "http://www.5lmh.com/", "productUrl": "http://www.5lmh.com/"}
productResult := &Product{}
common.DataToStructByTagSql(data, productResult)
fmt.Println(*productResult)
//這塊是模擬mysql獲取所有的資料反射到結構體
Alldata := []map[string]string{
{"id": "1", "ProductClass": "blog", "productName": "5lmh.com", "productNum": "40", "productImage": "http://www.5lmh.com/", "productUrl": "http://www.5lmh.com/"},
{"id": "2", "ProductClass": "blog", "productName": "5lmh.com", "productNum": "40", "productImage": "http://www.5lmh.com/", "productUrl": "http://www.5lmh.com/"},
}
var productArray []*Product
for _, v := range Alldata {
Allproduct := &Product{}
common.DataToStructByTagSql(v, Allproduct)
productArray = append(productArray, Allproduct)
}
for _, vv := range productArray {
fmt.Println(vv)
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/285571.html
標籤:PHP
上一篇:Git 使用技巧
