# 39 反射(Reflection)

Go是一门静态类型语言，绝大多数情况下，变量的类型在编译时就是已知的。

一种例外是接口类型，尤其是空接口`interface{}`。

空接口是一个动态类型，跟Java或C#里的`Object`类似。

在编译时，我们无法分辨接口类型的底层值是一个`int`还是`string`。

标准库中的[Reflect](https://golang.org/pkg/reflect/)包使得我们能够在运行时处理这些动态值。我们可以：

* 检查动态值的类型
* 枚举`struct`的字段
* 为字段设置值
* 在运行时创建一个新值

用于在运行时检查接口值的类型的相关语言级功能是[类型转换](/essential-go/12-empty-interface.md#lei-xing-jiao-huan-ji-type-switch)和[类型断言](/essential-go/12-empty-interface.md#lei-xing-duan-yan-type-assertion)。

```go
package main

import (
	"fmt"
	"reflect"
)

func main() {
	var v interface{} = 4
	var reflectVal reflect.Value = reflect.ValueOf(v)

	var typ reflect.Type = reflectVal.Type()
	fmt.Printf("Type '%s' of size: %d bytes\n", typ.Name(), typ.Size())
	if typ.Kind() == reflect.Int {
		fmt.Printf("v contains value of type int\n")
	}
}

// -----OUTPUT-------
// Type 'int' of size: 8 bytes
// v contains value of type int
```

上述代码是反射的基本操作：

* 从一个空接口(`interface{}`)类型的值开始
* 使用`reflect.ValueOf(v interface{})`去得到`reflect.Value`类型的变量，它表示关于该值的信息
* 使用`reflect.Value`去检查值的类型、值是否为`nil`、设置新的值

反射有[几个实际用途](/essential-go/common-standard-libraries/39-reflection/uses-for-reflection.md)。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://denglj.gitbook.io/essential-go/common-standard-libraries/39-reflection.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
