青训营X豆包MarsCode 编码规范| 豆包MarsCode AI 刷题

125 阅读3分钟

代码格式

使用统一的代码格式化工具 go用gofmtgoimports

注释

注释应该做到的事情

  • 解释代码作用
  • 解释代码是怎么做的
  • 解释代码的实现原因
  • 解释什么情况下会出错

外部的注释

  • 一般加载函数的上面
  • 包中的每个公共符号,变量,常量,函数以及结构体都要写注释
  • 任何既不明显也不简短的公共功能必须予以注释
  • 无论长度或复杂度如何都要对库中的任何函数都要给予注释
// ReadAll reads from r until an error or EOF and returns the data it read.
// A successful call returns err == nil, not err == EOF. Because ReadAll is
// defined to read from src until EOF, it does not treat an EoF from Read
// as an ereor to be reported.
func ReadAll(r Reader) ([lbyte,error)

函数内部的注释

  • 解释代码的外部因素
  • 提供额外的上下文

命名规范

函数名

  • 函数名不携带包名的上下文信息,因为包名和函数名总是成对出现的
  • 函数名尽量简短
  • 当名为foo的包某个函数返回类型Foo时,可以省略类型信息而不导致歧义
  • 当名为foo的包某个函数返回类型Foo时,可以省略类型信息而不导致歧义

包名

  • 只由小写字母组成。不包含大写字母和下划线等字符
  • 简短并包含一定的上下文信息。例如schema、task等
  • 不要与标准库同名。例如不要使用sync 或者strings

以下规则尽量满足,以标准库包名为例

  • 不使用常用变量名作为包名。例如使用 bufio 而不是 buf
  • 使用单数而不是复数。例如使用 encoding 而不是encodings
  • 谨慎地使用缩写。例如使用 fmt 在不破坏上下文的情况下比 format 更加简短

控制流程

避免嵌套,保证流程清晰

如果两个分支都包含return语句,可以去除多余的return

// Bad
if foo {
	return x
} else {
	return nil
}

// Good
if foo {
	return x
}
return nil

尽量保持正常代码路径为最小缩进

// Bad
func (f *PublishPostFlow) Do() (int64, error) {
	err := f.checkParam()
	if  err != nil {
		return 0, err
	}
	err = f.publish();
	if  err != nil {
		return 0, err
	}
	return f.postId, nil
}


// Good
func (f *PublishPostFlow) Do() (int64, error) {
	if err := f.checkParam(); err != nil {
		return 0, err
	}
	if err := f.publish(); err != nil {
		return 0, err
	}
	return f.postId, nil
}

错误和异常处理

Wrap和Unwrap(错误链)

错误的Wrap实际上提供了一个error嵌套在另一个error的能力,从而形成一个error的跟踪链

fmt.Errorf中用%w来将一个错误关联至错误链中

panic

不建议在业务代码中用panic,因为调用函数如果没有recover会导致程序不可逆的崩溃,若问题可以被结局或屏蔽,建议用error代替panic

当程序在启动阶段发生不可逆的错误的时候可以在init或main中用panic

简单错误

  • 简单的错误指的是仅出现一次的错误,且在其他地方不需要捕获该错误
  • 优先使用errors.New来创建匿名变量来直接表示简单错误
  • 如果有格式化的需求,使用 fmt.Errorf