自成一体的围棋与 c 的三元运算符等价吗?

In C/C++ (and many languages of that family), a common idiom to declare and initialize a variable depending on a condition uses the ternary conditional operator :

int index = val > 0 ? val : -val

Go doesn't have the conditional operator. What is the most idiomatic way to implement the same piece of code as above ? I came to the following solution, but it seems quite verbose

var index int

if val > 0 {
    index = val
} else {
    index = -val
}

Is there something better ?

转载于:https://stackoverflow.com/questions/19979178/what-is-the-idiomatic-go-equivalent-of-cs-ternary-operator

As pointed out (and hopefully unsurprisingly), using if+else is indeed the idiomatic way to do conditionals in Go.

In addition to the full blown var+if+else block of code, though, this spelling is also used often:

index := val
if val <= 0 {
    index = -val
}

and if you have a block of code that is repetitive enough, such as the equivalent of int value = a <= b ? a : b, you can create a function to hold it:

func min(a, b int) int {
    if a <= b {
        return a
    }
    return b
}

...

value := min(a, b)

The compiler will inline such simple functions, so it's fast, more clear, and shorter.

No Go doesn't have a ternary operator, using if/else syntax is the idiomatic way: http://golang.org/doc/faq#Does_Go_have_a_ternary_form

The map ternary is easy to read without parentheses:

c := map[bool]int{true: 1, false: 0} [5 > 4]

Suppose you have the following ternary expression (in C):

int a = test ? 1 : 2;

The idiomatic approach in Go would be to simply use an if block:

var a int

if test {
  a = 1
} else {
  a = 2
}

However, that might not fit your requirements. In my case, I needed an inline expression for a code generation template.

I used an immediately evaluated anonymous function:

a := func() int { if test { return 1 } else { return 2 } }()

This ensures that both branches are not evaluated as well.

If all your branches make side-effects or are computationally expensive the following would a semantically-preserving refactoring:

index := func() int {
    if val > 0 {
        return printPositiveAndReturn(val)
    } else {
        return slowlyReturn(-val)  // or slowlyNegate(val)
    }
}();  # exactly one branch will be evaluated

with normally no overhead (inlined) and, most importantly, without cluttering your namespace with a helper functions that are only used once (which hampers readability and maintenance). Live Example

Note if you were to naively apply Gustavo's approach:

    index := printPositiveAndReturn(val);
    if val <= 0 {
        index = slowlyReturn(-val);  // or slowlyNegate(val)
    }

you'd get a program with a different behavior; in case val <= 0 program would print a non-positive value while it should not! (Analogously, if you reversed the branches, you would introduce overhead by calling a slow function unnecessarily.)

eold's answer is interesting and creative, perhaps even clever.

However, it would be recommended to instead do:

var index int
if val > 0 {
    index = printPositiveAndReturn(val)
} else {
    index = slowlyReturn(-val)  // or slowlyNegate(val)
}

Yes, they both compile down to essentially the same assembly, however this code is much more legible than calling an anonymous function just to return a value that could have been written to the variable in the first place.

Basically, simple and clear code is better than creative code.

Additionally, any code using a map literal is not a good idea, because maps are not lightweight at all in Go. Since Go 1.3, random iteration order for small maps is guaranteed, and to enforce this, it's gotten quite a bit less efficient memory-wise for small maps.

As a result, making and removing numerous small maps is both space-consuming and time-consuming. I had a piece of code that used a small map (two or three keys, are likely, but common use case was only one entry) But the code was dog slow. We're talking at least 3 orders of magnitude slower than the same code rewritten to use a dual slice key[index]=>data[index] map. And likely was more. As some operations that were previously taking a couple of minutes to run, started completing in milliseconds.\

func Ternary(statement bool, a, b interface{}) interface{} {
    if statement {
        return a
    }
    return b
}

func Abs(n int) int {
    return Ternary(n >= 0, n, -n).(int)
}

This will not outperform if/else and requires cast but works. FYI:

BenchmarkAbsTernary-8 100000000 18.8 ns/op

BenchmarkAbsIfElse-8 2000000000 0.27 ns/op

/*
* type ListNode struct {
*     Val int
*     Next *ListNode
* }
*/

val := (l1 ? l1->val : 0) + (l2 ? l2->val : 0) + carry