最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go語言學(xué)習(xí)之反射的用法詳解

 更新時間:2022年04月21日 14:08:01   作者:隱姓埋名4869  
反射指的是運(yùn)行時動態(tài)的獲取變量的相關(guān)信息。本文將為大家詳細(xì)介紹Go語言中反射的用法,文中的示例代碼講解詳細(xì),感興趣的可以了解一下

反射指的是運(yùn)行時動態(tài)的獲取變量的相關(guān)信息

1. reflect 包

類型是變量,類別是常量

reflect.TypeOf,獲取變量的類型,返回reflect.Type類型

reflect.ValueOf,獲取變量的值,返回reflect.Value類型

reflect.Value.Kind,獲取變量的類別,返回一個常量

reflect.Value.Interface(),轉(zhuǎn)換成interface{}類型

1.1 獲取變量類型

package main

import (
	"fmt"
	"reflect"
)

func Test(i interface{}) {
	//反射數(shù)據(jù)類型
	t := reflect.TypeOf(i)
	fmt.Println("類型是", t)
	//反射數(shù)據(jù)值
	v := reflect.ValueOf(i)
	fmt.Println("值是", v)
}

func main() {
	a := "hello"
	Test(a)
}

輸出結(jié)果如下

類型是 string
值是 hello

package main

import (
	"fmt"
	"reflect"
)

type Student struct {
	Name  string
	Age   int
	Score float32
}

func Test(i interface{}) {
	//反射獲取類型
	t := reflect.TypeOf(i)
	fmt.Println("類型是", t)

	//反射獲取值
	v := reflect.ValueOf(i)
	//判斷值的類別
	c := v.Kind()
	fmt.Println("類別是", c)
}

func main() {
	var stu Student = Student{
		Name:  "張三",
		Age:   18,
		Score: 80,
	}
	Test(stu)

	fmt.Println("-------------")
	var num int = 10
	Test(num)
}

輸出結(jié)果如下

類型是 main.Student
類別是 struct
-------------
類型是 int
類別是 int

1.2 斷言處理類型轉(zhuǎn)換

package main

import (
	"fmt"
	"reflect"
)

type Student struct {
	Name  string
	Age   int
	Score float32
}

func Test(i interface{}) {
	t := reflect.TypeOf(i)
	fmt.Println("類型是", t)

	//類別
	v := reflect.ValueOf(i)
	c := v.Kind()
	fmt.Println("類別是", c)
	fmt.Printf("c的類型是%T\n", c)
	fmt.Printf("v的類型是%T\n", v)

	//轉(zhuǎn)換成接口
	iv := v.Interface()
	fmt.Printf("iv的類型%T\n", iv)
	//斷言處理
	stu_iv, err := iv.(Student)
	if err {
		fmt.Printf("stu_iv的類型%T\n", stu_iv)
	}
}

func main() {
	var stu Student = Student{
		Name:  "張三",
		Age:   18,
		Score: 80,
	}
	Test(stu)

}

輸出結(jié)果如下

類型是 main.Student
類別是 struct
c的類型是reflect.Kind
v的類型是reflect.Value
iv的類型main.Student
stu_iv的類型main.Student

2. ValueOf

2.1 獲取變量值

reflect.valueof(x).Float()

reflect.valueof(x).Int()

reflect.valueof(x).String()

reflect.Valueof(x).Bool()

2.2 類型轉(zhuǎn)換

package main

import (
	"fmt"
	"reflect"
)

func Test(i interface{}) {
	v := reflect.ValueOf(i)
	fmt.Printf("v的類型是%T\n", v)
	//轉(zhuǎn)換成指定類型
	t := v.Int()
	fmt.Printf("t的類型是%T\n", t)
}

func main() {
	//類型不同的話會報錯
	var num int = 100
	Test(num)
}

輸出結(jié)果如下

v的類型是reflect.Value
t的類型是int64

3. Value.Set

3.1 設(shè)置變量值

reflect.Value.SetFloat(),設(shè)置浮點(diǎn)數(shù)

reflect.value.SetInt(),設(shè)置整數(shù)

reflect.Value.SetString(),設(shè)置字符串

3.2 示例

package main

import (
	"fmt"
	"reflect"
)

func Test(i interface{}) {
	v := reflect.ValueOf(i)
	//更新值需要value的地址,否則會保存,Elem()表示指針*
	v.Elem().SetInt(100)
	result := v.Elem().Int()
	fmt.Printf("result類型為 %T, 值為 %d\n", result, result)
}

func main() {
	var num int = 10
	Test(&num)
}

輸出結(jié)果如下

result類型為 int64, 值為 100

4. 結(jié)構(gòu)體反射

