iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > GO >gocodereview代码调试
  • 822
分享到

gocodereview代码调试

2024-04-02 19:04:59 822人浏览 八月长安
摘要

目录ExamplesGoroutine LifetimesHandle ErrorsimportImport BlankImport DotIn-Band ErrorsIndent

Examples

在添加新包时,包括预期使用的示例:

  • 一个可运行的示例
  • 或一个演示完整调用序列的简单测试

Goroutine Lifetimes

当你使用 goroutines 时,要明确它们何时退出或者是否退出。

goroutine 可以通过阻塞通道发送或接收而泄漏: 即使阻塞的通道不可达,垃圾收集器也不会终止 goroutine

即使 goroutine 没有泄漏,当它们不再被需要时,将它们留在空中也会导致其他微妙和难以诊断的问题。发送在已关闭的通道时会引发 panic。“在结果不需要之后”修改仍在使用的输入仍然会导致数据竞争。并且让 goroutines 在运行中停留任意长的时间会导致不可预测的内存使用。

尽量保持并发代码足够简单,这样 goroutine 的生存期就很明显了。如果这是不可行的,记录下 goroutines 退出的时间和原因。

有些时候我们使用 goroutine 的时候,会忘记捕获 panic,这里提供一个封装好了的 go 方法:

// GoSafe runs the given fn using another goroutine, recovers if fn panics.
func GoSafe(log *log.Logger, fn func()) {
   go RunSafe(log, fn)
}
// RunSafe runs the given fn, recovers if fn panics.
func RunSafe(log *log.Logger, fn func()) {
   defer Recover(log)
   fn()
}
// Recover is used with defer catch panics.
func Recover(log *log.Logger) {
   if p := recover(); p != nil {
      log.Error("%s\n%s", p, debug.Stack())
   }
}

Handle Errors

不要使用 _ 变量丢弃错误。如果函数返回错误,请检查它以确保函数成功。处理错误,返回错误,或者,在真正异常的情况下,抛出 panic

可以参考官方文档中优雅的做法:Effective Go

import

避免重命名导入,除非是为了避免名称冲突

好的包名不需要重命名。如果发生冲突,最好重命名、本地的或特定于项目的导入。

导入按组区分,组与组之间有空白行。标准库包总是在第一组中。

package main
import (
	"fmt"
	"hash/adler32"
	"os"
	"appengine/foo"
	"appengine/user"
	"GitHub.com/foo/bar"
	"rsc.io/goversion/version"
)

使用 goimport 能帮助到您,所以在项目中配置 goimport 是必要的。

Import Blank

仅为其副作用而导入的包(使用import _ "pkg"语法)应该只在程序的主包中导入,或在需要它们的测试中导入。

类似使用其他包的 init 函数

Import Dot

import . 在解决循环依赖时较为好用的方式,但是不能滥用:

package foo_test
import (
	"bar/testutil" // also imports "foo"
	. "foo"
)

在这种情况下,测试文件不能在包 foo 中,因为它使用 bar/testutil,它导入 foo。所以我们使用 'import .' 形式让文件假装是包 foo 的一部分,即使它不是。除了这种情况,不要使用import .在你的项目中。它使程序更加难以阅读,因为不清楚像 Quux 这样的名称是当前包还是导入包中的顶级标识符。

In-Band Errors

C 和类似的语言中,函数通常会返回 -1 或 null 这样的值来表示错误或默认结果:

// Lookup returns the value for key or "" if there is no mapping for key.
func Lookup(key string) string
// Failing to check for an in-band error value can lead to bugs:
Parse(Lookup(key))  // returns "parse failure for value" instead of "no value for key"

Go 对多个返回值的支持提供了更好的解决方案。与其要求客户端检查带内错误值,函数应该返回一个额外的值来指示它的其他返回值是否有效。这个返回值可能是一个错误,也可能是一个不需要解释的布尔值。它应该是最终的返回值。

// Lookup returns the value for key or ok=false if there is no mapping for key.
func Lookup(key string) (value string, ok bool)

这可以防止调用者错误地使用返回值:

