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

3.8 KiB
Raw Blame History

Golang 反射和 unsafe

问题

  1. Go 的反射reflect有什么用
  2. 反射的性能如何?如何优化?
  3. unsafe 包的作用是什么?
  4. 什么场景下需要使用 unsafe
  5. 反射和 unsafe 的最佳实践是什么?

标准答案

1. 反射基础

基本用法

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. 反射的性能

性能对比

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. 缓存反射结果

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. 使用代码生成

# 使用 stringer
//go:generate go run golang.org/x/tools/cmd/stringer -type=User

3. unsafe 包

作用

绕过 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高性能序列化

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字符串转字节零拷贝

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高性能、零拷贝
  • 理解如何权衡安全性和性能