if else语句如何做单行? [复制]
Posted
技术标签:
【中文标题】if else语句如何做单行? [复制]【英文标题】:How to do one-liner if else statement? [duplicate] 【发布时间】:2014-12-20 04:06:51 【问题描述】:请参阅@accdias 指出的https://golangdocs.com/ternary-operator-in-golang(请参阅 cmets)
我可以像在 php 中那样在 go (golang) 中编写一个带有变量赋值的简单 if-else 语句吗?例如:
$var = ( $a > $b )? $a: $b;
目前我必须使用以下内容:
var c int
if a > b
c = a
else
c = b
对不起,如果这个控制语句我不记得名称,并且我无法在站点内或通过谷歌搜索找到信息。 :/
【问题讨论】:
它被称为三元运算符......不,Go 没有。 我相信你要找的词是“三元” 澄清一下,三元运算符是任意数量为 3 的运算符,即绑定 3 个子表达式的任何运算符。 C 恰好只有一个这样的运算符。这就是为什么它通常被称为三元运算符。不过,它的真名是“条件运算符”。 请看The ternary operator in GoLang。 【参考方案1】:正如 cmets 所提到的,Go 不支持三元一列。我能想到的最短形式是这样的:
var c int
if c = b; a > b
c = a
但请不要这样做,这样做不值得,只会让阅读您代码的人感到困惑。
【讨论】:
@thoroc 实际上我可能会在现实生活中避免这种情况,因为它不直观,恕我直言,不值得保存 2 行以降低可读性。 @thoroc,请听听 Not_a_Golfer 怎么说。您应该努力编写可维护的软件,而不是炫耀自己。巧妙的技巧很巧妙,但是下一个阅读您的代码的人(包括几个月/几年后的您)不会欣赏它们。跨度> 这取决于可读性。我认为这更具可读性,但就像其他任何东西一样,它可能会被滥用。如果您需要在 if 块之外声明一个不需要的变量,那么我认为这是一个赢家。 哦,天哪,看看没有三元运算符,Go 获得了多少收益。除了创建的可读性 cmets 之外,您还更改了一个延迟评估的构造,其中只运行一个分支,将其更改为始终运行第一个分支并且可以另外运行第二个分支。 @accdias 不,它在 Go 中不起作用。【参考方案2】:正如其他人提到的,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
【讨论】:
我更喜欢If(c bool).Then(a interface, b interface)
而不是 this answer,它对我来说看起来更惯用
What about: If(c bool).Then(a interface).Else(b interface)
如果只需要初始值,可以删除 else。甚至像这样:If(c bool).Then(a interface).Default(b interface)
可爱!感谢分享。【参考方案3】:
我经常使用以下:
c := b
if a > b
c = a
与@Not_a_Golfer 基本相同,但使用type inference。
【讨论】:
具有同样的缺点:当使用非对称解决方案来满足明显对称的需求时,会使理解复杂化。 同样的缺点是将应该是一个惰性评估的构造,其中两个分支中只有一个会被使用到一个总是会被评估的分支,有时两者都被评估(在这种情况下,第一次评估是多余的) 根据用例,这仍然可能非常有用。例如。listeningPath := "production.some.com"; if DEBUG listeningPath := "development.some.com"
生产速度与三元相同,而且可读性很好。
我通常会在故意浪费CPU周期时哭泣。【参考方案4】:
感谢您指出正确的答案。
我刚刚检查了Golang FAQ (duh),它明确指出,这在语言中不可用:
Go 有 ?: 运算符吗?
Go 中没有三元形式。您可以使用以下方法来实现相同的结果:
if expr n = trueVal else n = falseVal
发现可能对该主题感兴趣的其他信息:
Rosetta Code for Conditional Structures in Go Ternary Operator in Go experiment from this guy【讨论】:
也可以一行:var c int; if a > b c = a else c = b
?但我建议将其保留在 5 行中,以形成一个供读者娱乐的灯块;)【参考方案5】:
使用地图在一行中执行此操作的一种可能方法很简单,我正在检查 a > b
是否是 true
我将 c
分配给 a
否则 b
c := map[bool]inttrue: a, false: b[a > b]
然而,这看起来很神奇,但在某些情况下,由于评估顺序,它可能不是完美的解决方案。例如,如果我正在检查一个对象是否不是 nil
从中获取一些属性,请查看以下代码 sn-p ,如果是 myObj equals nil
,它将 panic
type MyStruct struct
field1 string
field2 string
var myObj *MyStruct
myObj = nil
myField := map[bool]stringtrue: 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(...)
还要糟糕。【参考方案6】:
在该语言中可以使用非常相似的结构
**if <statement>; <evaluation>
[statements ...]
else
[statements ...]
*
*
即
if path,err := os.Executable(); err != nil
log.Println(err)
else
log.Println(path)
【讨论】:
【参考方案7】:使用 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)
【讨论】:
有趣的方法,它可能在更复杂的情况下有用。 :)【参考方案8】:有时,我尝试使用匿名函数来实现定义和分配在同一行发生。如下:
a, b = 4, 8
c := func() int
if a >b
return a
return b
()
https://play.golang.org/p/rMjqytMYeQ0
【讨论】:
这在更复杂的情况下也可能有用+1。【参考方案9】:就像 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) ...
之类的函数实现三元表达式,但我不喜欢这种方法,看起来像是在语法上创建了一个异常情况,并创建了这个“功能”,在我个人看来,减少专注于这件事,那就是算法和可读性,但是,让我不这样做的最重要的事情是,这会带来一种开销,并在你的程序执行中带来更多的周期。
【讨论】:
【参考方案10】:您可以为此使用闭包:
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)
是的,那会更短,只传递函数。只需在一个实用程序库中拥有此功能一次,您就可以通过代码使用它。
为什么要调用函数而不是简单地返回它?【参考方案11】:
正如其他人指出的那样,Go 中没有三元运算符。
但是,对于您的特定示例,如果您想使用单个衬里,则可以使用 Max
。
import "math"
...
c := math.Max(a, b)
【讨论】:
【参考方案12】:三元?运营商替代品 | golang if else 一行 你不能用 Go 语言写一个简短的单行条件;没有三元条件运算符。 Read more about if..else of Golang
【讨论】:
这里没有什么新鲜事。这已经在其他答案中以更好的方式说过。 此外,没有任何实际用途的自我宣传。以上是关于if else语句如何做单行? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 if、else、elsif 语句创建 Terraform?
pb中的条件语句,if else,choose case ,for