Parse(Lookup(key))  // compile-time error

并鼓励更健壮和可读的代码:

value, ok := Lookup(key)
if !ok {
	return fmt.Errorf("no value for %q", key)
}
return Parse(value)

该规则适用于导出函数,但也适用于私有函数。

当它们是函数的有效结果时,像 nil、""、0 和 -1 这样的值是可以的,也就是说,当调用者不需要以不同于其他值的方式处理它们时。

一些标准库函数,比如包 strings 中的函数,返回带内错误值。这极大地简化了字符串操作代码,但代价是需要程序员付出更多努力。一般来说,Go代码应该返回额外的错误值。

Indent Error Flow

尽量将正常的代码路径缩进到最小,并缩进错误处理,首先处理它。这通过允许快速视觉扫描正常路径提高了代码的可读性。例如,不要写:

if err != nil {
	// error handling
} else {
	// nORMal code
}

相反,写:

if err != nil {
	// error handling
	return // or continue, etc.
}
// normal code

如果语句中有初始化语句,例如:if

if x, err := f(); err != nil {
	// error handling
	return
} else {
	// use x
}

然后,这可能需要将短变量声明移动到它自己的行:

x, err := f()
if err != nil {
	// error handling
	return
}
// use x

Initialisms

名字中属于首字母缩写或首字母缩写的词(例如:"URL""NATO")的大小写是一致的。例如,"URL"应该显示为 "URL""url" (如"urlPony""URLPony"),而不是"Url"。例如:ServeHttp而不是ServeHttp。对于具有多个初始化“单词”的标识符,可以使用例如"xmlHTTPRequest""XMLHTTPRequest"

"ID""identifier"的缩写时,这个规则也适用于"ID"(在大多数情况下,它不是"ego""superego"中的"ID"),所以写"appID"而不是"appId"

protobuf 生成的代码不受此规则约束。人类编写的代码要比机器编写的代码具有更高的标准。

Interfaces

Go 接口通常属于使用接口类型值的包,而不是实现这些值的包。实现包应该返回具体的(通常是指针或结构)类型:这样,新的方法就可以添加到实现中,而不需要大量的重构。

不要在api的实现者端定义 "mock" 接口;相反,应该设计API,以便可以使用实际实现的公共API进行测试。

不要在使用之前定义接口:没有一个实际的使用示例,很难判断接口是否必要,更不用说它应该包含哪些方法了。(有点重构的意思,将已有的方法抽象起来)

package consumer  // consumer.go
type Thinger interface { Thing() bool }
func Foo(t Thinger) string { … }
package consumer // consumer_test.go
type fakeThinger struct{ … }
func (t fakeThinger) Thing() bool { … }
…
if Foo(fakeThinger{…}) == "x" { … }
// DO NOT DO IT!!!
package producer
type Thinger interface { Thing() bool }
type defaultThinger struct{ … }
func (t defaultThinger) Thing() bool { … }
func NewThinger() Thinger { return defaultThinger{ … } }

相反,返回一个具体类型,并让使用者模拟生产者实现。

package producer
type Thinger struct{ … }
func (t Thinger) Thing() bool { … }
func NewThinger() Thinger { return Thinger{ … } }

Line Length

在Go代码中没有严格的行长限制,但是要避免令人不舒服的长行。类似地,当行更长的时候,不要添加换行符以保持行短——例如,如果它们是重复的。

大多数情况下,当人们“不自然地”换行时(或多或少地在函数调用或函数声明中换行,尽管存在一些异常),如果它们有合理数量的参数和合理较短的变量名,换行将是不必要的。较长的行似乎和较长的名字联系在一起,去掉长名字会有很大帮助。

换句话说,断行是因为你所写的内容的语义(作为一般规则),而不是因为行长。如果您发现这产生了太长行,那么更改名称或语义,您可能会得到一个好的结果。

实际上,这与函数的长度是完全相同的。没有“函数永远不会超过N行的规则”,但确实存在过长的函数,以及重复过小的函数,解决方法是改变函数的边界,而不是开始计数行数。

Mixed Caps

