go语言之行--接口(interface)、反射(reflect)详解

前端之家收集整理的这篇文章主要介绍了go语言之行--接口(interface)、反射(reflect)详解前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

一、interface简介

interface(接口)是golang最重要的特性之一,Interface类型可以定义一组方法,但是这些不需要实现。并且interface不能包含任何变量。

简单的说:

  • interface是方法的集合
  • interface是一种类型,并且是指针类型
  • interface的更重要的作用在于多态实现

interface定义

type 接口名称

interface使用

  • 接口的使用不仅仅针对结构体,自定义类型、变量等等都可以实现接口。
  • 如果一个接口没有任何方法,我们称为空接口,由于空接口没有方法,所以任何类型都实现了空接口。
  • 要实现一个接口,必须实现该接口里面的所有方法
import <span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"

<span style="color: #008000;">//<span style="color: #008000;">定义接口
type Skills <span style="color: #0000ff;">interface<span style="color: #000000;"> {
Running()
Getname() <span style="color: #0000ff;">string<span style="color: #000000;">

}

type Student <span style="color: #0000ff;">struct<span style="color: #000000;"> {
Name <span style="color: #0000ff;">string<span style="color: #000000;">
Age <span style="color: #0000ff;">int<span style="color: #000000;">
}

<span style="color: #008000;">//<span style="color: #008000;"> 实现接口
func (p Student) Getname() <span style="color: #0000ff;">string{ <span style="color: #008000;">//<span style="color: #008000;">实现Getname方法
<span style="color: #000000;"> fmt.Println(p.Name )
<span style="color: #0000ff;">return<span style="color: #000000;"> p.Name
}

func (p Student) Running() { <span style="color: #008000;">//<span style="color: #008000;"> 实现 Running方法
fmt.Printf(<span style="color: #800000;">"<span style="color: #800000;">%s running<span style="color: #800000;">"<span style="color: #000000;">,p.Name)
}
func main() {
<span style="color: #0000ff;">var<span style="color: #000000;"> skill Skills
<span style="color: #0000ff;">var<span style="color: #000000;"> stu1 Student
stu1.Name = <span style="color: #800000;">"<span style="color: #800000;">wd<span style="color: #800000;">"<span style="color: #000000;">
stu1.Age = <span style="color: #800080;">22<span style="color: #000000;">
skill =<span style="color: #000000;"> stu1
skill.Running() <span style="color: #008000;">//<span style="color: #008000;">调用接口
<span style="color: #000000;">}

<span style="color: #008000;">//<span style="color: #008000;">wd running

多态

上面提到了,go语言中interface是实现多态的一种形式,所谓多态,就是一种事物的多种形态,与python中类的多态是一致的。

同一个interface,不同的类型实现,都可以进行调用,它们都按照统一接口进行操作。

在上面的示例中,我们增加一个Teacher结构体,同样实现接口进行说明:

import <span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"<span style="color: #000000;">

type Skills <span style="color: #0000ff;">interface<span style="color: #000000;"> {
Running()
Getname() <span style="color: #0000ff;">string<span style="color: #000000;">

}

type Student <span style="color: #0000ff;">struct<span style="color: #000000;"> {
Name <span style="color: #0000ff;">string<span style="color: #000000;">
Age <span style="color: #0000ff;">int<span style="color: #000000;">
}

type Teacher <span style="color: #0000ff;">struct<span style="color: #000000;"> {
Name <span style="color: #0000ff;">string<span style="color: #000000;">
Salary <span style="color: #0000ff;">int<span style="color: #000000;">
}

func (p Student) Getname() <span style="color: #0000ff;">string{ <span style="color: #008000;">//<span style="color: #008000;">实现Getname方法
<span style="color: #000000;"> fmt.Println(p.Name )
<span style="color: #0000ff;">return<span style="color: #000000;"> p.Name
}

func (p Student) Running() { <span style="color: #008000;">//<span style="color: #008000;"> 实现 Running方法
fmt.Printf(<span style="color: #800000;">"<span style="color: #800000;">%s running<span style="color: #800000;">"<span style="color: #000000;">,p.Name)
}

func (p Teacher) Getname() <span style="color: #0000ff;">string{ <span style="color: #008000;">//<span style="color: #008000;">实现Getname方法
<span style="color: #000000;"> fmt.Println(p.Name )
<span style="color: #0000ff;">return<span style="color: #000000;"> p.Name
}

func (p Teacher) Running() { <span style="color: #008000;">//<span style="color: #008000;"> 实现 Running方法
fmt.Printf(<span style="color: #800000;">"<span style="color: #800000;">\n%s running<span style="color: #800000;">"<span style="color: #000000;">,p.Name)
}
func main() {
<span style="color: #0000ff;">var<span style="color: #000000;"> skill Skills
<span style="color: #0000ff;">var<span style="color: #000000;"> stu1 Student
<span style="color: #0000ff;">var<span style="color: #000000;"> t1 Teacher
t1.Name = <span style="color: #800000;">"<span style="color: #800000;">wang<span style="color: #800000;">"<span style="color: #000000;">
stu1.Name = <span style="color: #800000;">"<span style="color: #800000;">wd<span style="color: #800000;">"<span style="color: #000000;">
stu1.Age = <span style="color: #800080;">22<span style="color: #000000;">
skill =<span style="color: #000000;"> stu1
skill.Running()
skill =<span style="color: #000000;"> t1
t1.Running()
}
<span style="color: #008000;">//<span style="color: #008000;">wd running
<span style="color: #008000;">//<span style="color: #008000;">wang running

接口嵌套

go语言中的接口可以嵌套,可以理解我继承,子接口拥有父接口的所有方法,并且想要使用该子接口的话,必须将父接口和子接口的所有方法都实现。

type Skills }

type Test <span style="color: #0000ff;">interface<span style="color: #000000;"> {
sleeping()
Skills <span style="color: #008000;">//<span style="color: #008000;">继承Skills
}

类型转换

由于接口是一般类型,当我们使用接口时候可能不知道它是那个类型实现的,基本数据类型我们有对应的方法进行类型转换,当然接口类型也有类型转换。

当然我们也可以用这个方式来进行类型的判断。

转换方式:

s x x =<span style="color: #000000;"> s
y,ok :
= x.(<span style="color: #0000ff;">int
) <span style="color: #008000;">//
<span style="color: #008000;">将interface 转为int,ok可省略 但是省略以后转换失败会报错,true转换成功,false转换失败,并采用默认值

示例:

import <span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"<span style="color: #000000;">

func main() {
<span style="color: #0000ff;">var x <span style="color: #0000ff;">interface<span style="color: #000000;">{}

s :</span>= <span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;WD</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;
x </span>=<span style="color: #000000;"&gt; s
y,ok :</span>= x.(<span style="color: #0000ff;"&gt;int</span><span style="color: #000000;"&gt;)
z,ok1 :</span>= x.(<span style="color: #0000ff;"&gt;string</span><span style="color: #000000;"&gt;)
fmt.Println(y,ok)
fmt.Println(z,ok1)

}
<span style="color: #008000;">//<span style="color: #008000;">0 false
<span style="color: #008000;">//<span style="color: #008000;">WD true

判断类型示例:

import <span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"<span style="color: #000000;">

type Student <span style="color: #0000ff;">struct<span style="color: #000000;"> {
Name <span style="color: #0000ff;">string<span style="color: #000000;">
}

func TestType(items ...<span style="color: #0000ff;">interface<span style="color: #000000;">{}) {
<span style="color: #0000ff;">for k,v :=<span style="color: #000000;"> range items {
<span style="color: #0000ff;">switch<span style="color: #000000;"> v.(type) {
<span style="color: #0000ff;">case <span style="color: #0000ff;">string<span style="color: #000000;">:
fmt.Printf(<span style="color: #800000;">"<span style="color: #800000;">type is string,%d[%v]\n<span style="color: #800000;">"<span style="color: #000000;">,k,v)
<span style="color: #0000ff;">case <span style="color: #0000ff;">bool<span style="color: #000000;">:
fmt.Printf(<span style="color: #800000;">"<span style="color: #800000;">type is bool,v)
<span style="color: #0000ff;">case <span style="color: #0000ff;">int<span style="color: #000000;">:
fmt.Printf(<span style="color: #800000;">"<span style="color: #800000;">type is int,v)
<span style="color: #0000ff;">case<span style="color: #000000;"> float32,float64:
fmt.Printf(<span style="color: #800000;">"<span style="color: #800000;">type is float,v)
<span style="color: #0000ff;">case<span style="color: #000000;"> Student:
fmt.Printf(<span style="color: #800000;">"<span style="color: #800000;">type is Student,v)
<span style="color: #0000ff;">case *<span style="color: #000000;">Student:
fmt.Printf(<span style="color: #800000;">"<span style="color: #800000;">type is Student,%d[%p]\n<span style="color: #800000;">"<span style="color: #000000;">,v)
}
}
}

func main() {
<span style="color: #0000ff;">var<span style="color: #000000;"> stu Student
TestType(<span style="color: #800000;">"<span style="color: #800000;">WD<span style="color: #800000;">",<span style="color: #800080;">100,stu,<span style="color: #800080;">3.3<span style="color: #000000;">)
}
<span style="color: #008000;">//<span style="color: #008000;">type is string,0[WD]
<span style="color: #008000;">//<span style="color: #008000;">type is int,1[100]
<span style="color: #008000;">//<span style="color: #008000;">type is Student,2[{}]
<span style="color: #008000;">//<span style="color: #008000;">type is float,3[3.3]

二、反射reflect

反射是程序执行时检查其所拥有的结构。尤其是类型的一种能力。这是元编程的一种形式。它同一时候也是造成混淆的重要来源。

每一个语言的反射模型都不同(同一时候很多语言根本不支持反射,python通过hasattr方法实现)

go语言中的反射通过refect包实现,reflect包实现了运行时反射,允许程序操作任意类型的对象。

在介绍反射之前先说明下reflect包中的两个数据类Type和Value。

Type

Type:Type类型用来表示一个go类型。

不是所有go类型的Type值都能使用所有方法。请参见每个方法的文档获取使用限制。在调用分类限定的方法时,应先使用Kind方法获知类型的分类调用分类不支持方法会导致运行时的panic。

获取Type对象的方法

func TypeOf(i {}) Type

示例:

import (
<span style="color: #800000;">"<span style="color: #800000;">reflect<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"<span style="color: #000000;">
)

func main() {
str := <span style="color: #800000;">"<span style="color: #800000;">wd<span style="color: #800000;">"<span style="color: #000000;">
res_type :=<span style="color: #000000;"> reflect.TypeOf(str)
fmt.Println(res_type) <span style="color: #008000;">//<span style="color: #008000;">string
}

reflect.Type中方法

通用方法

方法 *rtype) String() 获取 t 类型的字符串描述,不要通过 String 来判断两种类型是否一致。 *rtype) Name() 获取 t 类型在其包中定义的名称,未命名类型则返回空字符串。 *rtype) PkgPath() 获取 t 类型所在包的名称,未命名类型则返回空字符串。 *rtype) Kind() reflect.Kind 获取 t 类型的类别。 *rtype) Size() uintptr 获取 t 类型的值在分配内存时的大小,功能和 unsafe.SizeOf 一样。 *rtype) Align() 获取 t 类型的值在分配内存时的字节对齐值。 *rtype) FieldAlign() 获取 t 类型的值作为结构体字段时的字节对齐值。 *rtype) NumMethod() 获取 t 类型的方法数量 *rtype) Method() reflect.Method 获取 t 类型的方法,如果方法不存在,则 panic。 *rtype) MethodByName() (reflect.Method,) 名称获取 t 类型的方法 *rtype) Implements(u reflect.Type) *rtype) ConvertibleTo(u reflect.Type) *rtype) AssignableTo(u reflect.Type) *rtype) Comparable()


 (t *rtype) () reflect.Type 获取元素类型、获取指针所指对象类型,获取接口的动态类型

示例:

import (
<span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">reflect<span style="color: #800000;">"<span style="color: #000000;">
)

type Skills <span style="color: #0000ff;">interface<span style="color: #000000;"> {
reading()
running()
}

type Student <span style="color: #0000ff;">struct<span style="color: #000000;"> {
Name <span style="color: #0000ff;">string<span style="color: #000000;">
Age <span style="color: #0000ff;">int<span style="color: #000000;">

}

func (self Student) runing(){
fmt.Printf(<span style="color: #800000;">"<span style="color: #800000;">%s is running\n<span style="color: #800000;">"<span style="color: #000000;">,self.Name)
}
func (self Student) reading(){
fmt.Printf(<span style="color: #800000;">"<span style="color: #800000;">%s is reading\n<span style="color: #800000;">"<span style="color: #000000;">,self.Name)
}
func main() {
stu1 := Student{Name:<span style="color: #800000;">"<span style="color: #800000;">wd<span style="color: #800000;">",Age:<span style="color: #800080;">22<span style="color: #000000;">}
inf := <span style="color: #0000ff;">new<span style="color: #000000;">(Skills)
stu_type :=<span style="color: #000000;"> reflect.TypeOf(stu1)
inf_type := reflect.TypeOf(inf).Elem() <span style="color: #008000;">//<span style="color: #008000;"> 特别说明,引用类型需要用Elem()获取指针所指的对象类型
fmt.Println(stu_type.String()) <span style="color: #008000;">//<span style="color: #008000;">main.Student
fmt.Println(stu_type.Name()) <span style="color: #008000;">//<span style="color: #008000;">Student
fmt.Println(stu_type.PkgPath()) <span style="color: #008000;">//<span style="color: #008000;">main
fmt.Println(stu_type.Kind()) <span style="color: #008000;">//<span style="color: #008000;">struct
fmt.Println(stu_type.Size()) <span style="color: #008000;">//<span style="color: #008000;">24
fmt.Println(inf_type.NumMethod()) <span style="color: #008000;">//<span style="color: #008000;">2
fmt.Println(inf_type.Method(<span style="color: #800080;">0),inf_type.Method(<span style="color: #800080;">0).Name) <span style="color: #008000;">//<span style="color: #008000;"> {reading main func() 0} reading
fmt.Println(inf_type.MethodByName(<span style="color: #800000;">"<span style="color: #800000;">reading<span style="color: #800000;">")) <span style="color: #008000;">//<span style="color: #008000;">{reading main func() 0} true
<span style="color: #000000;">
}

其他方法

*rtype) Bits() 获取数值类型的位宽,t 必须是整型、浮点型、复数型

<span style="color: #008000;">//<span style="color: #008000;"> 数组
<span style="color: #000000;">
func (t *rtype) Len() <span style="color: #0000ff;">int <span style="color: #008000;">//<span style="color: #008000;"> 获取数组的元素个数


<span style="color: #008000;">//<span style="color: #008000;"> 映射
<span style="color: #000000;">
func (t *rtype) Key() reflect.Type <span style="color: #008000;">//<span style="color: #008000;"> 获取映射的键类型


<span style="color: #008000;">//<span style="color: #008000;"> 通道
<span style="color: #000000;">

func (t *rtype) ChanDir() reflect.ChanDir <span style="color: #008000;">//<span style="color: #008000;"> 获取通道的方向


<span style="color: #008000;">//<span style="color: #008000;"> 结构体
<span style="color: #000000;">

func (t rtype) NumField() <span style="color: #0000ff;">int <span style="color: #008000;">//<span style="color: #008000;"> 获取字段数量
<span style="color: #000000;">
func (t
rtype) Field(<span style="color: #0000ff;">int) reflect.StructField <span style="color: #008000;">//<span style="color: #008000;"> 根据索引获取字段
<span style="color: #000000;">
func (t rtype) FieldByName(<span style="color: #0000ff;">string) (reflect.StructField,<span style="color: #0000ff;">bool) <span style="color: #008000;">//<span style="color: #008000;"> 根据名称获取字段
<span style="color: #000000;">
func (t
rtype) FieldByNameFunc(match func(<span style="color: #0000ff;">string) <span style="color: #0000ff;">bool) (reflect.StructField,<span style="color: #0000ff;">bool) <span style="color: #008000;">//<span style="color: #008000;"> 根据指定的匹配函数 math 获取字段
<span style="color: #000000;">
func (t *rtype) FieldByIndex(index []<span style="color: #0000ff;">int) reflect.StructField <span style="color: #008000;">//<span style="color: #008000;"> 根据索引链获取嵌套字段


<span style="color: #008000;">//<span style="color: #008000;"> 函数
<span style="color: #000000;">

func (t rtype) NumIn() <span style="color: #0000ff;">int <span style="color: #008000;">//<span style="color: #008000;"> 获取函数的参数数量
<span style="color: #000000;">
func (t
rtype) In(<span style="color: #0000ff;">int) reflect.Type <span style="color: #008000;">//<span style="color: #008000;"> 根据索引获取函数的参数信息
<span style="color: #000000;">
func (t rtype) NumOut() <span style="color: #0000ff;">int <span style="color: #008000;">//<span style="color: #008000;"> 获取函数的返回值数量
<span style="color: #000000;">
func (t
rtype) Out(<span style="color: #0000ff;">int) reflect.Type <span style="color: #008000;">//<span style="color: #008000;"> 根据索引获取函数的返回值信息
<span style="color: #000000;">
func (t *rtype) IsVariadic() <span style="color: #0000ff;">bool <span style="color: #008000;">//<span style="color: #008000;"> 判断函数是否具有可变参数。
<span style="color: #008000;">//<span style="color: #008000;"> 如果有可变参数,则 t.In(t.NumIn()-1) 将返回一个切片。

示例:

import (
<span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">reflect<span style="color: #800000;">"<span style="color: #000000;">
)

type Skills <span style="color: #0000ff;">interface<span style="color: #000000;"> {
reading()
running()
}

type Student <span style="color: #0000ff;">struct<span style="color: #000000;"> {
Name <span style="color: #0000ff;">string<span style="color: #000000;">
Age <span style="color: #0000ff;">int<span style="color: #000000;">

}

func (self Student) runing(){
fmt.Printf(<span style="color: #800000;">"<span style="color: #800000;">%s is running\n<span style="color: #800000;">"<span style="color: #000000;">,Age:<span style="color: #800080;">22<span style="color: #000000;">}
stu_type :=<span style="color: #000000;"> reflect.TypeOf(stu1)
fmt.Println(stu_type.NumField()) <span style="color: #008000;">//<span style="color: #008000;">2
fmt.Println(stu_type.Field(<span style="color: #800080;">0)) <span style="color: #008000;">//<span style="color: #008000;">{Name string 0 [0] false}
fmt.Println(stu_type.FieldByName(<span style="color: #800000;">"<span style="color: #800000;">Age<span style="color: #800000;">")) <span style="color: #008000;">//<span style="color: #008000;">{{Age int 16 [1] false} true
}

Value

不是所有go类型值的Value表示都能使用所有方法。请参见每个方法的文档获取使用限制。在调用分类限定的方法时,应先使用Kind方法获知该值的分类调用分类不支持方法会导致运行时的panic。

Value为go值提供了反射接口,获取Value对象方法

func ValueOf(i {}) Value

示例:

str := =

reflect.Value方法

注意:以下所有方法中的v是reflect.Value返回的值。

reflect.Value.Kind():获取变量类别,返回常量

import (
<span style="color: #800000;">"<span style="color: #800000;">reflect<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"<span style="color: #000000;">
)

func main() {
str := <span style="color: #800000;">"<span style="color: #800000;">wd<span style="color: #800000;">"<span style="color: #000000;">
val :=<span style="color: #000000;"> reflect.ValueOf(str).Kind()
fmt.Println(val)<span style="color: #008000;">//<span style="color: #008000;">string
}

用于获取方法

func (v Value) Int() int64 获取int类型值,如果 v 值不是有符号整型,则 panic。 获取unit类型的值,如果 v 值不是无符号整型(包括 uintptr),则 panic。 获取float类型的值,如果 v 值不是浮点型,则 panic。 获取复数类型的值,如果 v 值不是复数型,则 panic。 获取布尔类型的值,如果 v 值不是布尔型,则 panic。 获取 v 值的长度,v 值必须是字符串、数组、切片、映射、通道。 获取 v 值的容量,v 值必须是数值、切片、通道。 ) reflect.Value 获取 v 值的第 i 个元素,v 值必须是字符串、数组、切片,i 不能超出范围。 获取字节类型的值,如果 v 值不是字节切片,则 panic。 ) reflect.Value 获取 v 值的切片,切片长度 = j - i,切片容量 = v.Cap() - i。 ) reflect.Value 获取 v 值的切片,切片长度 = j - i,切片容量 = k - i。 获取 v 值的内容,v 值必须是映射。 获取 v 值的所有键的无序列表,v 值必须是映射。

设置值方法

func (v Value) SetInt(x int64) ) ) ) ) ) 添加

