当前位置: 首页 > news >正文

golang panic原理

数据结构与底层实现

Goroutine结构体

stack(栈内存范围)
结构体类型,包含 lo(低地址)和 hi(高地址)两个 uintptr 字段,描述 Goroutine 的栈内存区间 [lo, hi)。初始栈大小为 2KB,可动态扩容至 1GB。

m(Machine 绑定)
指向当前运行此 Goroutine 的内核线程(M)。调度器通过 M 将 Goroutine 映射到操作系统线程。

_panic 和 _defer(异常与延迟调用链)

  • _panic:指向当前最内层的 panic 结构体链表,处理异常传播。
  • _defer:指向延迟调用(defer)链表,按后进先出(LIFO)顺序执行清理操作。
type g struct {// Stack parameters.// stack describes the actual stack memory: [stack.lo, stack.hi).// stackguard0 is the stack pointer compared in the Go stack growth prologue.// It is stack.lo+StackGuard normally, but can be StackPreempt to trigger a preemption.// stackguard1 is the stack pointer compared in the //go:systemstack stack growth prologue.// It is stack.lo+StackGuard on g0 and gsignal stacks.// It is ~0 on other goroutine stacks, to trigger a call to morestackc (and crash).stack       stack   // offset known to runtime/cgostackguard0 uintptr // offset known to liblinkstackguard1 uintptr // offset known to liblink_panic    *_panic // innermost panic - offset known to liblink_defer    *_defer // innermost deferm         *m      // current m; offset known to arm liblinksched     gobuf......
}

panic结构体

从上述Goroutine结构体的定义,我们可以发现每一个Goroutine维护一个panic的链表,panic存储在栈上。

// _panic 保存了一个活跃的 panic 信息。// _panic 的值必须仅存在于栈上。// argp 和 link 字段是栈指针,但在栈增长时无需特殊处理:
// 由于它们是指针类型且 _panic 值仅存在于栈上,
// 常规的栈指针调整机制会自动处理这些字段。
type _panic struct {argp unsafe.Pointer // pointer to arguments of deferred call run during panic; cannot move - known to liblinkarg  any            // argument to paniclink *_panic        // link to earlier panic// startPC and startSP track where _panic.start was called.startPC uintptrstartSP unsafe.Pointer// The current stack frame that we're running deferred calls for.sp unsafe.Pointerlr uintptrfp unsafe.Pointer// retpc stores the PC where the panic should jump back to, if the// function last returned by _panic.next() recovers the panic.retpc uintptr// Extra state for handling open-coded defers.deferBitsPtr *uint8slotsPtr     unsafe.Pointerrecovered   bool // whether this panic has been recoveredgoexit      booldeferreturn bool
}

注意事项

golang中每个goroutine维护自己的panic信息,并不是全局的,所以,如果需要捕获panic信息需要在每个goroutine中处理。

所以,在下面的这个案例中recover不能捕获到panic信息。如果需要捕获到,需要在每个协程中都执行recover的逻辑。

func main() {defer func() {if r := recover(); r != nil {log.Printf("Recovered from panic: %v", r)os.Exit(1)}}()// 业务代码...go func() {testPanic()}()time.Sleep(1 * time.Second)
}

http://www.lryc.cn/news/539727.html

相关文章:

  • scratch猜年龄互动小游戏 2024年12月scratch四级真题 中国电子学会 图形化编程 scratch四级真题和答案解析
  • 【Elasticsearch】查询规则_query_rules
  • Git备忘录(三)
  • 用户的声音 | 文档结构化信息提取方案测评:LLM、开源模型部署与云端API,谁是合适选择?
  • vite调试node_modules下面插件
  • ES12 weakRefs的用法和使用场景
  • 【Python】集合set详细讲解(语法、操作、集合运算、性能、使用场景)
  • 网络安全大数据架构 网络安全之数据安全
  • (前端基础)CSS(一)
  • Redis数据类型全景解析:从底层编码到应用反模式
  • (蓝桥杯——10. 小郑做志愿者)洛斯里克城志愿者问题详解
  • TypeScript跟js,es6这些的区别
  • flink-cdc同步数据到doris中
  • Kubernetes:EKS 中 Istio Ingress Gateway 负载均衡器配置及常见问题解析
  • Golang教程
  • AI 百炼成神:线性回归,预测房价
  • 企业软件合规性管理:构建高效、安全的软件资产生态
  • 每日一题——编辑距离
  • TensorFlow项目GPU运行 安装步骤
  • c++进阶———继承
  • FreeSwitch的mod_translate模块详细,附带场景案例及代码示例
  • 前端504错误分析
  • 在 .NET 8/9 中使用 AppUser 进行 JWT 令牌身份验证
  • 基于python实现机器学习的心脏病预测系统
  • 使用 NVM 随意切换 Node.js 版本
  • 【Prometheus】prometheus结合pushgateway实现脚本运行状态监控
  • SpringBoot 项目配置动态数据源
  • CSS基本选择器
  • idea-代码补全快捷键
  • 基于SpringBoot+vue粮油商城小程序系统