关于go:怎么做one-liner if else声明?

How to do one-liner if else statement?

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

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

目前我必须使用以下方法:

1
2
3
4
5
6
var c int
if a > b {
    c = a
} else {
    c = b
}

很抱歉,如果这个控制语句和在站点和谷歌搜索中找不到信息,我就记不起它的名字了。:


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

1
2
3
4
var c int
if c = b; a > b {
    c = a
}


我经常使用以下方法:

1
2
3
4
c := b
if a > b {
    c = a
}

基本上与@not_a_golfer's相同,但使用类型推断。


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

1
2
3
4
5
6
7
// 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
}

下面是一些测试案例,演示如何使用它

1
2
3
4
5
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)
}

为了好玩,我写了一些更有用的实用功能,比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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


感谢您指出正确的答案。

我刚刚查看了Golang FAQ(DUH),它清楚地表明,这是不可用的语言:

Does Go have the ?: operator?

There is no ternary form in Go. You may use the following to achieve the same result:

1
2
3
4
5
if expr {
    n = trueVal
} else {
    n = falseVal
}

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

  • Go中条件结构的Rosetta代码
  • 这家伙的围棋实验中的三元运算符


一种可能的方法是使用地图在一行中完成这项工作,简单地说,我正在检查a > b是否是true,如果是true,我将c分配给a,否则b

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

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

1
2
3
4
5
6
7
8
9
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的情况下,这只会引起恐慌。

别忘了,您仍然可以只在一行中完成这些条件,请检查以下内容:

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

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

1
2
3
4
5
6
7
8
a, b = 4, 8

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

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


您可以为此使用一个闭包:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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中,我对闭包语法唯一的抱怨是没有默认的零参数零返回函数的别名,那么它会更好(想想如何只用一个类型名声明map、array和slice文本)。

甚至是较短的版本,正如一位评论者所建议的那样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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)
}

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


语言中有非常相似的结构

1
2
3
4
5
**if <statement>; <evaluation> {
   [statements ...]
} else {
   [statements ...]
}*

*

1
2
3
4
5
if path,err := os.Executable(); err != nil {
   log.Println(err)
} else {
   log.Println(path)
}