怎么做one-liner if else声明?

时间:2014-10-24 10:09:15

标签: if-statement go conditional-operator ternary

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

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

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

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

抱歉,如果此控制声明和我无法通过现场和谷歌搜索找到该信息,我记不住该名称。 :/

12 个答案:

答案 0 :(得分:92)

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

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

答案 1 :(得分:24)

我经常使用以下内容:

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

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

答案 2 :(得分:15)

正如其他人所提到的,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

找到它们

答案 3 :(得分:11)

感谢您指出正确的答案。

我刚检查了Golang FAQ(duh)并且明确指出,这种语言不可用:

  

Go是否有?:运算符?

     

Go中没有三元形式。您可以使用以下内容来获得相同的结果:

if expr {
    n = trueVal
} else {
    n = falseVal
}

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

答案 4 :(得分:2)

使用地图只在一行中执行此操作的一种可能方法,我正在检查a > b是否为true我是c还是a否则b

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

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

myObj equals nil
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}

答案 5 :(得分:1)

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

a, b = 4, 8

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

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

答案 6 :(得分:1)

就像 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{}) { ... } 之类的函数实现三元表达式,但我不喜欢这种方法,在我个人看来,它看起来像是在语法中创建了一个异常情况,并创建了这个“功能”,减少对重要的关注,即算法和可读性,但是,让我不走这种方式的最重要的事情是,这会带来一种开销,并在程序执行中带来更多周期.

答案 7 :(得分:0)

语言中提供了非常相似的结构

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

*

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

答案 8 :(得分:0)

您可以为此使用闭包:

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文字名称)。

或更短的版本,如评论者所建议的:

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)
}

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

答案 9 :(得分:0)

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

示例1

给出最大整数

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)
}

答案 10 :(得分:-1)

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

不过,对于您的特定示例,如果您想使用单个班轮,则可以使用 Max

import "math"

...

c := math.Max(a, b)

答案 11 :(得分:-4)

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