惯用语走快乐路径

时间:2017-09-03 15:10:41

标签: go idiomatic

假设我们有一个函数返回一些值和一个错误。什么是处理错误和值声明的首选方式?

func example_a(data interface{}) (interface{}, error) {
    var err error
    var bytes []byte
    if bytes, err = json.Marshal(data); err != nil {
        return nil, err
    }
    // ... 
    return use(bytes), nil
}

func example_b(data interface{}) (interface{}, error) {
    if bytes, err := json.Marshal(data); err != nil {
        return nil, err
    } else {
        // ... 
        return use(bytes), nil
    }
}

func example_c(data interface{}) (result interface{}, err error) {
    var bytes []byte
    if bytes, err = json.Marshal(data); err != nil {
        return
    }
    // ... 
    return use(bytes), nil
}

func example_d(data interface{}) (interface{}, error) {
    bytes, err := json.Marshal(data)
    if err != nil {
        return nil, err
    }
    // ... 
    return use(bytes), nil
}

func example_dream(data interface{}) (interface{}, error) {
    if bytes, err ≡ json.Marshal(data); err != nil {
        return nil, err
    }
    // ... 
    return use(bytes), nil
}

示例A 很明显,但它增加了2行。此外,我发现不清楚为什么在这种特殊情况下我们应该使用var,同时:=并不总是合适的。然后你想在某个地方重用err声明,而且我不是分裂声明和赋值的忠实粉丝。

示例B 正在使用if-declare-test语言功能,我猜这是鼓励的,但同时你也被迫嵌套函数延续违反了happy-path原则,鼓励。

示例C 使用命名参数返回功能,这是A和B之间的内容。这里最大的问题是,如果您的代码库使用样式B和C,那么它就是' s很容易误认为:==,这可能会导致各种问题。

示例D (从建议中添加)对我来说有与C相同的使用问题,因为我不可避免地遇到以下情况:

func example_d(a, b interface{}) (interface{}, error) {
    bytes, err := json.Marshal(a)
    if err != nil {
        return nil, err
    }

    bytes, err := json.Marshal(b) //Compilation ERROR
    if err != nil {
        return nil, err
    }

    // ... 
    return use(bytes), nil
}

因此,根据以前的声明,我必须修改我的代码以使用:==,这使得查看和重构更加困难。

示例梦想是我从GO直觉上所期望的 - 没有嵌套,快速退出而没有太多的冗长和可变重用。显然它没有编译。

通常会use()内联并多次重复该模式,从而导致嵌套或拆分声明问题。

那么处理这种多重回报和声明的最惯用方法是什么?是否有我失踪的模式?

1 个答案:

答案 0 :(得分:5)

如果你看看很多Go代码,你会发现以下情况通常是这样的:

func example(data interface{}) (interface{}, error) {
    bytes, err := json.Marshal(data)
    if err != nil {
        return nil, err
    }
    // ... 
    return use(bytes), nil
}

声明和测试if构造是否很好,但这里通常不合适。