Go-高质量编程与性能调优

这篇具有很好参考价值的文章主要介绍了Go-高质量编程与性能调优。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

高质量编程:

什么是高质量:

​ ——编写代码能达到正确可靠,简洁清晰的目标

各种边界条件是否考虑完备

异常情况处理,稳定性保证

易读易维护

编程原则
简单性

消除“多余的复杂性”,以简单清晰的逻辑编写代码

不理解的代码无法修复改进

可读性

代码是写给人看的,而不是机器

编写可维护代码的第一步是确保代码可读

生产力

团队整体工作效率非常重要

编写规范
  • 代码格式

    gofmt: go语言官方提供工具,自动格式化为官方统一风格

    goimports:go语言官方提供工具,实际等于gofmt加上依赖包管理,自动增删依赖包引用,对其排序分类等

  • 注释

    注释应该做的:

    应该解释代码作用

    应该解释代码如何做的

    应该解释代码实现的原因

    应该解释代码什么情况会出错

    应该解释公共符号(公共的变量,常量,函数,不应该取决与代码的长度来选择注释)

    代码是最好的注释,并且注释应该要提供代码未表达出的上下文信息

  • 命名规范

    简介胜于冗长

    for index := 0; index < len(s); index++{//bad
        //do something
    }
    
    for i := 0; i < len(s); i++{ //good
        //do something
    }
    

    缩略词全大写,但当其位于变量开头且不需要导出时,使用全小写

    例如:使用ServeHTTP而不是ServeHttp
    使用XMLHTTPRequest或者xmlHTTPRequest
    

    变量距离其被使用的地方越远,越需要携带更多的上下文信息

    函数名不携带包名的上下文信息,因为包名和函数总是成对出现的

    函数名尽量简短

    对于package来说,只由小写字母组成,不包含大写字母和下划线

    简短并包含一定上下文信息,例如schema,task

    不要与标准库同名

    不使用常用变量名作为包名,例如使用bufo而不是buf

    使用单数不使用复数,例如使用encoding而不是encodings

    谨慎使用缩写

  • 控制流程

    避免嵌套

    if foo{ // bad 
    	return x
    }else{
    	return nil
    }
    
    if foo{ // good
    	return x
    }
    return nil
    

    简单来说差不多少用else -f else的这样以后添加修改方便

    处理逻辑尽量走直线,避免复杂嵌套分支

  • 错误和异常处理

    简单错误:仅出现一次的错误,有限使用errors.New来创建匿名变量

    func ErrorsNew(size int) error {
    	if size > 10 {
    		return errors.New("size bigger , should be less then 10")
    	}
    	return nil
    }
    

    错误的Wrap和Unwrap

    在fmt.Errorf中使用%w关键字将一个错误关联到错误链中

    	list, _ , err := c.GetBytes(cache.Subkey(a.actionID , "srcfiles"))
    	if err != nil{
    		return fmt.Errorf("reading srcfiles list : %w" , err)
    	}
    

    错误判定

    判定一个错误是否为特定错误,使用errors.ls

    不同于使用==,使用该方法可判定错误链上的所有错误是否含有特定错误

    	data, err = lockedfile.Read( targ )
    	if errors.Is(err , fs.ErrNotExist){
    	// Treat non-existent as empty, to bootstrap 
    	//the "latest" filethe first time we connect to a given database.
    		return []byteP{} , nil
    	}
    	return data, err
    }
    

    在错误链上过去特定错误使用errors.AS

    	if _ ,err := os.Open("non-exit"); err != nil{
    		var pathError *fs.PathError
    		if errors.As(err , &pathError){
    			fmt.Println("Failed at path :" , pathError.Path)
    		}else{
    			fmt.Println(err)
    		}
    	}
    

    panic

    不建议在业务代码中使用panic

    调用函数不包含recover会造成程序崩溃

    若问题可以被屏蔽或解决,建议使用error代替panic

    recover

    recover只能被defer的函数中使用

    嵌套无法生效

    只在当前goroutine生效

    defer语句是后进先出

优化与性能测试:

性能优化的前提是满足正确可靠,简洁清晰等质量因素

性能优化是综合评估,有时候时间效率和空间效率可能对立

Benchmark

go语言提供支持基准性能测试的工具

func BenchmarkFib10(b *testing.B) {
	for i := 0; i < 10; i++{
		Fib(10)
	}
}

