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

Go 语言一些常用语法编写和优化指南

Go 语言以其简洁的语法和强大的并发性能而受到开发者的喜爱。然而,为了充分利用 Go 的潜力,我们需要了解如何优化 Go 程序。本文将介绍一些常见的 Go 语言优化技巧,并通过实际例子进行说明。

推荐系列
来来来,老铁们,男人女人都需要的技术活 拿去不谢:远程调试,发布网站到公网演示,远程访问内网服务,
福利链接

1. 利用 sync.Pool 减少内存分配

在 Go 中,频繁的内存分配和释放可能会导致性能问题。sync.Pool 可以用于存储和复用临时对象,从而减少内存分配和垃圾回收的开销。

var bufPool = sync.Pool{New: func() interface{} {return make([]byte, 1024)},
}buf := bufPool.Get().([]byte)
// 使用 buf...
bufPool.Put(buf)

在这个例子中,我们创建了一个 sync.Pool 来存储字节切片。当我们需要一个字节切片时,我们首先尝试从池中获取,如果池中没有可用的对象,那么 New 函数就会被调用来创建一个新的字节切片。使用完字节切片后,我们将其放回池中,以便后续的复用。

2. 使用缓冲通道进行异步操作

Go 的通道(channel)是一种在 goroutine 之间进行通信的机制。缓冲通道可以用于异步操作,从而提高程序的并发性能。

ch := make(chan int, 100) // 创建一个缓冲大小为100的通道go func() {for i := 0; i < 100; i++ {ch <- i // 向通道发送数据}close(ch)
}()for i := range ch { // 从通道接收数据fmt.Println(i)
}

在这个例子中,我们创建了一个缓冲大小为 100 的通道。然后我们启动了一个 goroutine 来向通道发送数据,主 goroutine 从通道接收数据。由于通道是缓冲的,所以发送者和接收者可以并行工作,从而提高了程序的并发性能。

3. 利用 pprof 进行性能分析

Go 标准库中的 net/http/pprof 包提供了一种方便的方式来分析 Go 程序的性能。我们可以通过添加一些简单的代码来启动一个 HTTP 服务器,然后通过 pprof 工具来获取和分析性能数据。

import _ "net/http/pprof"go func() {log.Println(http.ListenAndServe("localhost:6060", nil))
}()

在这个例子中,我们启动了一个运行在 localhost:6060 的 HTTP 服务器。然后我们可以通过 go tool pprof http://localhost:6060/debug/pprof/profile 命令来获取 CPU profile,或者通过 go tool pprof http://localhost:6060/debug/pprof/heap 命令来获取内存 profile。

4. 使用 strings.Builder 进行字符串拼接

在 Go 中,字符串是不可变的,这意味着每次字符串拼接操作都会创建一个新的字符串。如果你需要进行大量的字符串拼接操作,这可能会导致大量的内存分配和垃圾回收。strings.Builder 是 Go 语言中用于高效字符串拼接的工具。

var builder strings.Builderfor i := 0; i < 1000; i++ {builder.WriteString("Hello, World!")
}result := builder.String()

在这个例子中,我们使用 strings.Builder 来进行 1000 次字符串拼接操作。与直接使用 ++= 进行字符串拼接相比,strings.Builder 可以显著提高性能。

5. 利用 time.After 避免 goroutine 泄露

在 Go 中,如果一个 goroutine 在完成任务后没有被正确地关闭,那么它可能会一直占用内存,这被称为 goroutine 泄露。time.After 是一种常用的防止 goroutine 泄露的技巧。

