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

2019-04-19 16:33:06 +08:00
 NicolayShi
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))
}
4069 次点击
所在节点    PHP
15 条回复
NicolayShi
2019-04-19 16:34:09 +08:00
有说因为 if 语句块内的 err 变量会遮罩函数作用域内的 err 变量,但是没看懂。
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
2019-04-19 16:39:10 +08:00
DoTheThing 的返回值带了名字与 if 语句中的 err:= 冲突了,命名返回值是相当于声明了 err 变量,err := 又做了一次
fighterlyt
2019-04-19 16:39:44 +08:00
确实是因为 result, err := tryTheThing()中的 err 屏蔽了外层的 err,所以外层 err 没有变化
Junjunya
2019-04-19 16:40:54 +08:00
err 在 if 里面重新被声明并且赋值了,属于局部变量 。

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

因为这个。
qq316107934
2019-04-19 16:45:25 +08:00
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
2019-04-19 16:47:25 +08:00
顺便问句这个为啥在 PHP 节点
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
2019-04-19 17:00:51 +08:00
十分感谢大家,在此统一回复,因为没找到 golang 节点自己工作又是写 php,所以就在 php 节点提问了,所以我是没搞清楚 golang 的变量作用域是么(掩面哭泣 emoj )~
janxin
2019-04-19 17:47:54 +08:00
@NicolayShi 是的,如果你使用 GoLand 之类的 IDE,会有波浪线提醒你这里使用有问题的,不如考虑一下?
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
2019-04-19 20:07:05 +08:00
:= 这个语法很坑爹我觉得,很多时候图一下方便就容易踩坑
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))
}
```

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/556819

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX