Go 重构:尽量避免使用 else、break 和 continue

简介: Go 重构:尽量避免使用 else、break 和 continue

今天,我想谈谈相当简单的事情。我不会发明什么,但我在生产代码中经常看到这样的事情,所以我不能回避这个话题。


我经常要解开多个复杂的 if else 结构。多余的缩进、过多的逻辑只会加深理解。首先,这篇文章的主要目的是让代码更透明、更易读。不过,在某些情况下还是必须使用这些操作符。


else 操作

例如,我们有简单的用户处理程序:


func handleRequest(user *User) {
    if user != nil {
        showUserProfilePage(user)
    } else {
        showLoginPage()
    }
}


如果没有提供用户,则需要将收到的请求重定向到登录页面。If else 似乎是个不错的决定。但我们的主要任务是确保业务逻辑单元在任何输入情况下都能正常工作。因此,让我们使用提前返回来实现这一点。


func handleRequest(user *User) {
    if user == nil {
        return showLoginPage()
    } 
    showUserProfilePage(user)
}


逻辑是一样的,但是下面的做法可读性会更强。


break 操作


对我来说,BreakContinue 语句总是可以分解的信号。


例如,我们有一个简单的搜索任务。找到目标并执行一些业务逻辑,或者什么都不做。


func processData(data []int, target int) {
    for i, value := range data {
        if value == target {
            performActionForTarget(data[i])
            break
        }
    }
}


你应该始终记住,使用 break 操作符并不能保证整个数组都会被处理。这对性能有好处,因为我们丢弃了不必要的迭代,但对代码支持和可读性不利。因为我们永远不知道程序会在列表的开头还是结尾停止。


在某些情况下,带有子任务的简单功能可能会破坏这段代码。


func processData(data []int, target int, subtask int) {
    for i, value := range data {
        if value == subtask {
            performActionForSubTarget(data[i])
        }
        if value == target {
            performActionForTarget(data[i])
            break
        }
    }
}


这样我们实际上可以拆出一个 find 的方法:


func processData(data []int, target int, subTarget int) {
    found := findTarget(data, target)
    if found > notFound {
        performActionForTarget(found)
    }
    found = findTarget(data, subTarget)
    if found > notFound {
        performActionForSubTarget(found)
    }
}
const notFound = -1
func findTarget(data []int, target int) int {
    if len(data) == 0 {
        return notFound
    }
    for _, value := range data {
        if value == target {
            return value
        }
    }
    return notFound
}


同样的逻辑,但是拆分成更细粒度的方法,也有精确的返回语句,可以很容易地通过测试来实现。

continue 操作


该操作符与 break 类似。为了正确阅读代码,您应该牢记它对操作顺序的具体影响。


func processWords(words []string, substring string) {
    for _, word := range words {
        if !strings.Contains(word, substring) {
            continue
        }
        
        // do some buisness logic
        performAction(word)
    }
}


Continue 使得这种简单的流程变得有点难以理解。


让我们写得更简洁些:

func processWords(words []string, substring string) {
    for _, word := range words {
        if strings.Contains(word, substring) {
            performAction(word)
        }
    }
}
相关文章
|
16天前
|
算法 测试技术 Go
|
3月前
|
监控 Go
go语言并发实战——日志收集系统(十) 重构tailfile模块实现同时监控多个日志文件
go语言并发实战——日志收集系统(十) 重构tailfile模块实现同时监控多个日志文件
|
4月前
|
程序员 Go 开发者
Go语言中的跳转控制结构:`goto`、`break` 和 `continue`
【2月更文挑战第3天】在Go语言中,跳转控制结构允许程序员直接控制程序的执行流程,通过`goto`、`break`和`continue`关键字实现代码的跳转、退出循环或跳过循环的某次迭代。本文将深入探讨这些跳转控制结构的使用场景、注意事项以及最佳实践,帮助读者更好地理解和应用Go语言中的跳转控制结构。
|
11月前
|
Go
这些套路,教你灵活运用Go语言continue语句
这些套路,教你灵活运用Go语言continue语句
73 0
|
Java Go C++
三分钟学 Go 语言——循环语句的多种形式、死循环、break/continue
三分钟学 Go 语言——循环语句的多种形式、死循环、break/continue
三分钟学 Go 语言——循环语句的多种形式、死循环、break/continue
|
Go C++
Go-分支和循环总结(if、else、switch、for、range、continue、break等)
Go-分支和循环总结(if、else、switch、for、range、continue、break等)
101 0
Go-分支和循环总结(if、else、switch、for、range、continue、break等)
|
Go 索引
Go基础:range、循环控制Goto、Break、Continue
Go基础:range、循环控制Goto、Break、Continue
267 0
|
6天前
|
程序员 Go PHP
为什么大部分的 PHP 程序员转不了 Go 语言?
【9月更文挑战第8天】大部分 PHP 程序员难以转向 Go 语言,主要因为:一、编程习惯与思维方式差异,如语法风格和编程范式;二、学习成本高,需掌握新知识体系且面临项目压力;三、职业发展考量,现有技能价值及市场需求不确定性。学习新语言虽有挑战,但对拓宽职业道路至关重要。
35 10