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

相关文章
|
19天前
|
算法 Java Go
【GoGin】(1)上手Go Gin 基于Go语言开发的Web框架,本文介绍了各种路由的配置信息;包含各场景下请求参数的基本传入接收
gin 框架中采用的路优酷是基于httprouter做的是一个高性能的 HTTP 请求路由器,适用于 Go 语言。它的设计目标是提供高效的路由匹配和低内存占用,特别适合需要高性能和简单路由的应用场景。
125 4
|
2月前
|
数据采集 数据挖掘 测试技术
Go与Python爬虫实战对比:从开发效率到性能瓶颈的深度解析
本文对比了Python与Go在爬虫开发中的特点。Python凭借Scrapy等框架在开发效率和易用性上占优,适合快速开发与中小型项目;而Go凭借高并发和高性能优势,适用于大规模、长期运行的爬虫服务。文章通过代码示例和性能测试,分析了两者在并发能力、错误处理、部署维护等方面的差异,并探讨了未来融合发展的趋势。
228 0
|
19天前
|
JavaScript 前端开发 Java
【GoWails】Go做桌面应用开发?本篇文章带你上手Wails框架!一步步带你玩明白前后端双端的数据绑定!
wails是一个可以让你使用Go和Web技术编写桌面应用的项目 可以将它看作Go的快并且轻量级的Electron替代品。可以使用Go的功能,并结合现代化UI完成桌面应用程序的开发
129 4
|
19天前
|
存储 安全 Java
【Golang】(4)Go里面的指针如何?函数与方法怎么不一样?带你了解Go不同于其他高级语言的语法
结构体可以存储一组不同类型的数据,是一种符合类型。Go抛弃了类与继承,同时也抛弃了构造方法,刻意弱化了面向对象的功能,Go并非是一个传统OOP的语言,但是Go依旧有着OOP的影子,通过结构体和方法也可以模拟出一个类。
73 1
|
2月前
|
Cloud Native 安全 Java
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
258 1
|
2月前
|
Cloud Native Go API
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
300 0
|
2月前
|
Cloud Native Java Go
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
205 0
|
2月前
|
Cloud Native Java 中间件
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
170 0
|
2月前
|
Cloud Native Java Go
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
267 0
|
8月前
|
编译器 Go
揭秘 Go 语言中空结构体的强大用法
Go 语言中的空结构体 `struct{}` 不包含任何字段,不占用内存空间。它在实际编程中有多种典型用法:1) 结合 map 实现集合(set)类型;2) 与 channel 搭配用于信号通知;3) 申请超大容量的 Slice 和 Array 以节省内存;4) 作为接口实现时明确表示不关注值。此外,需要注意的是,空结构体作为字段时可能会因内存对齐原因占用额外空间。建议将空结构体放在外层结构体的第一个字段以优化内存使用。

热门文章

最新文章