行之有效的Golang编码规范

编码规范

熟悉编码规范可以帮助我们写出可读性高,可测试性高的代码
同时编码规范也是小型重构的利器,现在我们从命名,变量,循环,注释,函数等方面,谈谈如何从编码角度提升整体项目质量。

命名

  1. 命名的首要要求是准确直观地表达意图,次要要求是简短。

除了一些大家比较熟知的缩写外,不推荐使用缩写。
比如:sec 表示 second、str 表示 string、num 表示 number、doc 表示 document。

  1. 命名的技巧是:动词➕宾语,也就是"谁干了什么事"
    比如:AddTopicDynamic => 添加主题动态

动词-Add 宾语-TopicDynamic

  1. 用意义明确的常量代替魔法数字

有一次遇到一个if判断,心里已经MMP了,鬼知道这个 count*5 代表什么意思😝

if (groupCount < count*5) {
    // 业务代码
}
  1. 分组命名常量
    比如:redis的key
Dynamics      = "xxx"   // hash
GlobalDynamic = "xxx"   // 全局动态
DynamicPushed = "xxx"   // 用于标记动态是否已推送
-------------------------------------------------
// 使用前缀Key将常量分组,可读性更强
KeyDynamics      = "xxx"   // hash
KeyGlobalDynamic = "xxx"   // 全局动态
KeyDynamicPushed = "xxx"   // 用于标记动态是否已推送

变量

  1. 要控制变量的作用域,应该private的变量绝不public。
  2. 要控制变量的存活时间,变量的存活时间越短,代码越易读,重构起来越简单。
    比如:在变量即将被使用时再初始化
// 优化前
func Demo() {
    paramA := "A"
    // 业务代码1
    
    // 业务代码2
    paramA = "B"
}
---------------------------------------
// 在变量即将被使用时再初始化,缩短变量生命周期
func Demo() {
    // 业务代码1
    
    // 业务代码2
    paramA := "A"
    paramA = "B"
}
  1. 用布尔变量优化布尔判断
// 优化前
// 判断是否是提问者,主题必须已回答(answererId > 0) 且不能是自问自答(actorId != answererId)
func IsQuestioner(questionerId int64, actorId int64, answererId int64) bool {
	return actorId == questionerId && actorId != answererId && answererId > 0
}
----------------------------------------------------------------------------------
// 用布尔变量优化布尔判断
// 判断是否是提问者,主题必须已回答(answererId > 0) 且不能是自问自答(actorId != answererId)
func IsQuestioner(questionerId int64, actorId int64, answererId int64) bool {
	isQuestioner := actorId == questionerId // 是提问者
	isNotAnswer := actorId != answererId    // 不是回答者
	isAlreadyAnswered := answererId > 0     // 问题已经回答
	
	return isQuestioner && isNotAnswer && isAlreadyAnswered
}

控制语句(for语句&if语句)

  1. 一个循环只做一件事。
  2. 循环的内务操作(比如index++这种),要么放在循环开头,要么放在循环结尾。
  3. 长循环使用有意义的循环变量名,并且可以把部分内容抽成一个子函数。
  4. 函数内或循环内做数据校验时(比如if判断),合理使用continue,break,return,让正常路径变得清晰。
  5. 最多嵌套两层循环。

第四点和第五点看下面这个示例

// 假设下面是一段根据审核结果做相应操作的代码
// 嵌套了3层if判断,最后执行业务代码
func ReviewTopicHandler(reviewResult interface) (err error) {
	if reviewResult.IsValid() {
		if reviewResult.IsTopicType() {
			if reviewResult.GetStatus() != topic.StatusNormal {
                // 业务操作
				return
			}
		}
	}

	return 
}
------------------------------------------------------------
// 根据第四点和第五点的观念,利用return优化调嵌套if
func ReviewTopicHandler(reviewResult interface) (err error) {
	if !reviewResult.IsValid() {
		Logger.Warnf("review result is invalid")
		return
	}
	if !reviewResult.IsTopicType() {
		Logger.Debugf("It's not a topic review result")
		return
	}
	if reviewResult.GetStatus() == topic.StatusNormal {
		Logger.Debugf("a normal topic. No any operation")
		return
	}

    // 业务操作
	return 
}

注释

提倡高效注释,不合理的注释只会帮倒忙。

  1. 不要用注释将你写的代码用文字翻译一遍。
  2. 不要尝试用注释解释晦涩难懂的代码,正确的做法是重构代码。
  3. 最好可以用一句话概述代码块做了什么。

心态:面向离职写注释

函数

  1. 函数不能过长,过长的函数不易测试,从中抽离出一些功能内聚的代码作为子函数,其可读性,可测试性,可复用性,可扩展性都会显著提高。
  2. 利用空行分割代码块,可以让代码逻辑更清晰
  3. 尽量让函数内聚,只做一件事。(单一职责原则)
// 假设下面这个函数负责构建一段将要推送给用户的文本。
// 因为能推送给终端用户的内容有限,每个文本都限制了字符串长度,如下图所示
// 优化方案:"限制文本长度"是一个功能非常内聚的函数(符合单一职责),
// 将它抽离成单独的函数,可以更好的复用代码,并且针对这个函数的单元测试也是十分高效的。
func (s *Service) BuildContent() {
	var text string
	textRune := []rune(s.Text)
	if len(textRune) > ImMessageLength {
		text =  string(textRune[0:ImMessageLength-3]) + "..."
	}
	var nickName string
	nickNameRune := []rune(s.User.Nickname)
	if len(nickNameRune) > UserNameMaxLength {
		nickName =  string(nickNameRune[0:UserNameMaxLength-3]) + "..."
	}

	// 业务代码
	
	s.Content = nickName + text
}
---------------------------------------------------------
// 抽离出函数:SpiltOverMaxLenString
func (s *Service) BuildContent() {
	text := SpiltOverMaxLenString(s.Text, ImMessageLength)
	nickName := SpiltOverMaxLenString(s.User.Nickname, UserNameMaxLength)

	// 业务代码
	
	s.Content = nickName + text
}
func SpiltOverMaxLenString(input string, maxLen int) (output string) {
	aliasRune := []rune(input)
	if len(aliasRune) > maxLen {
		return string(aliasRune[0:maxLen-3]) + "..."
	}

	return input
}
  1. 控制函数参数的个数,一般大于6个时可以考虑用对象封装起来。
  2. 不要用函数参数来控制代码逻辑。

这是我在萌新阶段最喜欢干的事,我曾经写过类似这样"离谱"的代码:
这种代码通常可以分解成多个函数,更便于复用,测试

func Demo(action string) {
    switch action {
    case "createTopic": // 业务代码A
    case "createComment": // 业务代码B
    case "createAnswer": // 业务代码C
    }
}
-------------------------------------------
func Demo(isDeleted bool) {
    if (isDeleted) {
        // 业务代码A
    } else {
        // 业务代码B
    }
}

写文章不易,求大家点赞~蟹蟹各位啦~

参考文章:
《代码大全》
《重构:改善既有代码的设计》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
golang开发规范pdf是指一份关于使用Go语言进行开发的规范的电子文档。这份规范的目的是为了提高团队开发效率、代码质量和维护性,确保项目的一致性和可扩展性。 在golang开发规范pdf中,通常会包含以下几个方面的内容: 1. 项目结构:定义项目的目录结构,包括如何组织代码文件、测试文件和配置文件等。这样可以使整个项目更加清晰、易于理解和维护。 2. 命名约定:定义变量、函数、类型和包等的命名规范。良好的命名规范可以增加代码的可读性,并且有助于其他开发人员更好地理解代码。 3. 代码风格: 指定代码缩进、换行、注释、命名等细节。统一的代码风格可以减少开发人员之间的沟通障碍,提高代码的可读性和可维护性。 4. 错误处理:明确规定如何处理错误,使用错误码还是异常处理,以及如何记录错误信息。规范的错误处理可以增加代码的健壮性,降低系统的崩溃风险。 5. 并发处理:定义并发编程的规范,包括使用goroutine、channel和锁等的最佳实践。良好的并发处理规范可以避免死锁和竞态条件等问题,提高系统的性能和稳定性。 6. 单元测试:指导如何编写单元测试,包括测试用例的组织方式、覆盖率要求以及测试结果的处理等。规范的单元测试有助于发现代码的潜在问题,并且可以提供一种自动化验证代码正确性的手段。 7. 文档编写:规范文档的编写方式,包括文档结构、格式规范和文档的更新机制等。清晰、详尽的文档可以减少沟通成本,提高项目的文档管理效率。 通过遵循golang开发规范pdf,开发人员可以更加高效、一致地进行开发,减少出错和重复的工作。此外,规范的开发还有助于多人协作和后期维护,提高整个项目的质量和可持续性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值