反射进阶

在本节中,我们将探讨反射的更高级的用法,将使用相对较小的advRefl.go的Go代码进行演示。

  1. >

package main

import ( “fmt” “os” “reflect” )

type t1 int type t2 int ```

可以注意到尽管t1t2类型都基于int类型,因此本质上也与int类型相同,但Go语言将它们视为完全不同的类型。它们在Go编译器解析后的内部表示分别是main.t1main.t2

  1. >

type a struct { X int Y float64 Text string }

func (a1 a) compareStruct(a2 a) bool { r1 := reflect.ValueOf(&a1).Elem() r2 := reflect.ValueOf(&a2).Elem()

  1. for i := 0; i < r1.NumField(); i++ {
  2. if r1.Field(i).Interface() != r2.Field(i).Interface() {
  3. return false
  4. }
  5. }
  6. return true

} ```

在这个代码段中,我们定义了一个名为a的Go结构类型,并实现了一个名为compareStruct()的Go函数。这个函数的目的是找出类型a的两个变量是否完全相同。如您所见,compareStruct()使用reflection.go中的Go代码来执行其任务。

  1. >

func printMethods(i interface{}) { r := reflect.ValueOf(i) t := r.Type() fmt.Printf(“Type to examine: %s\n”, t)

  1. for j := 0; j < r.NumMethod(); j++ {
  2. m := r.Method(j).Type()
  3. fmt.Println(t.Method(j).Name, "-->", m)
  4. }

} ```

  1. ```advRefl.go```的第四段包含以下Go代码:
  2. >

func main() { x1 := t1(100) x2 := t2(100) fmt.Printf(“The type of x1 is %s\n”, reflect.TypeOf(x1)) fmt.Printf(“The type of x2 is %s\n”, reflect.TypeOf(x2))

  1. var p struct{}
  2. r := reflect.New(reflect.ValueOf(&p).Type()).Elem()
  3. fmt.Printf("The type of r is %s\n", reflect.TypeOf(r))

```

  1. >
  1. a1 := a{1, 2.1, "A1"}
  2. a2 := a{1, -2, "A2"}
  3. if a1.compareStruct(a1) {
  4. fmt.Println("Equal!")
  5. }
  6. if !a1.compareStruct(a2) {
  7. fmt.Println("Not Equal!")
  8. }
  9. var f *os.File
  10. printMethods(f)

} ```

正如您稍后将看到的,a1.compareStruct(a1)调用返回true,因为我们正在比较a1与自身,而a1.compareStruct(a2)调用将返回false,因为a1a2变量的值不同。

执行advRefl.go将得到以下输出:

  1. $ go run advRefl.go
  2. The type of x1 is main.t1
  3. The type of x2 is main.t2
  4. The type of r is reflect.Value
  5. Equal!
  6. Not Equal!
  7. Type to examine: *os.File
  8. Chdir --> func() error
  9. Chmod --> func(os.FileMode) error
  10. Chown --> func(int, int) error
  11. Close --> func() error
  12. Fd --> func() uintptr
  13. Name --> func() string
  14. Read --> func([]uint8) (int, error)
  15. ReadAt --> func([]uint8, int64) (int, error)
  16. Readdir --> func(int) ([]os.FileInfo, error)
  17. Readdirnames --> func(int) ([]string, error)
  18. Seek --> func(int64, int) (int64, error)
  19. Stat --> func() (os.FileInfo, error)
  20. Sync --> func() error
  21. Truncate --> func(int64) error
  22. Write --> func([]uint8) (int, error)
  23. WriteAt --> func([]uint8, int64) (int, error)
  24. WriteString --> func(string) (int, error)

可以看到由reflect.New()返回的r变量的类型是reflect.Value。另外,printMethods()方法的输出可以看到*os.File类型支持很多的方法,例如:Chdir()Chmod()等。