反射出結(jié)構(gòu)體的屬性和方法數(shù)量

方法名需大寫,需要被跨包調(diào)用識別

4.1 查看結(jié)構(gòu)體字段數(shù)量和方法數(shù)量

package main

import (
	"fmt"
	"reflect"
)

//結(jié)構(gòu)體
type Student struct {
	Name  string
	Age   int
	Score float32
}

//結(jié)構(gòu)體方法
func (s Student) Run() {
	fmt.Println("Running")
}

func (s Student) Sleep() {
	fmt.Println("Sleeping")
}

//使用反射查看結(jié)構(gòu)體字段數(shù)量和方法數(shù)量
func Test(i interface{}) {
	v := reflect.ValueOf(i)
	//類別判斷
	if v.Kind() != reflect.Struct {
		fmt.Println("不是結(jié)構(gòu)體")
		return
	}
	//獲取結(jié)構(gòu)體中字段數(shù)量
	stu_num := v.NumField()
	fmt.Println("字段數(shù)量: ", stu_num)
	//獲取結(jié)構(gòu)體中方法數(shù)量
	stu_meth := v.NumMethod()
	fmt.Println("方法數(shù)量: ", stu_meth)
}

func main() {
	var stu Student = Student{
		Name:  "張三",
		Age:   18,
		Score: 88,
	}
	Test(stu)
}

輸出結(jié)果如下

字段數(shù)量:  3
方法數(shù)量:  2

4.2 獲取結(jié)構(gòu)體屬性

package main

import (
	"fmt"
	"reflect"
)

type Student struct {
	Name  string
	Age   int
	Score float32
}

func Test(i interface{}) {
	v := reflect.ValueOf(i)
	//獲取結(jié)構(gòu)體中每個屬性
	for i := 0; i < v.NumField(); i++ {
		//輸出屬性值
		fmt.Printf("%d %v\n", i, v.Field(i))
		//輸出屬性值的類型
		fmt.Printf("%d %v\n", i, v.Field(i).Kind())
	}
}

func main() {
	var stu Student = Student{
		Name:  "張三",
		Age:   18,
		Score: 88,
	}
	Test(stu)
}

輸出結(jié)果如下

0 張三
0 string
1 18
1 int
2 88
2 float32

4.3 更改屬性值

package main

import (
	"fmt"
	"reflect"
)

type Student struct {
	Name  string
	Age   int
	Score float32
}

func Test(i interface{}, name string) {
	v := reflect.ValueOf(i)
	vk := v.Kind()
	//判斷是都為指針并指向結(jié)構(gòu)體類型
	if vk != reflect.Ptr && v.Elem().Kind() == reflect.Struct {
		fmt.Println("expect struct")
		return
	}
	//更改屬性值
	v.Elem().Field(0).SetString(name)
	//獲取結(jié)構(gòu)體中每個屬性
	for i := 0; i < v.Elem().NumField(); i++ {
		//輸出屬性值
		fmt.Printf("%d %v\n", i, v.Elem().Field(i))
		//輸出屬性值的類型
		fmt.Printf("%d %v\n", i, v.Elem().Field(i).Kind())
	}
}

func main() {
	var stu Student = Student{
		Name:  "張三",
		Age:   18,
		Score: 88,
	}
	Test(&stu, "李四")
}

輸出結(jié)果如下

0 李四
0 string
1 18
1 int
2 88
2 float32

4.4 Tag原信息處理

package main

import (
	"encoding/json"
	"fmt"
	"reflect"
)

type Student struct {
	Name  string `json:"stu_name"`
	Age   int
	Score float32
}

func Test(i interface{}, name string) {
	v := reflect.ValueOf(i)
	vk := v.Kind()
	//判斷是都為指針并指向結(jié)構(gòu)體類型
	if vk != reflect.Ptr && v.Elem().Kind() == reflect.Struct {
		fmt.Println("expect struct")
		return
	}
	//更改屬性值
	v.Elem().Field(0).SetString(name)
	//獲取結(jié)構(gòu)體中每個屬性
	for i := 0; i < v.Elem().NumField(); i++ {
		//輸出屬性值
		fmt.Printf("%d %v\n", i, v.Elem().Field(i))
		//輸出屬性值的類型
		fmt.Printf("%d %v\n", i, v.Elem().Field(i).Kind())
	}
}

func main() {
	var stu Student = Student{
		Name:  "張三",
		Age:   18,
		Score: 88,
	}
	Test(&stu, "李四")
	fmt.Println("----------------json原信息----------------")
	result, _ := json.Marshal(stu)
	fmt.Println("json原信息: ", string(result))
	//反射獲取類型
	st := reflect.TypeOf(stu)
	s := st.Field(0)
	fmt.Printf("Name原信息名稱: %s\n", s.Tag.Get("json"))
}