Effective Go

Named Result Parameters

想想在 godoc 中会是什么样子。命名结果参数如下:

func (n *node) Parent1() (node *Node) {}
func (n *Node) Parent2() (node *Node, err error) {}

将在 godoc 中重复;更好的使用:

func (n *Node) Parent1() *Node {}
func (n *Node) Parent2() (*Node, error) {}

另一方面,如果函数返回两个或三个相同类型的参数,或者如果从上下文不清楚结果的含义,添加名称在某些上下文中可能是有用的。不要为了避免在函数内部声明 var 而命名结果参数;以不必要的API冗长为代价来换取较小的实现简便性。

func (f *Foo) Location() (float64, float64, error)

不如:

// Location returns f's latitude and longitude.
// Negative values mean south and west, respectively.
func (f *Foo) Location() (lat, long float64, err error)

如果函数只有几行,裸返回是可以的。一旦它是一个中等大小的函数,就要显式地显示返回值。推论:仅仅因为结果参数允许使用裸返回而命名结果参数是不值得的。清晰的文档总是比在函数中节省一两行更重要。

最后,在某些情况下,您需要命名结果参数,以便在延迟闭包中更改它。这总是可以的。

Naked Returns

没有参数的语句返回指定的返回值。这就是所谓的“裸返回”。

func split(sum int) (x, y int) {
	x = sum * 4 / 9
	y = sum - x
	return
}

Package Comments

包注释,像 godoc 提供的所有注释一样,必须出现在 package 的上面,不能有空行。

// Package math provides basic constants and mathematical functions.
package math

package template

对于 "package main" 注释,其他风格的注释在二进制名称之后也可以(如果它在前面,则可以大写),例如,对于您可以编写的目录中的

// Binary seedgen ...
package main
// Command seedgen ...
package main
// Program seedgen ...
package main
// The seedgen command ...
package main
// The seedgen program ...
package main
// Seedgen ..
package main

这些都是例子,合理的变体也是可以接受的。

注意,以小写单词开头的句子不属于包注释的可接受选项,因为它们是公开可见的,应该用正确的英语编写,包括句子的第一个单词大写。当二进制名称是第一个单词时,即使它与命令行调用的拼写不严格匹配,也需要将其大写。

Effective Go

struct

每个结构体必须有自己的构造函数,并且使用 options 模式来构建新的参数。

以上就是go code review 代码调试的详细内容,更多关于go code review的资料请关注编程网其它相关文章!

您可能感兴趣的文档:

--结束END--

本文标题: gocodereview代码调试

