ChatGPT解决这个技术问题 Extra ChatGPT

if else语句如何做单行? [复制]

这个问题在这里已经有了答案:C 的三元运算符的惯用 Go 等价物是什么? (13个回答) 去年关闭。

请参阅@accdias 指出的https://golangdocs.com/ternary-operator-in-golang(见评论)

我可以像在 php 中那样在 go (golang) 中编写一个带有变量赋值的简单 if-else 语句吗?例如:

$var = ( $a > $b )? $a: $b;

目前我必须使用以下内容:

var c int
if a > b {
    c = a
} else {
    c = b
}

对不起,如果这个控制语句我不记得名字,我无法在网站内或通过谷歌搜索找到信息。 :/

它被称为三元运算符……不,Go 没有。
我相信你要找的词是“三元”
澄清一下,三元运算符是任何 arity 3 的运算符,即绑定 3 个子表达式的任何运算符。 C 恰好只有一个这样的运算符。这就是为什么它通常被称为三元运算符。不过,它的真名是“条件运算符”。

N
Not_a_Golfer

正如评论所提到的,Go 不支持三元一列。我能想到的最短形式是这样的:

var c int
if c = b; a > b {
    c = a
}

但是请不要这样做,这不值得,只会让阅读您的代码的人感到困惑。


@thoroc我实际上可能会在现实生活中避免这种情况,因为它是不直观的恕我直言,不值得保存2行以降低可读性。
@thoroc,请听听 Not_a_Golfer 怎么说。您应该努力编写可维护的软件,而不是炫耀自己。巧妙的技巧很巧妙,但是下一个阅读您的代码的人(包括几个月/几年内的您)不会欣赏它们。
就可读性而言,这取决于。我认为这更具可读性,但就像其他任何东西一样,它可能会被滥用。如果您需要在 if 块之外声明一个不需要的变量,那么我认为这是一个赢家。
哦,高兴,看看没有三元运算符的 Go 获得了多少。除了所做的可读性注释之外,您还更改了一个懒惰评估的结构,其中只运行一个分支到一个始终运行第一个分支并且可能另外运行第二个分支的分支。
@accdias 不,它在 Go 中不起作用。
R
Raed Shomali

正如其他人提到的,Go 不支持三元单行。然而,我写了一个实用函数,可以帮助你实现你想要的。

// IfThenElse evaluates a condition, if true returns the first parameter otherwise the second
func IfThenElse(condition bool, a interface{}, b interface{}) interface{} {
    if condition {
        return a
    }
    return b
}

这里有一些测试用例来展示如何使用它

func TestIfThenElse(t *testing.T) {
    assert.Equal(t, IfThenElse(1 == 1, "Yes", false), "Yes")
    assert.Equal(t, IfThenElse(1 != 1, nil, 1), 1)
    assert.Equal(t, IfThenElse(1 < 2, nil, "No"), nil)
}

为了好玩,我写了更有用的实用函数,例如:

IfThen(1 == 1, "Yes") // "Yes"
IfThen(1 != 1, "Woo") // nil
IfThen(1 < 2, "Less") // "Less"

IfThenElse(1 == 1, "Yes", false) // "Yes"
IfThenElse(1 != 1, nil, 1)       // 1
IfThenElse(1 < 2, nil, "No")     // nil

DefaultIfNil(nil, nil)  // nil
DefaultIfNil(nil, "")   // ""
DefaultIfNil("A", "B")  // "A"
DefaultIfNil(true, "B") // true
DefaultIfNil(1, false)  // 1

FirstNonNil(nil, nil)                // nil
FirstNonNil(nil, "")                 // ""
FirstNonNil("A", "B")                // "A"
FirstNonNil(true, "B")               // true
FirstNonNil(1, false)                // 1
FirstNonNil(nil, nil, nil, 10)       // 10
FirstNonNil(nil, nil, nil, nil, nil) // nil
FirstNonNil()                        // nil

如果您想使用其中任何一个,可以在此处找到它们https://github.com/shomali11/util