輸出結(jié)果如下

0 李四
0 string
1 18
1 int
2 88
2 float32
----------------json原信息----------------
json原信息:  {"stu_name":"李四","Age":18,"Score":88}
Name原信息名稱: stu_name

5. 函數(shù)反射

Go 中函數(shù)是可以賦值給變量的

示例:

既然函數(shù)可以像普通的類型變量一樣,那么在反射機(jī)制中就和不同的變量是一樣的,在反射中函數(shù)和方法的類型(Type)都是reflect.Func,如果要調(diào)用函數(shù),通過 Value 的Call() 方法

package main

import (
	"fmt"
	"reflect"
)

func hello() {
	fmt.Println("hello world")
}

func main() {
	//反射使用函數(shù)
	v := reflect.ValueOf(hello)
	//類型判斷是否屬于reflect.func類型
	if v.Kind() == reflect.Func {
		fmt.Println("函數(shù)")
	}
	//反射調(diào)用函數(shù)
	v.Call(nil)   //Call中需要傳入的是切片
}

輸出結(jié)果如下

函數(shù)
hello world

package main

import (
	"fmt"
	"reflect"
	"strconv"
)

//反射調(diào)用傳參和返回值函數(shù)
func Test(i int) string {
	return strconv.Itoa(i)
}

func main() {
	v := reflect.ValueOf(Test)
	//定義參數(shù)切片
	params := make([]reflect.Value, 1)
	//切片元素賦值
	params[0] = reflect.ValueOf(20)
	//反射調(diào)函數(shù)
	result := v.Call(params)
	fmt.Printf("result的類型是 %T\n", result)
	//[]reflect.Value切片轉(zhuǎn)換string
	s := result[0].Interface().(string)
	fmt.Printf("s的類型是 %T ,值為 %s\n", s, s)
}

輸出結(jié)果如下

result的類型是 []reflect.Value
s的類型是 string ,值為 20

6. 方法反射

反射中方法的調(diào)用,函數(shù)和方法可以說其實(shí)本質(zhì)上是相同的,只不過方法與一個“對象”進(jìn)行了“綁定”,方法是“對象”的一種行為,這種行為是對于這個“對象”的一系列操作,例如修改“對象”的某個屬性

6.1 使用 MethodByName 名稱調(diào)用方法

package main

import (
	"fmt"
	"reflect"
	"strconv"
)

//反射方法
type Student struct {
	Name string
	Age  int
}

//結(jié)構(gòu)體方法
func (s *Student) SetName(name string) {
	s.Name = name
}

func (s *Student) SetAge(age int) {
	s.Age = age
}

func (s *Student) String() string {
	return fmt.Sprintf("%p", s) + ",Name:" + s.Name + ",Age:" + strconv.Itoa(s.Age)
}

func main() {
	//實(shí)例化
	stu := &Student{"張三", 19}
	//反射獲取值:指針方式
	stuV := reflect.ValueOf(&stu).Elem()
	fmt.Println("修改前: ", stuV.MethodByName("String").Call(nil)[0])
	//修改值
	params := make([]reflect.Value, 1)		//定義切片
	params[0] = reflect.ValueOf("李四")
	stuV.MethodByName("SetName").Call(params)
	params[0] = reflect.ValueOf(20)
	stuV.MethodByName("SetAge").Call(params)
	fmt.Println("修改后: ", stuV.MethodByName("String").Call(nil)[0])
}

輸出結(jié)果如下

修改前:  0xc000004078,Name:張三,Age:19
修改后:  0xc000004078,Name:李四,Age:20

6.2 使用 method 索引調(diào)用方法

package main

import (
	"fmt"
	"reflect"
	"strconv"
)

//反射方法
type Student struct {
	Name string
	Age  int
}

//結(jié)構(gòu)體方法
func (s *Student) B(name string) {
	s.Name = name
}

func (s *Student) A(age int) {
	s.Age = age
}

func (s *Student) C() string {
	return fmt.Sprintf("%p", s) + ",Name:" + s.Name + ",Age:" + strconv.Itoa(s.Age)
}

func main() {
	//實(shí)例化
	stu := &Student{"張三", 19}
	//反射獲取值:指針方式
	stuV := reflect.ValueOf(&stu).Elem()

	//索引調(diào)用方法
	fmt.Println("修改前: ", stuV.Method(2).Call(nil)[0])

	params := make([]reflect.Value, 1)
	params[0] = reflect.ValueOf("李四")
	stuV.Method(1).Call(params)

	params[0] = reflect.ValueOf(20)
	stuV.Method(0).Call(params)
	fmt.Println("修改后: ", stuV.Method(2).Call(nil)[0])
	//調(diào)用索引大小取決于方法名稱的ASCII大小進(jìn)行排序
}

