10

善用闭包(closure)让Go代码更优雅

 3 years ago
source link: https://jiajunhuang.com/articles/2020_04_21-use_closure.md.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

善用闭包(closure)让Go代码更优雅

通常来说我们降低一个函数的复杂度的方法是拆分。即大事化小,各个击破的原理。不过拆分成函数调用有一个问题,那就是修改 函数参数的时候很蛋疼。

比如,原本由于各种原因我们有一个巨长的函数,他的作用是发工资:

func loooooooooooog(userID int) {
    // 比如1000行代码
}

因为我们要拆分成若干个小函数,这自然是一件好事情,降低了变量之间的依赖:

func loooooooooooog(userID int) {
    checkUser(userID)
    checkSalary(userID)
    Send(userID, salary)
    Notify(userID)
}

但是现在我们决定引入 Context,用以随时取消Goroutine的执行,当然啦,在Go里没法自动取消,只能手动档:

func checkUser(ctx context.Context, userID int) error {
    select {
        case <-ctx.Done():
            err := ctx.Err()
            log.Printf("ctx is done for %s", err)
            return err
        default:
    }

    // blablabla 业务代码
}

同样的代码还会出现在若干个子函数中,例如 checkSalary, Send, Notify等等。难道有谁愿意写这么多重复的代码吗? 至少我不愿意,所以捏,我决定创造一个函数,取缔这些重复的context检查,幸好Go支持闭包,要不然就不好弄了:

// Execute execute fn until ctx.Done() is received
func Execute(ctx context.Context, fn func()) error {
    select {
    case <-ctx.Done():
        err := ctx.Err()
        log.Printf("ctx is done for %s", err)
        return err
    default:
        return fn()
    }
}

那么接下来我就可以这样用了:

func loooooooooooog(ctx context.Context, userID int) {
    Execute(ctx, func() error {/*业务代码在这里*/})
    Execute(ctx, func() error {/*业务代码在这里*/})
}

不过,没有银弹。这样做又带来了一个副作用,由于闭包是可以访问外层函数的变量的,也就意味着还是有可能产生变量混用的可能性, 但是我认为这个可以人为消除,也就是说,写的时候注意,不是公共变量的,不要乱用,尽量在匿名函数内使用内部变量,当然也不是 没有解决方案,那就是外边包装一层匿名函数+调用,不过那样的缺点就是更复杂了,没有关系,我们手动控制好即可。

所以说是 “善用”闭包,任何东西,都要拿捏好,不能滥用的。


参考资料:


微信公众号
关注公众号,获得及时更新

GCC默认的头文件搜索路径

读《远见-如何规划职业生涯3大阶段》

后端工程师学前端(五): SASS

后端工程师学前端(四): CSS进阶(盒子模型)

读《投资中最简单的事》

后端工程师学前端(三): CSS进阶(特指度、单位和字体族)

后端工程师学前端(二): CSS基础知识(规则与选择器)

Swift语法笔记

后端工程师学前端(一): HTML

读《管理的实践》

frp 源码阅读与分析(二):TCP内网穿透的实现

五天不用微信 - 爽得很

frp 源码阅读与分析(一):流程和概念

学习frp源码之简洁的在两个connection之间转发流量

自己动手写一个反向代理




About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK