Go语言开发小技巧&易错点100例(五)

简介: Go语言开发小技巧&易错点100例(五)


本期看点(技巧类用【技】表示,易错点用【易】表示)

(1)pprof查看运行时状态信息【技】

(2)goruntine使用后的销毁【易】

PS:《Go语言开发小技巧&易错点100例》算上这一篇已经完成了20篇啦!五分之一!继续加油

正文如下:

1 pprof查看运行时状态信息

pprof是Go语言的性能分析工具,主要可以分析以下几种情况:

  • allocs:过去所有内存分配的示例
  • block:导致同步原语阻塞的堆栈跟踪
  • cmdline:当前程序的命令行调用
  • goroutine:当前所有goroutine的堆栈跟踪
  • heap:活动对象的内存分配示例。您可以指定gc GET参数,以便在执行堆样例之前运行gc。
  • mutex:竞争互斥对象持有者的堆栈跟踪
  • profile:CPU profile。可以在seconds GET参数中指定持续时间。获得概要文件后,使用go工具pprof命令来研究概要文件。
  • threadcreate:用于创建新的操作系统线程的堆栈跟踪
  • trace:当前程序执行的跟踪。可以在seconds GET参数中指定持续时间。获得跟踪文件后,使用go工具trace命令来调查跟踪。

运行代码:

package main
import (
   "fmt"
   "net/http"
   _ "net/http/pprof"
   "strings"
)
func main() {
   http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
      writer.Write([]byte("Hello~"))
   })     
   http.ListenAndServe(":9090", nil) 
}

访问链接:http://localhost:9090/debug/pprof/

2 goruntine使用后的销毁

在上节我们学到了如何去控制goruntine的数量,因为短时间内大量的goroutine同时执行也会造成内存崩溃、CPU占用率过高等问题,不仅如此,当goruntine启动后未进行关闭时,因为大量的挤压goroutine也会造成相同的问题,因此我们要习惯在项目中使用goruntine后进行关闭。

2.1 使用后不销毁出现的问题示例

代码示例:

package main
import (
   "fmt"
   "net/http"
   _ "net/http/pprof"
)
func main() {
   ints := make(chan int,1000)
   i := 0
   worker := func (ch chan int){
      for v := range ch {
         fmt.Println(v)
      }
   }
   http.HandleFunc("/go", func(writer http.ResponseWriter, request *http.Request) {
      i+=1
      ints<-i
      go worker(ints)
   })
   http.ListenAndServe(":9090", nil)
}

查看pprof:

我们发现同一个地方我们只go出去一次,但是几次请求后还是有很多goruntine,这样如果大批量请求的话一定会出问题。

2.2 使用后销毁的方式
2.2.1 优化代码逻辑

第一种优化方式,就是换一种方式去监听channel:

package main
import (
   "fmt"
   "net/http"
   _ "net/http/pprof"
)
func main() {
   ints := make(chan int,1000)
   i := 0
   worker := func (ch chan int){
      select {
      case v := <-ch:
         fmt.Println(v)
      default:
         return
      }
   }
   http.HandleFunc("/go", func(writer http.ResponseWriter, request *http.Request) {
      i+=1
      ints<-i
      go worker(ints)
   })
   http.ListenAndServe(":9090", nil)
}
2.2.2 利用channel销毁多余的goruntine

第二种方式,我们可以close掉channel来间接的关闭监听他的goruntine

package main
import (
   "fmt"
   "net/http"
   _ "net/http/pprof"
)
func worker(v ...int) {
   count := len(v)
   res :=make(chan int,count)
   go func (ch chan int){
      for i := 0; i < count; i++ {
         fmt.Println(v[i])
         ch <- v[i]
      }
   }(res)
   for i := 0; i < count; i++ {
      <-res
   }
   close(res)
}
func main() {
   val := 0
   http.HandleFunc("/go", func(writer http.ResponseWriter, request *http.Request) {
      val += 1
      go worker(val)
   })
   http.ListenAndServe(":9090", nil)
}
2.2.3 利用Context销毁多余的goruntine

第三种方式,使用Context机制关闭多余的goruntine

相关文章
|
2天前
|
JavaScript Java Go
探索Go语言在微服务架构中的优势
在微服务架构的浪潮中,Go语言以其简洁、高效和并发处理能力脱颖而出。本文将深入探讨Go语言在构建微服务时的性能优势,包括其在内存管理、网络编程、并发模型以及工具链支持方面的特点。通过对比其他流行语言,我们将揭示Go语言如何成为微服务架构中的一股清流。
|
1天前
|
Ubuntu 编译器 Linux
go语言中SQLite3驱动安装
【11月更文挑战第2天】
16 7
|
1天前
|
关系型数据库 Go 网络安全
go语言中PostgreSQL驱动安装
【11月更文挑战第2天】
16 5
|
1天前
|
SQL 关系型数据库 MySQL
go语言数据库中mysql驱动安装
【11月更文挑战第2天】
13 4
|
1天前
|
存储 设计模式 安全
Go语言中的并发编程:从入门到精通###
本文深入探讨了Go语言中并发编程的核心概念与实践技巧,旨在帮助读者从理论到实战全面掌握Go的并发机制。不同于传统的技术文章摘要,本部分将通过一系列生动的案例和代码示例,直观展示Go语言如何优雅地处理并发任务,提升程序性能与响应速度。无论你是Go语言初学者还是有一定经验的开发者,都能在本文中找到实用的知识与灵感。 ###
|
1天前
|
安全 Go
用 Zap 轻松搞定 Go 语言中的结构化日志
在现代应用程序开发中,日志记录至关重要。Go 语言中有许多日志库,而 Zap 因其高性能和灵活性脱颖而出。本文详细介绍如何在 Go 项目中使用 Zap 进行结构化日志记录,并展示如何定制日志输出,满足生产环境需求。通过基础示例、SugaredLogger 的便捷使用以及自定义日志配置,帮助你在实际开发中高效管理日志。
9 1
|
2天前
|
关系型数据库 MySQL 数据库连接
go语言中打开数据库连接
【11月更文挑战第1天】
13 2
|
9天前
|
Go 数据安全/隐私保护 开发者
Go语言开发
【10月更文挑战第26天】Go语言开发
24 3
|
10天前
|
Java 程序员 Go
Go语言的开发
【10月更文挑战第25天】Go语言的开发
21 3
|
3月前
|
JSON 中间件 Go
go语言后端开发学习(四) —— 在go项目中使用Zap日志库
本文详细介绍了如何在Go项目中集成并配置Zap日志库。首先通过`go get -u go.uber.org/zap`命令安装Zap,接着展示了`Logger`与`Sugared Logger`两种日志记录器的基本用法。随后深入探讨了Zap的高级配置,包括如何将日志输出至文件、调整时间格式、记录调用者信息以及日志分割等。最后,文章演示了如何在gin框架中集成Zap,通过自定义中间件实现了日志记录和异常恢复功能。通过这些步骤,读者可以掌握Zap在实际项目中的应用与定制方法
125 1
go语言后端开发学习(四) —— 在go项目中使用Zap日志库
下一篇
无影云桌面