func Fib(n int)  int {
	if n < 2{
		return n
	}
	return Fib(n - 1) + Fib(n - 2)
}
go test -bench=. -benchmem // 执行命令

Go-高质量编程与性能调优,go,golang

上面第一行-16差不多是cpu核数了

10000… 是执行次数

0.0005517 是每次花费时间

0B 是每次申请内存

0allocs是每次申请几次内存

性能优化建议Slice

预分配

尽可能在使用make初始化切片时提供容量信息

func BenchmarkNoPreAlloc(){
	data := make([]int , 0)
	for k := 0; k < n; k++{
		data = append(data, k)
	}
}

func BenchmarkPreAlloc(){

	data := make([]int , n)
	for k := 0; k < n; k++{
		data = append(data,  k )
	}
}

Go-高质量编程与性能调优,go,golang

大内存未释放

在已有的切片基础上创建切片,不会创建新的底层数组,如下

func Copy(origin []int) []int{
	return origin[3:len(origin)]
}

上述就是想创建个新切片,但是其实底层数组用的是同一个,如果说传入参数在之后不用的,但是因为有个这个返回值只用一段数据却占用这之前的一大块数据,内存就浪费了

另一个问题就是由于工用一个数组,你改变一个切片的值,另一个也就改变了

func main() {
	a := []int{1, 2, 3, 4, 5}
	b := a
	fmt.Println(a) //[1 2 3 4 5]
	fmt.Println(b) //[1 2 3 4 5]
	b[0] = 1000
	fmt.Println(a) //[1000 2 3 4 5]
	fmt.Println(b) //[1000 2 3 4 5]
}

由于切片是引用类型,所以a和b其实都指向了同一块内存地址。修改b的同时a的值也会发生变化。

Go语言内建的copy()函数可以迅速地将一个切片的数据复制到另外一个切片空间中,copy()函数的使用格式如下:

copy(destSlice, srcSlice []T)

其中:

  • srcSlice: 数据来源切片
  • destSlice: 目标切片

举个例子:

func main() {
	// copy()复制切片
	a := []int{1, 2, 3, 4, 5}
	c := make([]int, 5, 5)
	copy(c, a)     //使用copy()函数将切片a中的元素复制到切片c
	fmt.Println(a) //[1 2 3 4 5]
	fmt.Println(c) //[1 2 3 4 5]
	c[0] = 1000
	fmt.Println(a) //[1 2 3 4 5]
	fmt.Println(c) //[1000 2 3 4 5]
}
性能优化建议-Map
const n = 10000000

func BenchmarkNoPreAlloc(b *testing.B) {
	data := make(map[int]int , 0)
	for k := 0; k < n; k++ {
		data[k] = 1
	}
}

Go-高质量编程与性能调优,go,golang

func BenchmarkPreAlloc(b *testing.B) {

	data := make(map[int]int , n)
	for k := 0; k < n; k++ {
		data[k] = 1
	}
}

Go-高质量编程与性能调优,go,golang
可以看出,结果和切片差不多

分析:

​ 不断向map中添加元素操作会触发map扩容

​ 提前分配好空间可以减少内存拷贝和ReHash的消耗

性能优化建议-字符串处理

常见的字符串拼接方式

func plus(n int , str string) string{
	s := ""
	for i := 0; i < n; i++{
		s += str
	}
	return s
}

func StrBulider(n int  , str string)string{
	var builder strings.Builder
	for i := 0; i < n; i++{
		builder.WriteString(str)
	}
	return builder.String()
}

func ByteBuffer(n int , str string)string{
	buf := new(bytes.Buffer)
	for i := 0; i < n; i++{
		buf.WriteString(str)
	}
	return buf.String()
}

使用 + 拼接性能最差,后面俩个差不多,strings.Buffer更快

分析:

​ 字符串在Go语言中是不可变类型,占用内存大小固定

​ 使用 + 每次都会重新分配内存

​ 后面的底层都是 []byte数组,内存扩容策略,不需要每次拼接重新分配内存文章来源地址https://www.toymoban.com/news/detail-617035.html

