V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
find456789
V2EX  ›  问与答

Swift 里的 guard 完全可以用 if 代替呀,为什么要弄个 guard 呀?

  •  
  •   find456789 · 2021-05-22 22:50:34 +08:00 · 1420 次点击
    这是一个创建于 1266 天前的主题,其中的信息可能已经有所发展或是发生改变。

    实在想不通,这个语法糖存在的价值是啥, 还希望各位前辈指点一下

    
    func guard11(age:Int?) {
        guard  age! > 18 else {
            print("guard:你没有成年,不许进入,\(age!)")
            return
        }
        print("guard:你是成年人,可以饮酒了,\(age!)")
    }
    
    guard11(age: 17)
    guard11(age: 19)
     
     
     
     func if22(age:Int?){
        if !(age! > 18) {
            print("if:你没有成年,不许进入,\(age!)")
            return
        }
        print("if:你是成年人,可以饮酒了,\(age!)")
     }
    
     if22(age: 17)
     if22(age: 19)
    
    
    
    
    7 条回复    2021-08-23 11:04:47 +08:00
    zacksz
        1
    zacksz  
       2021-05-23 04:20:23 +08:00   ❤️ 1
    我的理解是,`guard` 是用来做前置条件检查的。

    对于每个函数,大体上有个流程:先对输入进行前置条件检查,再对输入进行处理,从而进行输出。`guard` 就是用于第一步的。和 `if` 不同的是, `guard` 块中必须改变程序控制流(`return`, `break`, `continue`, `throw`)。

    回到你的程序样例中,这个函数有这么些前置条件:`age` 需要是非 `Nil`,其次 `age` 需要大于 18 。因此,实现应该是这样的:

    ```swift
    func enterBar(age: Int?) {
    // 前置条件检查
    guard let age = age else {
    print("输入数据为空。")
    return
    }
    guard age > 18 else {
    print("你没有成年,不许进入")
    return
    }

    // 对 输入数据进行处理
    if age < 30 {
    enterYoungArea()
    } else {
    enterSeniorArea()
    }
    }
    ```
    66450146
        2
    66450146  
       2021-05-23 07:40:05 +08:00 via iPhone   ❤️ 1
    guard 里如果没有退出这个 block 的话会报错,给了用户一个防止自己犯低级错误的工具
    duhb
        3
    duhb  
       2021-05-23 09:41:24 +08:00 via iPhone   ❤️ 1
    写 swift 记住两个字:安全!
    agagega
        4
    agagega  
       2021-05-23 20:22:49 +08:00   ❤️ 1
    在 guard let 的时候就有用了
    vincentxue
        5
    vincentxue  
       2021-05-23 21:54:05 +08:00   ❤️ 2
    我觉得楼上的都没回答到点子上,能用 guard 的地方也完全可以使用 if,但是 guard 关键字存在的理由有以下几点:

    1. guard 的主要作用是中止执行或者退出当前作用域。使用此关键字我表达的意思是如果 cond 不满足,一定会跳出当前作用域。else 中没有终止执行的代码(如 return / fatal / throw 等)不会被编译通过。if 做不到这一点。像你的 if22 函数,如果 return 没有写,一样可以编译通过,但是 guard11 就不行。

    2. guard let 变量可以在作用域外访问。if let 做不到这一点。

    3. guard 没有增加额外的作用域。if 做不到这一点。


    通常应该优先使用 guard,这样会让代码更清晰。

    你这两个函数的实现是有问题的,Swift 是一个安全的语言,应该尽量避免强行解包,你应该先尝试解包,然后再执行你的逻辑。在解包过程中你就能感受到 guard 和 if 的区别了。下面是 demo 。

    https://gist.github.com/VincentSit/e0755219fce38c7df213073490d42a98
    aec4d
        6
    aec4d  
       2021-08-22 17:56:41 +08:00
    @vincentxue 第二三点说到作用域上有点让人费解,觉得更好的说辞是对 option 进行前置处理后提取出值,方便后续使用,避免花括号层级嵌套。
    和 Kotlin 的可空类型智能转换差不多作用
    vincentxue
        7
    vincentxue  
       2021-08-23 11:04:47 +08:00
    @aec4d 一个花括号对不就是一个作用域吗..
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   965 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 21:15 · PVG 05:15 · LAX 13:15 · JFK 16:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.