前言
这是Go常见错误系列的第12篇:Go语言中冗余的嵌套代码,俗称箭头型代码。
素材来源于Go布道者,现Docker公司资深工程师Teiva Harsanyi。
本文涉及的源代码全部开源在:Go常见错误源代码,欢迎大家关注公众号,及时获取本系列最新更新。
常见错误
我们先看看如下的代码:
func join(s1, s2 string, max int) (string, error) {
if s1 == "" {
return "", errors.New("s1 is empty")
} else {
if s2 == "" {
return "", errors.New("s2 is empty")
} else {
concat, err := concatenate(s1, s2)
if err != nil {
return "", err
} else {
if len(concat) > max {
return concat[:max], nil
} else {
return concat, nil
}
}
}
}
}
func concatenate(s1 string, s2 string) (string, error) {
// ...
}
这段代码要做的事情很简单:
- 把两个字符串s1和s2拼接起来,如果长度超过max,就只返回长度为max的子串。
- 实现过程中,对s1和s2做了判空;对concatenate返回值有无error做了判断;
从功能正确性的角度来说,代码完全没有毛病。但是看着很费劲,因为嵌套了很多层。
优化版本
我们对上面的多层嵌套代码优化如下:
func join(s1, s2 string, max int) (string, error) {
if s1 == "" {
return "", errors.New("s1 is empty")
}
if s2 == "" {
return "", errors.New("s2 is empty")
}
concat, err := concatenate(s1, s2)
if err != nil {
return "", err
}
if len(concat) > max {
return concat[:max], nil
}
return concat, nil
}
func concatenate(s1 string, s2 string) (string, error) {
// ...
}
这段代码实现了和刚才完全一样的功能,但是可读性好很多。
那有什么最佳实践我们可以作为参考,来规范代码实现呢?
最佳实践
通常来说,函数里的代码嵌套的层次越多,可读性就越差。可以参考如下原则来规范代码编写:
当if语句里会return时,那不要继续用else了,直接把else里的内容和if放在同一个层次。
bad case:
if foo() { // ... return true } else { // ... }
good case:
if foo() { // ... return true } // ...
如果修改判断条件,可以减少嵌套层次,可以考虑对判断条件做调整。示例如下:
bad case:
if s != "" { // ... } else { return errors.New("empty string") }
good case:
if s == "" { return errors.New("empty string") } // ...
归纳上面2个原则,其实就是能先return的就先return,减少不必要的代码嵌套。
感兴趣的也可以看看参考资料里"左耳朵耗子"写过的一篇文章"如何重构箭头型代码",
下一篇文章,我们会讲解下Go语言里init函数的常见错误和最佳实践。
推荐阅读
- Go面试题系列,看看你会几题?
- Go常见错误第1篇:未知枚举值
- Go常见错误第2篇:benchmark性能测试的坑
- Go常见错误第3篇:go指针的性能问题和内存逃逸
- Go常见错误第4篇:break操作的注意事项
- Go常见错误第5篇:Go语言Error管理
- Go常见错误第6篇:slice初始化常犯的错误
- Go常见错误第7篇:不使用-race选项做并发竞争检测
- Go常见错误第8篇:并发编程中Context使用常见错误
- Go常见错误第9篇:使用文件名称作为函数输入
- Go常见错误第10篇:Goroutine和循环变量一起使用的坑
- Go常见错误第11篇:意外的变量遮蔽(variable shadowing
开源地址
文章和示例代码开源在GitHub: Go语言初级、中级和高级教程。
公众号:coding进阶。关注公众号可以获取最新Go面试题和技术栈。
个人网站:Jincheng's Blog。
知乎:无忌。
福利
我为大家整理了一份后端开发学习资料礼包,包含编程语言入门到进阶知识(Go、C++、Python)、后端开发技术栈、面试题等。
关注公众号「coding进阶」,发送消息 backend 领取资料礼包,这份资料会不定期更新,加入我觉得有价值的资料。
发送消息「进群」,和同行一起交流学习,答疑解惑。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。