到了这里,关于Go-高质量编程与性能调优的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 萤火跑模型 | 高性能 Stable Diffusion 助力高质量 AI 绘图

    Stable Diffusion AI 绘画最近成功破圈,成了炙手可热的热门话题。DALLE,GLIDE,Stable Diffusion 等基于扩散机制的生成模型让 AI 作图发生质变,让人们看到了“AI 转成生产力”的曙光。 在这些扩散模型中,Stable Diffusion 以其优秀的效果和开源的权重成为了其中的代表,受到广泛的关

    2024年02月09日
    浏览(52)
  • AI Code Translator —— 能够实现高质量的自动编程语言转换工具

    https://github.com/mckaywrigley/ai-code-translator AI Code Translator —— 是一款基于大型语言模型的代码翻译工具,同时也是一款颠覆性的编程语言翻译工具,它基于先进的机器学习技术和大规模语料库训练而成,能够实现高质量的自动编程语言转换。 这款工具最大的突破在于翻译速度快且

    2024年02月04日
    浏览(49)
  • ChatGPT如何提供实用且高质量的建议和指导,提高编程效率和准确性

    ChatGPT4.0的功能包括: 无限制ChatGPT模型使用 GPT-4模型使用 GPT-4图像分析功能 GPT-4联网功能 GPT-4高级数据分析功能 GPT-4高级插件功能 DALLE-3高级AI绘图功能 如何能高效地处理文本、文献查阅、PPT编辑、编程、绘图和论文写作已经成为您成功的关键。而 ChatGPT,作为一种强大的自然

    2024年02月22日
    浏览(55)
  • 【人工智能】大模型时代,程序员需要具备哪些技能才能胜任?哪些技能重要、哪些不再重要?无论如何,人是最终的决定性的因素:高质量需求、简单设计、防御式编程、测试先行、质量内建……

    无论如何,人是最终的决定性的因素:高质量需求、简单设计、防御式编程、测试先行、质量内建…… 目录 Part.1 “程序员”的工作,还是不是“写程序”?

    2024年02月07日
    浏览(83)
  • 微软和OpenAI联手推出了GitHub Copilot这一AI编程工具,可根据开发者的输入和上下文,生成高质量的代码片段和建议

    只需要写写注释,就能生成能够运行的代码?对于程序员群体来说,这绝对是一个提高生产力的超级工具,令人难以置信。实际上,早在2021年6月,微软和OpenAI联手推出了GitHub Copilot这一AI编程工具。它能够根据开发者的输入和上下文,生成高质量的代码片段和建议。这个工具

    2024年02月09日
    浏览(71)
  • 高质量椭圆检测库

    目录 前言 效果展示 检测库 简介 安装库 用法 测试 论文算法步骤简读 1. lsd 检测 2. lsd group 3. 生成初始 ellipse 4. 聚类 椭圆检测是工业中比较常用的一种检测需求。目前常用的基于传统图像处理的椭圆检测方法是霍夫变换,但是霍变换的检测率比较低,很难满足工业场景。而基

    2024年02月07日
    浏览(151)
  • 如何写出高质量代码?

    作为一名资深开发人员,写出高质量的代码是我们必须要追求的目标。然而,在实际开发中,我们常常会遇到各种问题。比如,代码的可读性、可维护性、健壮性和灵活性等,这些都会影响代码的质量。那么,究竟如何才能写出高质量的代码呢? 代码结构清晰易懂,能够使代

    2024年02月02日
    浏览(58)
  • 如何编写高质量代码

    现代软件开发中,代码是构建高质量软件的核心。高质量代码能够提高软件系统的可靠性、可维护性和可扩展性,减少bug的数量和修复时间,提升开发效率和代码可读性,同时有助于团队协作和知识传承共享。 然而,梦想是丰满的,现实是骨感的!软件开发面临诸多挑战。

    2024年02月02日
    浏览(128)
  • 如何写出高质量代码

    一、 前言 编写高质量代码是每一位程序员的追求。高质量的代码可以提高代码可读性、可维护性、可扩展性以及软件运行的性能和稳定性。在这篇文章中,我将分享一些编写高质量代码的特征、编程实践技巧和软件工程方法论。 可读性:好的代码应该能够被维护者轻易地理

    2024年02月02日
    浏览(88)
  • 如何写出高质量的代码

    你是否曾经为自己写的代码而感到懊恼?你是否想过如何才能写出高质量代码?那就不要错过这个话题!在这里,我们可以讨论什么是高质量代码,如何写出高质量代码等问题。无论你是初学者还是资深开发人员,都可以在这个话题下进行分享,汲取灵感和知识,共同提高自

    2023年04月25日
    浏览(129)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包