我更喜欢 this answer 中的 If(c bool).Then(a interface{}, b interface{}),它看起来更符合我的习惯
怎么样:If(c bool).Then(a interface{}).Else(b interface{}) 如果只需要初始值,则可以删除 else。甚至像这样:If(c bool).Then(a interface{}).Default(b interface{})
迷人的!感谢分享。
x
xoyuz

我经常使用以下内容:

c := b
if a > b {
    c = a
}

与@Not_a_Golfer 的基本相同,但使用的是 type inference


有同样的缺点:当使用不对称解决方案来满足明显对称的需求时,会使理解复杂化。
同样的缺点是将应该是一个懒惰评估的构造,其中两个分支中只有一个会被使用到一个总是会被评估的分支,有时两者都被评估(在这种情况下,第一次评估是多余的)
根据用例,这仍然可能非常有用。例如 listeningPath := "production.some.com"; if DEBUG { listeningPath := "development.some.com" } 与生产中的三元相同的速度,并且恕我直言,可读性非常好。
我通常会在故意浪费CPU周期时哭泣。
t
thoroc

感谢您指出正确的答案。

我刚刚检查了 Golang FAQ (duh),它清楚地指出,这在语言中不可用:

Go 有 ?: 运算符吗? Go 中没有三元形式。您可以使用以下方法来获得相同的结果: if expr { n = trueVal } else { n = falseVal }

发现可能对该主题感兴趣的其他信息:

Go 中条件结构的 Rosetta 代码

这家伙的 Go 实验中的三元运算符


也可以在一行中:var c int; if a > b { c = a } else { c = b }?但我建议将其保留在 5 行中,以形成一个供读者娱乐的灯块;)
M
Muhammad Soliman

一种可能的方法是使用地图在一行中执行此操作,很简单我正在检查 a > b 如果它是 true 我将 c 分配给 a 否则 b

c := map[bool]int{true: a, false: b}[a > b]

然而,这看起来很神奇,但在某些情况下,由于评估顺序,它可能不是完美的解决方案。例如,如果我正在检查一个对象是否不是 nil 从中获取某些属性,请查看以下代码片段,如果是 myObj equals nil,它将 panic

type MyStruct struct {
   field1 string
   field2 string 
}

var myObj *MyStruct
myObj = nil 

myField := map[bool]string{true: myObj.field1, false: "empty!"}[myObj != nil}

因为地图将在评估条件之前首先创建和构建,所以在 myObj = nil 的情况下,这将只是恐慌。

别忘了提一下,您仍然可以只用一行简单的代码完成条件,请检查以下内容:

var c int
...
if a > b { c = a } else { c = b}

想想你用这种方法浪费的所有努力。您分配了内存,初始化了一个映射,向其中添加了两个条目,对两者进行了全面评估,然后对查找值进行哈希处理,查找然后让 GC 收集映射。是的,它是单线的,但值得吗?它甚至比在 Java 中执行 Optional.ofNullable(x).ifPresent(...) 还要糟糕。
u
user2680100

语言中有一个非常相似的结构

**if <statement>; <evaluation> {
   [statements ...]
} else {
   [statements ...]
}*

*

IE

if path,err := os.Executable(); err != nil {
   log.Println(err)
} else {
   log.Println(path)
}

A
Alice Vixie

使用 lambda 函数代替三元运算符

示例 1

给出最大 int

package main

func main() {

    println( func(a,b int) int {if a>b {return a} else {return b} }(1,2) )
}

示例 2

假设您有此 must(err error) 函数来处理错误,并且您想在不满足条件时使用它。 (在https://play.golang.com/p/COXyo0qIslP享受)

package main

import (
    "errors"
    "log"
    "os"
)

// must is a little helper to handle errors. If passed error != nil, it simply panics.
func must(err error) {
    if err != nil {
        log.Println(err)
        panic(err)
    }
}

func main() {

    tmpDir := os.TempDir()
    // Make sure os.TempDir didn't return empty string
    // reusing my favourite `must` helper
    // Isn't that kinda creepy now though?
    must(func() error {
        var err error
        if len(tmpDir) > 0 {
            err = nil
        } else {
            err = errors.New("os.TempDir is empty")
        }
        return err
    }()) // Don't forget that empty parentheses to invoke the lambda.
    println("We happy with", tmpDir)
}

有趣的方法,它可能在更复杂的情况下有用。 :)
R
Ron

有时,我尝试使用匿名函数来实现定义和分配在同一行发生。如下所示:

a, b = 4, 8

c := func() int {
    if a >b {
      return a
    } 
    return b
  } ()

https://play.golang.org/p/rMjqytMYeQ0


这在更复杂的情况下也可能有用+1。
I
Igor Fagundes

就像 user2680100 说的,在 Golang 中你可以有这样的结构:

if <statement>; <evaluation> {
    [statements ...]
} else {
    [statements ...]
}

这对于简化一些需要错误检查或另一种布尔检查的表达式很有用,例如:


var number int64
if v := os.Getenv("NUMBER"); v != "" {
   if number, err = strconv.ParseInt(v, 10, 64); err != nil {
       os.Exit(42)
   }
} else {
    os.Exit(1)
}

有了这个,你可以实现类似(在 C 中):

Sprite *buffer = get_sprite("foo.png");
Sprite *foo_sprite = (buffer != 0) ? buffer : donut_sprite

但很明显,Golang 中的这种糖必须适度使用,就我个人而言,我喜欢使用这种糖,最多嵌套一层,例如:


var number int64
if v := os.Getenv("NUMBER"); v != "" {
    number, err = strconv.ParseInt(v, 10, 64)
    if err != nil {
        os.Exit(42)
    }
} else {
    os.Exit(1)
}

您还可以使用 func Ternary(b bool, a interface{}, b interface{}) { ... } 之类的函数实现三元表达式,但我不喜欢这种方法,看起来像是在语法中创建了一个异常情况,并且创建了这个“功能”,在我个人看来,减少对它的关注重要的是算法和可读性,但是,让我不采用这种方式的最重要的事情是,这会带来一种开销,并在程序执行中带来更多周期。


L
Louki Sumirniy

您可以为此使用闭包:

func doif(b bool, f1, f2 func()) {
    switch{
    case b:
        f1()
    case !b:   
        f2()
    }
}

func dothis() { fmt.Println("Condition is true") }

func dothat() { fmt.Println("Condition is false") }

func main () {
    condition := true
    doif(condition, func() { dothis() }, func() { dothat() })
}

我对 Go 中的闭包语法的唯一抱怨是默认的零参数零返回函数没有别名,那么它会更好(想想你如何用类型名称声明映射、数组和切片文字)。

甚至更短的版本,正如评论者刚刚建议的那样:

func doif(b bool, f1, f2 func()) {
    switch{
    case b:
        f1()
    case !b:   
        f2()
    }
}

func dothis() { fmt.Println("Condition is true") }

func dothat() { fmt.Println("Condition is false") }

func main () {
    condition := true
    doif(condition, dothis, dothat)
}

如果您需要为函数提供参数,您仍然需要使用闭包。在传递方法的情况下可以避免这种情况,而不仅仅是我认为的函数,其中参数是与方法关联的结构。


较短的版本 doif(condition, dothis, dothat)
是的,那会更短,只传递函数。只需在一个实用程序库中拥有此功能一次,您就可以通过代码使用它。
为什么调用函数而不是简单地返回它?
E
Edson Medina

正如其他人指出的那样,Go 中没有三元运算符。

但是,对于您的特定示例,如果您想使用单个衬里,则可以使用 Max

import "math"

...

c := math.Max(a, b)


L
Laxmikant Tiwari

三元?运营商替代品 | golang if else one line 你不能用 Go 语言写一个简短的单行条件;没有三元条件运算符。 Read more about if..else of Golang


这里没有什么新鲜事。这已经在其他答案中以更好的方式说过。
此外,没有任何实际用途的自我宣传。