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

Golang学习笔记:后端性能优化秘籍(持续更新)

减少堆对象分配

1.小对象使用结构体而非指针

func createUser() *User {return &User{ID: 1, Name: "Alice"} // 逃逸到堆
}

改成下面的写法编成栈分配,生命周期结束自动回收

func createUser() User {return User{ID: 1, Name: "Alice"} // 栈分配,函数结束后自动回收
}

2.列表对象使用值切片而非指针切片

场景

type User struct {ID      int64Name    stringValue   float64Status  int// 假设总共约 50-100 字节
}// 场景:返回 1000 个 User 对象

值切片内存布局

[ User1 ][ User2 ][ User3 ]... // 连续内存块

一次堆分配,GC只追踪一个对象

指针切片布局

[ ptr1 ][ ptr2 ][ ptr3 ]... → 各自指向堆上的 User 对象

1001次堆分配(切片数组+1000个User对象),内存碎片化,GC需追踪1001个对象

3.参数传递代替闭包捕获

func main() {x := 42go func() {fmt.Println(x) // x 逃逸到堆}()
}
func main() {x := 42go func(val int) {fmt.Println(val) // val 通过值传递,保留在栈上}(x)
}

使用对象池

var pool = sync.Pool{New: func() interface{} { return make([]byte, 1024) },
}
func processRequest() {buf := pool.Get().([]byte) // 从池中获取(可能复用)defer pool.Put(buf)        // 放回池中// 使用 buf...
}

预分配内存

// 未优化:多次扩容
var data []int
for i := 0; i < 1000; i++ {data = append(data, i)  // 可能触发多次堆分配
}

预分配内存,可以避免中途多次触发GC扫描,同时减少数据迁移的开销。

// 优化:单次预分配
data := make([]int, 0, 1000)  // 一次性分配底层数组
for i := 0; i < 1000; i++ {data = append(data, i)    
}

非关键路径异步化处理

对于耗时高的非关键操作,采用异步化操作,避免长时间阻塞主流程。

避免反射

反射需要在运行时动态检查数据类型和创建临时对象(每次reflect.ValueOf()或reflect.TypeOf()调用至少产生1次堆分配)。引入泛型,泛型在编译时期会生成对应类型的代码,运行时无需校验类型和分配临时对象。
性能上:泛型>强制类型转换/断言>反射

字符串拼接

  • strings.Builder性能最高,底层是[]byte,可动态扩容;
  • strings.Join底层是strings.Builder,一次性计算分配内存,性能差不多;
  • +运算符,需要不断创建新的临时对象;
  • fmt.Sprintf(),性能很差,涉及到反射。性能敏感场景避免使用;

工具排查

使用pprof,推荐参考

切片清空

清空切片(如使用 buf[:0] 或重新初始化)是 Go 后端开发中常见的性能优化手段,尤其在高频操作或处理大量数据的场景中,合理清空切片能有效减少内存分配和垃圾回收(GC)压力,提升程序性能。

循环中复用切片(高频操作)

在循环(尤其是高迭代次数的循环)中处理数据时,若每次迭代都需要一个临时切片存储中间结果,复用切片比每次创建新切片更高效。

func processBatch(data [][]byte) {// 预分配一个切片,容量足够容纳单次处理的最大数据量buffer := make([]byte, 0, 1024) for _, item := range data {// 清空切片内容,复用底层数组buffer = buffer[:0]// 填充新数据(如解析 item 到 buffer)buffer = append(buffer, item...)buffer = append(buffer, '\n')// 处理 buffer...}
}

池化资源

在高并发场景中,可结合 sync.Pool 实现切片的池化管理,避免重复创建和销毁切片,进一步提升性能。

var slicePool = sync.Pool{New: func() interface{} {// 初始化一个具有一定容量的切片return make([]int, 0, 100)},
}// 从池获取切片,使用后清空并放回
func getSlice() []int {return slicePool.Get().([]int)
}func putSlice(s []int) {// 清空切片内容,保留容量后放回池s = s[:0]slicePool.Put(s)
}// 高并发场景中使用
func handleRequest() {s := getSlice()defer putSlice(s)// 使用 s 处理请求...s = append(s, 1, 2, 3)
}
http://www.dtcms.com/a/550170.html

相关文章:

  • Easyx图形库应用(基础的AI开发原理)
  • arthas实现类的热部署
  • Rust 注释与文档注释:从代码可读性到 API 文档化的工程实践
  • 取名网站怎么做2022年新闻摘抄十条简短
  • 网站开发工具教程wordpress 关键词获取
  • tensorflow的广播机制
  • MIT-最大连续子序列和(MCS)
  • 深圳市住建局网站官网济南网站建设公司哪家好
  • Kubernetes资源管理全解析
  • 郑州企业型网站建设怎么做可以访问网站
  • 网站制作前必须做的事情有哪些网站行业
  • TC3xx芯片ACCEN寄存器保护详解
  • Linux上如何挂载磁盘
  • 卫星轨道计算中的数值精度陷阱:第三体引力摄动的稳定性优化
  • 白山网站seoe网站的图标怎么做
  • RHSCA---用户和组管理
  • 温州网站域名注册服务公司易语言如何做浏网站
  • 仿糗事百科网站源码dede二次开发分享+评论+互动国外网站域名
  • 仓颉语言中String的内存表示深度解析
  • NetSuite 中自定义基础打印模板的调整方法分享
  • 东城企业网站开发什么网站能免费做简历
  • “调用销毁者置于末尾”原则
  • GRPO相关优化论文
  • Openvins学习---ov_msckf中的State.h
  • 有什么网站可以做数学题项目建设全过程
  • 德庆网站建设良精企业网站管理系统
  • dz网站自己做的模板放在哪里小说网站建设的支柱
  • idea中Docker一键自动化部署
  • faster-whisper热词详解与程序设计
  • 电子电力技术的控制电路学习分享1