其他方法

func (v Value) NumField() 获取结构体字段(成员)数量 ) reflect.Value 获取结构体字段 ) reflect.Value 获取结构体嵌套字段 ) reflect.Value 名称获取结构体的字段,不存在返回reflect.ValueOf(nil) ) ) Value 函数 match 获取字段,如果没有匹配的字段,则返回零值(reflect.ValueOf(nil))

<span style="color: #008000;">########通道相关:
func (v Value) Send(x reflect.Value)<span style="color: #008000;">//<span style="color: #008000;"> 发送数据(会阻塞),v 值必须是可写通道。
<span style="color: #000000;">
func (v Value) Recv() (x reflect.Value,ok <span style="color: #0000ff;">bool) <span style="color: #008000;">//<span style="color: #008000;"> 接收数据(会阻塞),v 值必须是可读通道。
<span style="color: #000000;">
func (v Value) TrySend(x reflect.Value) <span style="color: #0000ff;">bool <span style="color: #008000;">//<span style="color: #008000;"> 尝试发送数据(不会阻塞),v 值必须是可写通道。
<span style="color: #000000;">
func (v Value) TryRecv() (x reflect.Value,ok <span style="color: #0000ff;">bool) <span style="color: #008000;">//<span style="color: #008000;"> 尝试接收数据(不会阻塞),v 值必须是可读通道。
<span style="color: #000000;">
func (v Value) Close() <span style="color: #008000;">//<span style="color: #008000;"> 关闭通道

<span style="color: #008000;">########函数相关
func (v Value) Call(<span style="color: #0000ff;">in []Value) (r []Value) <span style="color: #008000;">//<span style="color: #008000;"> 通过参数列表 in 调用 v 值所代表的函数(或方法)。函数的返回值存入 r 中返回。
<span style="color: #008000;">//<span style="color: #008000;"> 要传入多少参数就在 in 中存入多少元素。
<span style="color: #008000;">//<span style="color: #008000;"> Call 即可以调用定参函数(参数数量固定),也可以调用变参函数(参数数量可变)。
<span style="color: #000000;">
func (v Value) CallSlice(<span style="color: #0000ff;">in []Value) []Value <span style="color: #008000;">//<span style="color: #008000;"> 调用变参函数

示例一:获取和设置普通类型的值

import (
<span style="color: #800000;">"<span style="color: #800000;">reflect<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"<span style="color: #000000;">
)

func main() {
str := <span style="color: #800000;">"<span style="color: #800000;">wd<span style="color: #800000;">"<span style="color: #000000;">
age := <span style="color: #800080;">11<span style="color: #000000;">
fmt.Println(reflect.ValueOf(str).String()) <span style="color: #008000;">//<span style="color: #008000;">获取str的值,结果wd
fmt.Println(reflect.ValueOf(age).Int()) <span style="color: #008000;">//<span style="color: #008000;">获取age的值,结果age
str2 := reflect.ValueOf(&str) <span style="color: #008000;">//<span style="color: #008000;">获取Value类型
str2.Elem().SetString(<span style="color: #800000;">"<span style="color: #800000;">jack<span style="color: #800000;">") <span style="color: #008000;">//<span style="color: #008000;">设置值
fmt.Println(str2.Elem(),age) <span style="color: #008000;">//<span style="color: #008000;">jack 11
}

示例二:简单结构体操作

import (
<span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">reflect<span style="color: #800000;">"<span style="color: #000000;">
)

type Skills <span style="color: #0000ff;">interface<span style="color: #000000;"> {
reading()
running()
}

type Student <span style="color: #0000ff;">struct<span style="color: #000000;"> {
Name <span style="color: #0000ff;">string<span style="color: #000000;">
Age <span style="color: #0000ff;">int<span style="color: #000000;">

}

func (self Student) runing(){
fmt.Printf(<span style="color: #800000;">"<span style="color: #800000;">%s is running\n<span style="color: #800000;">"<span style="color: #000000;">,Age:<span style="color: #800080;">22<span style="color: #000000;">}
stu_val := reflect.ValueOf(stu1) <span style="color: #008000;">//<span style="color: #008000;">获取Value类型
fmt.Println(stu_val.NumField()) <span style="color: #008000;">//<span style="color: #008000;">2
fmt.Println(stu_val.Field(<span style="color: #800080;">0),stu_val.Field(<span style="color: #800080;">1)) <span style="color: #008000;">//<span style="color: #008000;">wd 22
fmt.Println(stu_val.FieldByName(<span style="color: #800000;">"<span style="color: #800000;">Age<span style="color: #800000;">")) <span style="color: #008000;">//<span style="color: #008000;">22
stu_val2 := reflect.ValueOf(&<span style="color: #000000;">stu1).Elem()
stu_val2.FieldByName(<span style="color: #800000;">"<span style="color: #800000;">Age<span style="color: #800000;">").SetInt(<span style="color: #800080;">33) <span style="color: #008000;">//<span style="color: #008000;">设置字段值 ,结果33
<span style="color: #000000;"> fmt.Println(stu1.Age)

}

示例三:通过反射调用结构体中的方法,通过reflect.Value.Method(i int).Call()或者reflect.Value.MethodByName(name string).Call()实现

import (
<span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">reflect<span style="color: #800000;">"<span style="color: #000000;">
)

type Student <span style="color: #0000ff;">struct<span style="color: #000000;"> {
Name <span style="color: #0000ff;">string<span style="color: #000000;">
Age <span style="color: #0000ff;">int<span style="color: #000000;">
}

func (<span style="color: #0000ff;">this *Student) SetName(name <span style="color: #0000ff;">string<span style="color: #000000;">) {
<span style="color: #0000ff;">this.Name =<span style="color: #000000;"> name
fmt.Printf(<span style="color: #800000;">"<span style="color: #800000;">set name %s\n<span style="color: #800000;">",<span style="color: #0000ff;">this<span style="color: #000000;">.Name )
}

func (<span style="color: #0000ff;">this *Student) SetAge(age <span style="color: #0000ff;">int<span style="color: #000000;">) {
<span style="color: #0000ff;">this.Age =<span style="color: #000000;"> age
fmt.Printf(<span style="color: #800000;">"<span style="color: #800000;">set age %d\n<span style="color: #800000;">"<span style="color: #000000;">,age )
}

func (<span style="color: #0000ff;">this *Student) String() <span style="color: #0000ff;">string<span style="color: #000000;"> {
fmt.Printf(<span style="color: #800000;">"<span style="color: #800000;">this is %s\n<span style="color: #800000;">",<span style="color: #0000ff;">this<span style="color: #000000;">.Name)
<span style="color: #0000ff;">return <span style="color: #0000ff;">this<span style="color: #000000;">.Name
}

func main() {
stu1 := &Student{Name:<span style="color: #800000;">"<span style="color: #800000;">wd<span style="color: #800000;">",Age:<span style="color: #800080;">22<span style="color: #000000;">}
val := reflect.ValueOf(stu1) <span style="color: #008000;">//<span style="color: #008000;">获取Value类型,也可以使用reflect.ValueOf(&stu1).Elem()
val.MethodByName(<span style="color: #800000;">"<span style="color: #800000;">String<span style="color: #800000;">").Call(nil) <span style="color: #008000;">//<span style="color: #008000;">调用String方法

<span style="color: #0000ff;"&gt;params</span> := make([]reflect.Value,<span style="color: #800080;"&gt;1</span><span style="color: #000000;"&gt;)
</span><span style="color: #0000ff;"&gt;params</span>[<span style="color: #800080;"&gt;0</span>] = reflect.ValueOf(<span style="color: #800080;"&gt;18</span><span style="color: #000000;"&gt;)
val.MethodByName(</span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;SetAge</span><span style="color: #800000;"&gt;"</span>).Call(<span style="color: #0000ff;"&gt;params</span>)  <span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt;通过<a href="/tag/mingcheng/" target="_blank" class="keywords">名称</a><a href="/tag/diaoyong/" target="_blank" class="keywords">调用</a><a href="/tag/fangfa/" target="_blank" class="keywords">方法</a></span>

<span style="color: #0000ff;"&gt;params</span>[<span style="color: #800080;"&gt;0</span>] = reflect.ValueOf(<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;jack</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;)   
val.Method(</span><span style="color: #800080;"&gt;1</span>).Call(<span style="color: #0000ff;"&gt;params</span>)    <span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt;通过<a href="/tag/fangfa/" target="_blank" class="keywords">方法</a>索引<a href="/tag/diaoyong/" target="_blank" class="keywords">调用</a></span>

<span style="color: #000000;">
fmt.Println(stu1.Name,stu1.Age)
}
<span style="color: #008000;">//<span style="color: #008000;">this is wd
<span style="color: #008000;">//<span style="color: #008000;">set age 18
<span style="color: #008000;">//<span style="color: #008000;">set name jack
<span style="color: #008000;">//<span style="color: #008000;">jack 18

猜你在找的Go相关文章