輸出結(jié)果如下

修改前:  0xc000004078,Name:張三,Age:19
修改后:  0xc000004078,Name:李四,Age:20

到此這篇關(guān)于Go語言學(xué)習(xí)之反射的用法詳解的文章就介紹到這了,更多相關(guān)Go語言反射內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解Go語言中的內(nèi)存對齊

    詳解Go語言中的內(nèi)存對齊

    前面我們學(xué)習(xí)了Go語言空結(jié)構(gòu)體詳解,最近又在看unsafe包的知識,在查閱相關(guān)資料時不免會看到內(nèi)存對齊相關(guān)的內(nèi)容。雖然不會,但可以學(xué)呀,那么這篇文章,我們就一起來看下什么是內(nèi)存對齊吧
    2022-10-10
  • 關(guān)于go get 下載第三方包存儲路徑問題

    關(guān)于go get 下載第三方包存儲路徑問題

    這篇文章主要介紹了關(guān)于go get 下載第三方包存儲路徑問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • golang中defer的關(guān)鍵特性示例詳解

    golang中defer的關(guān)鍵特性示例詳解

    defer是golang語言中的關(guān)鍵字,用于資源的釋放,會在函數(shù)返回之前進(jìn)行調(diào)用。下面這篇文章主要給大家介紹了關(guān)于golang中defer的關(guān)鍵特性,文中通過示例代碼介紹的非常詳細(xì),對大家具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧。
    2017-08-08
  • 詳解Golang語言中的interface

    詳解Golang語言中的interface

    這篇文章主要介紹了Golang語言中的interface的相關(guān)資料,幫助大家更好的理解和使用golang,感興趣的朋友可以了解下
    2021-01-01
  • win7下配置GO語言環(huán)境 + eclipse配置GO開發(fā)

    win7下配置GO語言環(huán)境 + eclipse配置GO開發(fā)

    這篇文章主要介紹了win7下配置GO語言環(huán)境 + eclipse配置GO開發(fā),需要的朋友可以參考下
    2014-10-10
  • Go中使用gjson來操作JSON數(shù)據(jù)的實(shí)現(xiàn)

    Go中使用gjson來操作JSON數(shù)據(jù)的實(shí)現(xiàn)

    本文主要介紹了Go中使用gjson來操作JSON數(shù)據(jù),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • Golang通脈之方法詳情

    Golang通脈之方法詳情

    這篇文章主要介紹了Golang通脈方法,Go語言中的方法(Method)是一種作用于特定類型變量的函數(shù)。這種特定類型變量叫做接收者(Receiver)。接收者的概念就類似于,其他語言中的this或者 self,具體內(nèi)容請和小編一起來學(xué)習(xí)下面文章內(nèi)容吧
    2021-10-10
  • Go語言web快速開發(fā)框架Gin的HttpRouter路由的使用

    Go語言web快速開發(fā)框架Gin的HttpRouter路由的使用

    in框架內(nèi)部使用了高性能的路由器庫httprouter,支持動態(tài)參數(shù)匹配和簡潔的接口,本文主要介紹了Go語言web快速開發(fā)框架Gin的HttpRouter路由的使用,感興趣的可以了解一下
    2025-03-03
  • 重學(xué)Go語言之如何使用Redis

    重學(xué)Go語言之如何使用Redis

    Redis是我們開發(fā)應(yīng)用程序中很常用的NoSQL數(shù)據(jù)庫,那么在Go語言中要如何連接和操作Redis呢,在這篇文章中,我們就來一起來探究一下吧
    2023-08-08
  • Go語言遍歷map實(shí)現(xiàn)(訪問map中的每一個鍵值對)

    Go語言遍歷map實(shí)現(xiàn)(訪問map中的每一個鍵值對)

    這篇文章主要介紹了Go語言遍歷map實(shí)現(xiàn)(訪問map中的每一個鍵值對),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01

最新評論

鹿泉市| 东辽县| 永清县| 兴海县| 商水县| 巴林右旗| 阳江市| 延寿县| 永宁县| 手游| 青神县| 和龙市| 惠东县| 靖边县| 大丰市| 黄平县| 安平县| 沧州市| 璧山县| 白水县| 抚宁县| 宿松县| 象山县| 枣阳市| 榆中县| 新兴县| 如东县| 南部县| 建平县| 鹤岗市| 岑溪市| 黔江区| 娱乐| 柞水县| 理塘县| 渝中区| 木兰县| 绵阳市| 吉木萨尔县| 舟曲县| 青铜峡市|