欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

1. reflect 包

類型是變量,類別是常量

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

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

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

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() {
	//類型不同的話會(huì)報(bào)錯(cuò)
	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的地址,否則會(huì)保存,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)用識(shí)別

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)體中每個(gè)屬性
	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)體中每個(gè)屬性
	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)體中每個(gè)屬性
	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ì)上是相同的,只不過方法與一個(gè)“對(duì)象”進(jìn)行了“綁定”,方法是“對(duì)象”的一種行為,這種行為是對(duì)于這個(gè)“對(duì)象”的一系列操作,例如修改“對(duì)象”的某個(gè)屬性

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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 精通Go語言日志記錄高效日志管理

    精通Go語言日志記錄高效日志管理

    本文將深入探討 Go 語言中的日志記錄,包括 Go 的標(biāo)準(zhǔn)日志庫(kù)的使用、流行的第三方日志庫(kù)以及如何在實(shí)際項(xiàng)目中實(shí)現(xiàn)有效的日志管理
    2023-11-11
  • Go語言開發(fā)中redis的使用詳解

    Go語言開發(fā)中redis的使用詳解

    這篇文章主要介紹了Go語言開發(fā)中redis的使用詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-07-07
  • Golang中時(shí)間相關(guān)操作合集

    Golang中時(shí)間相關(guān)操作合集

    這篇文章主要為大家介紹了Golang中的各種時(shí)間相關(guān)操作,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-09-09
  • GO語言延遲函數(shù)defer用法詳解

    GO語言延遲函數(shù)defer用法詳解

    本文主要介紹了GO語言延遲函數(shù)defer用法詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • Go語言實(shí)現(xiàn)的web爬蟲實(shí)例

    Go語言實(shí)現(xiàn)的web爬蟲實(shí)例

    這篇文章主要介紹了Go語言實(shí)現(xiàn)的web爬蟲,實(shí)例分析了web爬蟲的原理與Go語言的實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-02-02
  • Go語言定時(shí)任務(wù)的實(shí)現(xiàn)示例

    Go語言定時(shí)任務(wù)的實(shí)現(xiàn)示例

    本文主要介紹了Go語言定時(shí)任務(wù)的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • docker中部署golang項(xiàng)目的步驟詳解

    docker中部署golang項(xiàng)目的步驟詳解

    這篇文章主要給大家介紹了關(guān)于在docker中部署golang項(xiàng)目的步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-11-11
  • goLang引入自定義包的方法

    goLang引入自定義包的方法

    今天小編就為大家分享一篇goLang引入自定義包的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-06-06
  • Golang10進(jìn)制轉(zhuǎn)16進(jìn)制的幾種方法代碼示例

    Golang10進(jìn)制轉(zhuǎn)16進(jìn)制的幾種方法代碼示例

    這篇文章主要給大家介紹了關(guān)于Golang10進(jìn)制轉(zhuǎn)16進(jìn)制的幾種方法,進(jìn)制轉(zhuǎn)換是Golang的一些基本操作,文中通過實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-07-07
  • 通過Golang編寫一個(gè)AES加密解密工具

    通過Golang編寫一個(gè)AES加密解密工具

    這篇文章主要為大家詳細(xì)介紹了如何利用Golang制作一個(gè)AES加密解密工具,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2022-05-05

最新評(píng)論