Go 18.0 专业五


03. 反射

<h1>1. 反射</h1> <p>反射是指在程序运行期对程序本身进行访问和修改的能力</p> <h3>1.1.1. 变量的内在机制</h3> <ul> <li>变量包含类型信息和值信息 var arr [10]int arr[0] = 10</li> <li>类型信息:是静态的元信息,是预先定义好的</li> <li>值信息:是程序运行过程中动态改变的</li> </ul> <h3>1.1.2. 反射的使用</h3> <ul> <li>reflect包封装了反射相关的方法</li> <li>获取类型信息:reflect.TypeOf,是静态的</li> <li>获取值信息:reflect.ValueOf,是动态的</li> </ul> <h3>1.1.3. 空接口与反射</h3> <ul> <li>反射可以在运行时动态获取程序的各种详细信息</li> <li> <p>反射获取interface类型信息</p> <p>package main</p> <p>import ( &quot;fmt&quot; &quot;reflect&quot; )</p> <p>//反射获取interface类型信息</p> <p>func reflect_type(a interface{}) { t := reflect.TypeOf(a) fmt.Println(&quot;类型是:&quot;, t) // kind()可以获取具体类型 k := t.Kind() fmt.Println(k) switch k { case reflect.Float64: fmt.Printf(&quot;a is float64\n&quot;) case reflect.String: fmt.Println(&quot;string&quot;) } }</p> <p>func main() { var x float64 = 3.4 reflect_type(x) }</p> </li> <li> <p>反射获取interface值信息</p> <p>package main</p> <p>import ( &quot;fmt&quot; &quot;reflect&quot; )</p> <p>//反射获取interface值信息</p> <p>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(&quot;a是:&quot;, v.Float()) } }</p> <p>func main() { var x float64 = 3.4 reflect_value(x) }</p> </li> <li> <p>反射修改值信息</p> <p>package main</p> <p>import ( &quot;fmt&quot; &quot;reflect&quot; )</p> <p>//反射修改值 func reflect_set_value(a interface{}) { v := reflect.ValueOf(a) k := v.Kind() switch k { case reflect.Float64: // 反射修改值 v.SetFloat(6.9) fmt.Println(&quot;a is &quot;, v.Float()) case reflect.Ptr: // Elem()获取地址指向的值 v.Elem().SetFloat(7.9) fmt.Println(&quot;case:&quot;, v.Elem().Float()) // 地址 fmt.Println(v.Pointer()) } }</p> <p>func main() { var x float64 = 3.4 // 反射认为下面是指针类型,不是float类型 reflect_set_value(&amp;x) fmt.Println(&quot;main:&quot;, x) }</p> </li> </ul> <h3>1.1.4. 结构体与反射</h3> <p>查看类型、字段和方法</p> <pre><code>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 &lt; 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 &lt; t.NumMethod(); i++ { m := t.Method(i) fmt.Println(m.Name) fmt.Println(m.Type) } } func main() { u := User{1, "zs", 20} Poni(u) }</code></pre> <p>查看匿名字段</p> <pre><code>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)) }</code></pre> <p>修改结构体的值</p> <pre><code>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(&amp;u) fmt.Println(u) }</code></pre> <p>调用方法</p> <pre><code>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) }</code></pre> <p>获取字段的tag</p> <pre><code>package main import ( "fmt" "reflect" ) type Student struct { Name string `json:"name1" db:"name2"` } func main() { var s Student v := reflect.ValueOf(&amp;s) // 类型 t := v.Type() // 获取字段 f := t.Elem().Field(0) fmt.Println(f.Tag.Get("json")) fmt.Println(f.Tag.Get("db")) }</code></pre> <h3>1.1.5. 反射练习</h3> <ul> <li>任务:解析如下配置文件 <ul> <li>序列化:将结构体序列化为配置文件数据并保存到硬盘</li> <li>反序列化:将配置文件内容反序列化到程序的结构体</li> </ul></li> <li> <p>配置文件有server和mysql相关配置</p> <h1>this is comment</h1> <p>;this a comment ;[]表示一个section [server] ip = 10.238.2.2 port = 8080</p> <p>[mysql] username = root passwd = admin database = test host = 192.168.10.10 port = 8000 timeout = 1.2</p> </li> </ul> <p>代码地址:<a href="https://github.com/lu569368/Practise_reflex.git"><a href="https://github.com/lu569368/Practise\_reflex.git">https://github.com/lu569368/Practise\_reflex.git</a></a></p>

页面列表

ITEM_HTML