本文链接: https://www.lsjlt.com/news/121290.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • gocodereview代码调试
    目录ExamplesGoroutine LifetimesHandle ErrorsimportImport BlankImport DotIn-Band ErrorsIndent ...
    99+
    2024-04-02
  • python调试代码
    我在看一些开源的python项目时,需要知道各个类各个函数之间的调用关系才能看懂代码,因此我写了个方法来跟踪代码的调用过程   import sys  from time import ctime  is_log=True  def log...
    99+
    2023-01-31
    代码 python
  • Unity3D代码调试
    1.光标定位到代码中的指定行,按F9/单击左键 设置断点。 2.在点击RUN->“Attach to Process...”3.弹出Attach to Process面板出现的面板中选择Process Name为unity Edit...
    99+
    2023-01-31
    代码 Unity3D
  • #7 Python代码调试
    前言 Python已经学了这么久了,你现在已经长大了,该学会自己调试代码了!相信大家在编写程序过程中会遇到大量的错误信息,我也不例外的啦~遇到这些问题该怎么解决呢?使用最多的方法就是使用print打印中间变量了哇,关于这种方法怎么说呢~l...
    99+
    2023-01-31
    代码 Python
  • Node.js的代码调试debug
    在Node.js中调试代码有多种方法,下面列举了一些常用的调试方法:1. 使用console.log():最简单的调试方法是在代码中...
    99+
    2023-09-17
    Node.js
  • Python代码调试技巧
    原文地址:http://www.ibm.com/developerworks/cn/linux/l-cn-pythondebugger/一、使用pdb进行调试pdb是Python自带的包,为Python提供一种交互的源代码调试功能。常用命令...
    99+
    2023-01-31
    代码 技巧 Python
  • python调试代码举例
    Python自带的pdb库,发现用pdb来调试程序还是很方便的,当然了,什么远程调试,多线程之类,pdb是搞不定的。用pdb调试有多种方式可选:1. 命令行启动目标程序,加上-m参数,这样调用myscript.py的话断点就是程序的执行第一...
    99+
    2023-01-31
    代码 python
  • JavaScript代码调试有哪些
    这篇文章将为大家详细讲解有关JavaScript代码调试有哪些,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。1.alert()通常可以使用警告框来提示变量信...
    99+
    2024-04-02
  • 如何调试 PHP 异步代码
    调试 php 异步代码的工具包括:psalm:静态分析工具,可发现潜在错误。parallellint:检查异步代码并提供建议的工具。xdebug:用于调试 php 应用程序的扩展,可通过...
    99+
    2024-05-11
    调试 php
  • 如何使用PySnooper调试代码
    本篇内容介绍了“如何使用PySnooper调试代码”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1. 快速安装执行下面这些命令进行安装 Py...
    99+
    2023-06-15
  • 如何使用VS代码调试
    小编给大家分享一下如何使用VS代码调试,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!Visual Studio 2005中,给程序员提供了十分强大和便捷的VS代码...
    99+
    2023-06-17
  • 如何在PHP中调试代码
    在开发PHP应用程序时,经常会遇到需要调试代码的情况。调试是解决程序问题,找出代码中的错误以及改进程序性能的必要步骤。在PHP中,调试使用的是调试器。 本文将介绍如何在PHP中使用调试器调试代码。一、配置调试环境在开始调试之前,需要配置调试...
    99+
    2023-05-23
    Debug phpstorm Xdebug
  • 如何远程调试Python代码
    这是一篇小记。平时使用python写的代码对外部依赖性都不复杂,这些代码在本地调试,运行没问题之后,就可以放到生产去跑了。然而,最近的一个项目,由于使用了一些内部服务,需要连接到内部的环境进行调试。如果每次都修改代码之后,发布一次到内部环境...
    99+
    2023-01-31
    代码 Python
  • Linux下如何调试c++代码
    这篇文章主要为大家展示了“Linux下如何调试c++代码”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Linux下如何调试c++代码”这篇文章吧。Linux下调试C++代码具体方法1.编写好代码...
    99+
    2023-06-28
  • Joyent中怎么调试Node代码
    Joyent中怎么调试Node代码,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。“Node.js使用JavaScript并具备动态特性,”...
    99+
    2024-04-02
  • YOLOv8代码调试运行实战
    YOLOv8代码调试运行实战 YOLOv8入坑出坑。 1.创建虚拟环境 创建:conda create -n yolov8 python=3.8 conda create -n yolov8 pyth...
    99+
    2023-10-02
    python 开发语言 目标检测 pytorch 计算机视觉
  • VScode + PHPstudy + PHP Debug 调试PHP代码
    找了好多文章写个流程笔记记录下,整了几天终于搞定了(毕竟我是小白萌新)。 下载小皮面板 https://www.xp.cn/download.html下载vscode https://code.vis...
    99+
    2023-09-03
    php vscode apache
  • Linux下怎么调试python代码
    本篇内容介绍了“Linux下怎么调试python代码”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Linux下调试pytho代码具体方法日志...
    99+
    2023-06-28
  • 如何调试和测试SQL拼接代码
    调试和测试SQL拼接代码的步骤如下: 使用日志输出:在拼接SQL语句的过程中,可以使用日志输出来打印拼接的结果,以便查看拼接是否...
    99+
    2024-04-29
    SQL
  • 调试JavaScript代码如何打印调用堆栈
    小编给大家分享一下调试JavaScript代码如何打印调用堆栈,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!打印调用堆栈可以通过调试面板查看当前代码的调用堆栈,也...
    99+
    2023-06-27
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作