V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NicolayShi
V2EX  ›  PHP

请教大家一段 golang 代码,为什么会输出两个 nil ~

  •  
  •   NicolayShi · 2019-04-19 16:33:06 +08:00 · 4295 次点击
    这是一个创建于 2080 天前的主题,其中的信息可能已经有所发展或是发生改变。
    package main
    
    import (
        "errors"
        "fmt"
    )
    
    var ErrDidNotWork = errors.New("did not work")
    
    func DoTheThing(reallyDoIt bool) (err error) {
        if reallyDoIt {
            result, err := tryTheThing()
            if err != nil || result != "it worked" {
                err = ErrDidNotWork
            }
        }
        return err
    }
    
    func tryTheThing() (string,error)  {
        return "",ErrDidNotWork
    }
    
    func main() {
        fmt.Println(DoTheThing(true))
        fmt.Println(DoTheThing(false))
    }
    
    15 条回复    2019-04-20 04:02:31 +08:00
    NicolayShi
        1
    NicolayShi  
    OP
       2019-04-19 16:34:09 +08:00
    有说因为 if 语句块内的 err 变量会遮罩函数作用域内的 err 变量,但是没看懂。
    slicent8
        2
    slicent8  
       2019-04-19 16:36:29 +08:00
    package main

    import (
    "errors"
    "fmt"
    )

    var ErrDidNotWork = errors.New("did not work")

    func DoTheThing(reallyDoIt bool) (err error) {
    if reallyDoIt {
    result, err1 := tryTheThing()
    if err1 != nil || result != "it worked" {
    err = ErrDidNotWork
    }
    }
    return err
    }

    func tryTheThing() (string,error) {
    return "",ErrDidNotWork
    }

    func main() {
    fmt.Println(DoTheThing(true))
    fmt.Println(DoTheThing(false))
    }
    thuai
        3
    thuai  
       2019-04-19 16:39:10 +08:00
    DoTheThing 的返回值带了名字与 if 语句中的 err:= 冲突了,命名返回值是相当于声明了 err 变量,err := 又做了一次
    fighterlyt
        4
    fighterlyt  
       2019-04-19 16:39:44 +08:00
    确实是因为 result, err := tryTheThing()中的 err 屏蔽了外层的 err,所以外层 err 没有变化
    Junjunya
        5
    Junjunya  
       2019-04-19 16:40:54 +08:00
    err 在 if 里面重新被声明并且赋值了,属于局部变量 。

    而 rerturn 的 err 是在 在 return_types 位置声明的。 并且 一直没有赋值,所以一直都是 nil
    Heavytiger
        6
    Heavytiger  
       2019-04-19 16:41:52 +08:00
    (err error)
    err = nil

    因为这个。
    qq316107934
        7
    qq316107934  
       2019-04-19 16:45:25 +08:00
    qq316107934
        8
    qq316107934  
       2019-04-19 16:46:55 +08:00
    ```
    package main

    import (
    "fmt"
    "errors"
    )

    func main() {
    DoTheThing(true)
    }

    func DoTheThing(reallyDoIt bool) (err error) {
    err = errors.New("Custom Error 0")
    fmt.Println(err)
    if reallyDoIt {
    err := errors.New("Custom Error 1")
    fmt.Println(err)
    if err != nil {
    err := errors.New("Custom Error 2")
    fmt.Println(err)
    }
    fmt.Println(err)
    }
    fmt.Println(err)
    return err
    }

    ```
    跑下这个有助于你理解 @NicolayShi #1
    qq316107934
        9
    qq316107934  
       2019-04-19 16:47:25 +08:00
    顺便问句这个为啥在 PHP 节点
    dust09
        10
    dust09  
       2019-04-19 16:51:03 +08:00
    DoTheThing 函数内 err 不是同一个
    ````go
    package main

    import (
    "errors"
    "fmt"
    )

    var ErrDidNotWork = errors.New("did not work")

    func DoTheThing(reallyDoIt bool) (err error) {
    fmt.Println("err:",&err)
    if reallyDoIt {
    result, err := tryTheThing()
    if err != nil || result != "it worked" {
    err = ErrDidNotWork
    }
    fmt.Println("err:",&err)
    }
    return err
    }

    func tryTheThing() (string,error) {
    return "",ErrDidNotWork
    }

    func main() {
    fmt.Println(DoTheThing(true))
    fmt.Println(DoTheThing(false))
    }
    ````
    NicolayShi
        11
    NicolayShi  
    OP
       2019-04-19 17:00:51 +08:00
    十分感谢大家,在此统一回复,因为没找到 golang 节点自己工作又是写 php,所以就在 php 节点提问了,所以我是没搞清楚 golang 的变量作用域是么(掩面哭泣 emoj )~
    janxin
        12
    janxin  
       2019-04-19 17:47:54 +08:00
    @NicolayShi 是的,如果你使用 GoLand 之类的 IDE,会有波浪线提醒你这里使用有问题的,不如考虑一下?
    johz
        13
    johz  
       2019-04-19 17:55:07 +08:00
    是作用域问题,:=赋值之后 err 变量覆盖了
    这样就好了:
    package main

    import (
    "errors"
    "fmt"
    )

    var ErrDidNotWork = errors.New("did not work")

    func DoTheThing(reallyDoIt bool) (err error) {
    if reallyDoIt {
    result, err2 := tryTheThing()
    if err2 != nil || result != "it worked" {
    err = ErrDidNotWork
    }
    }
    return err
    }

    func tryTheThing() (string,error) {
    return "",ErrDidNotWork
    }

    func main() {
    fmt.Println(DoTheThing(true))
    fmt.Println(DoTheThing(false))
    }

    自己体会一下~
    Mitt
        14
    Mitt  
       2019-04-19 20:07:05 +08:00 via iPhone
    := 这个语法很坑爹我觉得,很多时候图一下方便就容易踩坑
    unlimitedsola
        15
    unlimitedsola  
       2019-04-20 04:02:31 +08:00
    改成这样也是可以的

    ```go
    package main

    import (
    "errors"
    "fmt"
    )

    var ErrDidNotWork = errors.New("did not work")

    func DoTheThing(reallyDoIt bool) (err error) {
    result := ""
    if reallyDoIt {
    result, err = tryTheThing()
    if err != nil || result != "it worked" {
    err = ErrDidNotWork
    }
    }
    return err
    }

    func tryTheThing() (string, error) {
    return "", ErrDidNotWork
    }

    func main() {
    fmt.Println(DoTheThing(true))
    fmt.Println(DoTheThing(false))
    }
    ```
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1418 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 17:26 · PVG 01:26 · LAX 09:26 · JFK 12:26
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.