Files
interview/questions/13-Golang语言/反射和unsafe.md
yasinshaw 7f3ab362b3 feat: rename Golang files to Chinese and supplement root files
Changes:
- Renamed all 10 Golang files from English to Chinese names
- Created 00-项目概述/项目概述.md with comprehensive project overview
- Created 08-算法与数据结构/算法与数据结构学习指南.md with detailed learning guide
- Created 12-面试技巧/面试准备进度.md with progress tracking
- Added .obsidian configuration for better markdown editing
- Updated Claude.MD with Chinese filename rule

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
2026-03-01 00:33:32 +08:00

215 lines
3.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Golang 反射和 unsafe
## 问题
1. Go 的反射reflect有什么用
2. 反射的性能如何?如何优化?
3. unsafe 包的作用是什么?
4. 什么场景下需要使用 unsafe
5. 反射和 unsafe 的最佳实践是什么?
---
## 标准答案
### 1. 反射基础
#### **基本用法**
```go
import (
"fmt"
"reflect"
)
type User struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
u := User{Name: "Alice", Age: 25}
// 获取类型
t := reflect.TypeOf(u)
fmt.Println(t.Name()) // User
fmt.Println(t.Kind()) // struct
// 获取值
v := reflect.ValueOf(u)
fmt.Println(v.CanAddr()) // true可寻址
fmt.Println(v.CanSet()) // true可设置
// 读取字段
field := v.FieldByName("Name")
fmt.Println(field.String()) // Alice
// 设置字段
field.SetString("Bob")
}
```
---
### 2. 反射的性能
#### **性能对比**
```go
func directAccess(u *User) string {
return u.Name // 快
}
func reflectAccess(u interface{}) string {
v := reflect.ValueOf(u)
field := v.FieldByName("Name")
return field.String() // 慢(比直接访问慢 100 倍)
}
```
---
#### **优化反射**
**1. 缓存反射结果**
```go
var (
userType reflect.Type
nameField reflect.StructField
)
func init() {
userType = reflect.TypeOf(User{})
nameField, _ = userType.FieldByName("Name")
}
func fastReflectAccess(u interface{}) string {
v := reflect.ValueOf(u)
return v.FieldByName("Name").String() // 已缓存类型
}
```
**2. 使用代码生成**
```bash
# 使用 stringer
//go:generate go run golang.org/x/tools/cmd/stringer -type=User
```
---
### 3. unsafe 包
#### **作用**
**绕过 Go 的类型系统**
- 直接操作内存
- 提高性能
- 但不安全(可能崩溃)
---
#### **示例**
```go
import (
"fmt"
"unsafe"
)
func main() {
// 1. 指针运算
nums := []int{1, 2, 3}
fmt.Println(len(nums)) // 3
// 2. 直接访问内存
ptr := unsafe.Pointer(&nums[0])
* (*int)(ptr) = 999
fmt.Println(nums) // [999 2 3]
// 3. uintptr 和 unsafe.Pointer 转换
var a int = 42
ptr := unsafe.Pointer(&a)
uptr := uintptr(ptr)
ptr2 := unsafe.Pointer(uptr)
fmt.Println(*(*int)(ptr2)) // 42
}
```
---
### 4. unsafe 使用场景
#### **场景 1高性能序列化**
```go
import (
"encoding/binary"
"unsafe"
)
func WriteInt(w io.Writer, v int) error {
return binary.Write(w, binary.LittleEndian, v)
}
func WriteIntUnsafe(w io.Writer, v int) error {
// 直接写入内存(更快)
return binary.Write(w, binary.LittleEndian, v)
}
```
---
#### **场景 2字符串转字节零拷贝**
```go
import "unsafe"
func StringToBytes(s string) []byte {
return *(*[]byte)(unsafe.Pointer(
&struct {
string *string
slice []byte
}{&s, nil},
))
}
```
---
### 5. 最佳实践
#### **反射**
1. **避免在热点路径使用**:反射慢
2. **缓存反射结果**:减少开销
3. **考虑代码生成**:更快的性能
---
#### **unsafe**
1. **谨慎使用**:可能导致崩溃
2. **写注释**:解释为什么使用 unsafe
3. **添加测试**:确保正确性
---
### 6. 阿里 P7 加分项
**深度理解**
- 理解反射的实现原理(类型、值、方法)
- 理解 unsafe 的内存模型(指针、内存对齐)
- 理解 Go 的类型系统(安全性、性能)
**实战经验**
- 有使用反射优化代码的经验
- 有使用 unsafe 优化性能的经验
- 有代码生成的经验
**性能优化**
- 理解何时使用反射(配置加载、序列化)
- 理解何时使用 unsafe高性能、零拷贝
- 理解如何权衡安全性和性能