Files
interview/questions/13-Golang语言/go-reflect-unsafe.md
yasinshaw ab3a99f131 feat: add 10 Golang interview questions
Added comprehensive Golang interview preparation materials:
- 基础语法(值类型、切片、map、defer、接口、struct、new/make)
- Goroutine 和并发模型(与线程对比、调度模型、内存模型)
- 错误处理和测试(error、panic/recover、单元测试、Benchmark)
- 并发编程进阶(Mutex、RWMutex、WaitGroup、atomic、数据竞争)
- HTTP 和 Web 开发(Client、Server、中间件模式)
- 内存模型和垃圾回收(内存分配、逃逸分析、GC)
- 性能优化(pprof、内存优化、CPU优化、并发优化)
- 反射和 unsafe(反射性能、unsafe 使用场景)
- 接口和类型系统(类型断言、interface{}、类型嵌入、泛型)
- 数据库操作(database/sql、GORM、事务、SQL 注入防护)
- 项目结构和工程化(标准项目结构、Go Module、CI/CD)

Each file includes:
- Detailed questions and comprehensive answers
- Code examples and best practices
- Alibaba P7 level requirements

Total: 60 interview questions (50 backend + 10 Golang)

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

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

215 lines
3.8 KiB
Markdown
Raw 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高性能、零拷贝
- 理解如何权衡安全性和性能