func doSomethingWithTimeout(timeout time.Duration) {done := make(chan bool)go func() {// 做一些耗时的操作...done <- true}()select {case <-done:// 操作成功完成case <-time.After(timeout):// 操作超时}
}

在这个例子中,我们启动了一个 goroutine 来执行一些耗时的操作,然后使用 select 语句等待操作的完成或超时。如果操作在超时时间内完成,那么 done 通道会接收到一个值,select 语句会退出。如果操作在超时时间内没有完成,那么 time.After 会发送一个值,select 语句会退出,goroutine 会被正确地关闭。

6. 使用 strconv 而不是 fmt 进行字符串转换

在 Go 中,fmt.Sprintf 是一种常用的将其他类型的值转换为字符串的方法。然而,fmt.Sprintf 的性能通常不如 strconv 包中的函数。

s := fmt.Sprintf("%d", 123) // 不推荐s := strconv.Itoa(123) // 推荐

在这个例子中,我们比较了 fmt.Sprintfstrconv.Itoa 两种将整数转换为字符串的方法。虽然 fmt.Sprintf 更灵活,但 strconv.Itoa 的性能更好。

7. 使用索引访问切片元素

在 Go 中,使用 range 循环遍历切片是一种常见的做法。然而,如果你只需要访问切片的元素,而不需要元素的索引,那么使用索引访问元素通常会有更好的性能。

for i := range slice {_ = slice[i] // 推荐
}for _, v := range slice {_ = v // 不推荐
}

在这个例子中,我们比较了使用 range 循环和使用索引访问切片元素的两种方法。虽然使用 range 循环更简洁,但使用索引访问元素的性能更好。

8. 避免在循环中创建 goroutine

在 Go 中,go 关键字可以用于创建新的 goroutine。然而,如果你在循环中创建 goroutine,那么可能会导致大量的 goroutine 被创建,从而消耗大量的内存。

for _, v := range slice {go func(v int) {// 处理 v...}(v)
}

在这个例子中,我们在循环中为每个元素创建了一个新的 goroutine。虽然这样可以并行处理元素,但如果切片的大小很大,那么可能会创建大量的 goroutine,从而消耗大量的内存。因此,我们应该避免在循环中创建 goroutine,或者使用一些技术(如使用 sync.WaitGroup 或者使用通道)来限制 goroutine 的数量。

Go 语言优化指南(续)

在前几篇文章中,我们已经介绍了一些常见的 Go 语言优化技巧。在这篇文章中,我们将继续探讨更多的优化技巧,并通过实际例子进行说明。

9. 使用 sync.Map 进行并发安全的映射操作

在 Go 中,内置的 map 类型不是并发安全的,这意味着你不能在多个 goroutine 中同时对同一个 map 进行读写操作。sync.Map 是 Go 语言中用于并发安全的映射操作的工具。

var m sync.Mapm.Store("hello", "world") // 存储键值对value, ok := m.Load("hello") // 加载键值对
if ok {fmt.Println(value)
}

在这个例子中,我们使用 sync.Map 来存储和加载键值对。与内置的 map 相比,sync.Map 的性能可能稍微差一些,但它可以在多个 goroutine 中安全地使用。

10. 利用 context 包进行超时和取消操作

在 Go 中,context 包提供了一种在 API 边界之间传递超时、取消信号以及其他请求范围的值的机制。

ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()select {
case <-time.After(2 * time.Second):fmt.Println("overslept")
case <-ctx.Done():fmt.Println(ctx.Err())
}

在这个例子中,我们创建了一个会在一秒后自动取消的 context。然后我们等待两秒或 context 被取消。由于 context 会在一秒后被取消,所以 ctx.Err() 会返回一个错误,表明 context 已经被取消。

11. 使用 atomic 包进行并发安全的操作

在 Go 中,sync/atomic 包提供了一些原子操作函数,可以用于实现并发安全的计数器、标志等。

var counter int64go func() {for {atomic.AddInt64(&counter, 1)time.Sleep(time.Millisecond)}
}()go func() {for {fmt.Println(atomic.LoadInt64(&counter))time.Sleep(time.Second)}
}()

在这个例子中,我们创建了一个并发安全的计数器。一个 goroutine 每毫秒将计数器加一,另一个 goroutine 每秒打印计数器的当前值。由于我们使用了 atomic 包中的函数,所以这个计数器在多个 goroutine 中是安全的。

12. 利用 reflect 包进行动态操作

在 Go 中,reflect 包提供了一种在运行时动态操作对象的机制,包括获取对象的类型和值、调用方法等。

v := reflect.ValueOf(123)
t := reflect.TypeOf(123)fmt.Println(v.Int()) // 输出:123
fmt.Println(t.Name()) // 输出:int

在这个例子中,我们使用 reflect 包获取了一个整数的值和类型。虽然 reflect 包非常强大,但它的性能通常不如静态类型的操作,所以我们应该谨慎使用。

13. 使用 sort 包进行高效排序

Go 语言的 sort 包提供了一系列函数用于对切片和自定义数据结构进行排序。

nums := []int{3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5}
sort.Ints(nums)
fmt.Println(nums) // 输出:[1 1 2 3 3 4 5 5 5 6 9]

在这个例子中,我们使用 sort.Ints 函数对一个整数切片进行排序。sort 包还提供了其他函数,如 sort.Float64ssort.Strings 等,用于对特定类型的切片进行排序。

14. 利用 encoding/json 包进行 JSON 操作

Go 语言的 encoding/json 包提供了一系列函数用于处理 JSON 数据。

type Person struct {Name string `json:"name"`Age  int    `json:"age"`
}jsonStr := `{"name":"John","age":30}`
var p Person
json.Unmarshal([]byte(jsonStr), &p)
fmt.Println(p) // 输出:{John 30}

在这个例子中,我们定义了一个 Person 结构体,并使用 json.Unmarshal 函数将一个 JSON 字符串解析到这个结构体中。encoding/json 包还提供了其他函数,如 json.Marshal 等,用于将 Go 数据结构转换为 JSON 字符串。

推荐系列

来来来,老铁们,男人女人都需要的技术活 拿去不谢:远程调试,发布网站到公网演示,远程访问内网服务,
福利链接

相关文章:

Go 语言一些常用语法编写和优化指南

Go 语言以其简洁的语法和强大的并发性能而受到开发者的喜爱。然而&#xff0c;为了充分利用 Go 的潜力&#xff0c;我们需要了解如何优化 Go 程序。本文将介绍一些常见的 Go 语言优化技巧&#xff0c;并通过实际例子进行说明。 推荐系列 来来来,老铁们,男人女人都需要的技术活…...

Golang 语法系列:结构体

结构体&#xff1a;相当于"类" 1.结构体声明 type [name] struct {[field_name] [field_type][field_name] [field_type]... }//例子&#xff1a;type Person struct {name stringage int }其中field_name可以省略 2.结构体的使用 1) 格式1 var person Person p…...

关于iPad中的密码和触控ID的使用,看这篇文章就差不多了

序言 许多苹果iPad型号都有熟悉的密码系统和触控ID,这需要指纹扫描才能解锁设备。本指南向你展示如何使用iPad Air 2或更高版本、iPad Mini 3或更新版本以及iPad Pro设置或更改密码和触控ID指纹。 一些iPad Pro型号支持面部识别,并配备了面容ID而不是触控ID作为安全功能。面…...

Vue3之ref与reactive的基本使用

ref可以创建基本类型、对象类型的响应式数据 reactive只可以创建对象类型的响应式数据 接下来让我为大家介绍一下吧&#xff01; 在Vue3中&#xff0c;我们想让数据变成响应式数据&#xff0c;我们需要借助到ref与reactive 先为大家介绍一下ref如何使用还有什么注意点 我们需…...

wsl内置Ubuntu使用 Dinky 与 Flink 集成

Dinky 与 Flink 集成 说明 本文档介绍 Dinky 与 Flink 集成的使用方法, 如果您是 Dinky 的新用户, 请先阅读 本文档, 以便更好的搭建 Dinky 环境 如果您已经熟悉 Dinky 并已经部署了 Dinky, 请跳过本文档的前置要求部分, 直接阅读 Dinky 与 Flink 集成部分 注意: 本文档基…...

”戏说“ 交换机 与 路由器

一般意义上说 老哥 这文章发表 的 东一榔头 西一锤 呵呵&#xff0c; 想到哪里就啰嗦到哪里 。 交换机&#xff1a; 其实就是在通道交换 路由器&#xff1a; 不光是在通道交换还要在协议上交换 下图你看懂了吗&#xff1f; &#xff08;仅仅数据交换-交换机 协议…...

Linux pageset

1. 引言 在用户进程发生缺页异常时&#xff0c;Linux内核需要分配所需物理页面以及建立也表映射&#xff0c;来维持进程的正常内存使用需求。而对于分配物理页面仅依赖于buddy系统&#xff0c;对于小order页面的分配效率较低。因此Linux通过在每个cpu维护一个page链表&#xff…...

【C++之语法篇003】

C学习笔记---003 C知识开篇1、内联函数1.1、什么是内联函数?1.2、解决外部头文件&#xff0c;重复定义问题1.3、内联函数的总结 2、auto关键字2.1、auto的作用2.2、auto的总结 3、范围for3.1、什么是范围for&#xff1f;3.2、范围for的循环应用 4、指针空值关键字nullptr4.1、…...

Github代码仓库SSH配置流程

作者&#xff1a; Herman Ye Auromix 测试环境&#xff1a; Ubuntu20.04 更新日期&#xff1a; 2024/02/21 注1&#xff1a; Auromix 是一个机器人爱好者开源组织。 注2&#xff1a; 由于笔者水平有限&#xff0c;以下内容可能存在事实性错误。 相关背景 在为Github代码仓库配…...

Arrays工具类的常见方法总结

一、Arrays.asList( ) 1.作用&#xff1a;Arrays.asList( )方法的作用是将数组转换成List&#xff0c;将List中的全部集合对象添加至ArrayList集合中 2.参数&#xff1a;动态参数 (T... a) 3.返回值&#xff1a;List 集合 List<T> 4.举例&#xff1a; package com…...

物联网和人工智能的融合

物联网和人工智能的融合 1. 物联网和人工智能的融合2. 芯片技术的进步3. 安全和隐私保护挑战4. 软件开发和调试技术的创新5. 自动化和智能化趋势 1. 物联网和人工智能的融合 随着物联网和人工智能技术的快速发展&#xff0c;嵌入式系统将更多地与物联网设备和人工智能算法相结…...

【微信小程序】wxss 和 css 、wxml 和 html 区别

wxss 和 css 区别 wxss 支持小程序特有的选择器和 样式属性 scroll-into-view cover-view 等wxss 引入了 rpx 单位&#xff0c;可以根据屏幕宽度进行自适应&#xff0c;使得开发者可以更方便的处理不同尺寸屏幕的适配问题。wxss 背景图片只能引入外链&#xff0c;不能使用本地…...

python统计分析——使用AIC进行模型选择

参考资料&#xff1a;用python动手学统计学 1、导入库 # 导入库 # 用于数值计算的库 import numpy as np import pandas as pd import scipy as sp from scipy import stats # 用于绘图的库 import matplotlib.pyplot as plt import seaborn as sns sns.set() # 用于估计统计…...

Android 11以上获取不到第三方app是否安装

开年第一篇&#xff0c;处理了一下年前的小问题。 问题&#xff1a;本地app跳转到第三方app地图进行导航&#xff0c;获取不到第三方地图是否安装。 解决&#xff1a; 1.添加包名 This can be done by adding a <queries> element in the Android manifest.在app下的…...

Java的编程之旅24——private私有方法

1.private的介绍 在面向对象编程中&#xff0c;private是一种访问修饰符&#xff0c;用于限制成员的访问范围。私有成员只能在所属的类内部访问&#xff0c;对外部的类或对象是不可见的。 private的使用可以带来以下几个好处&#xff1a; 封装实现细节&#xff1a;私有成员可…...

为什么在MOS管开关电路设计中使用三极管容易烧坏?

MOS管作为一种常用的开关元件&#xff0c;具有低导通电阻、高开关速度和低功耗等优点&#xff0c;因此在许多电子设备中广泛应用。然而&#xff0c;在一些特殊情况下&#xff0c;我们需要在MOS管控制电路中加入三极管来实现一些特殊功能。然而&#xff0c;不同于MOS管&#xff…...

CSS的注释:以“ /* ”开头,以“ */ ”结尾

CSS的注释:以“ /* ”开头&#xff0c;以“*/”结尾 CSS的注释: 以“ /* ”开头&#xff0c;以“ */ ”结尾 在CSS中&#xff0c;注释是一种非常重要的工具&#xff0c;它们可以帮助开发者记录代码的功能、用法或其他重要信息。这些信息对于理解代码、维护代码以及与他人合作都…...

MySQL中常见的几种日志类型【重点】

在MySQL中&#xff0c;有几种不同类型的日志&#xff0c;用于记录数据库的活动和操作&#xff0c;以便于故障排查、性能调优和数据恢复等目的。以下是MySQL中常见的几种日志类型&#xff1a; 错误日志&#xff08;Error Log&#xff09;&#xff1a; 错误日志记录了MySQL服务器…...

odoo16-API(Controller)带有验证访问的接口

odoo16-API&#xff08;Controller&#xff09;带有验证访问的接口 目前我使用odoo原生的登录token来验证登陆的有效性 废话不多说直接上代码 # 测试获取session_id import requests class GetOdooData(http.Controller):def getOdooToken(self):# http://localhost:8123访问…...

Eclipse项目间的引用

我们在开发的时候&#xff0c;有时候需要把一个大的项目打散&#xff0c;尤其是现在微服务的架构很流行&#xff0c;一个大的项目往往被拆成很多小的项目&#xff0c;而有的项目作为公共工程被独立出来&#xff0c;比如有个工程专门提供各种Util工具类&#xff0c;有的工程专门…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

【论文笔记】若干矿井粉尘检测算法概述

总的来说&#xff0c;传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度&#xff0c;通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar&#xff1a;依赖注入与仓储模式实践 在 C# 的应用开发中&#xff0c;数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护&#xff0c;许多开发者会选择成熟的 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;SqlSugar 就是其中备受…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象&#xff0c;只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意&#xff1a;它移动的位置必须是相连的有内容的单元格…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...

短视频矩阵系统文案创作功能开发实践,定制化开发

在短视频行业迅猛发展的当下&#xff0c;企业和个人创作者为了扩大影响力、提升传播效果&#xff0c;纷纷采用短视频矩阵运营策略&#xff0c;同时管理多个平台、多个账号的内容发布。然而&#xff0c;频繁的文案创作需求让运营者疲于应对&#xff0c;如何高效产出高质量文案成…...

Rust 开发环境搭建

环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行&#xff1a; rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu ​ 2、Hello World fn main() { println…...