Please see https://golangdocs.com/ternary-operator-in-golang as pointed by @accdias (see comments)

Can I write a simple if-else statement with variable assignment in go (golang) as I would do in php? For example:

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

Currently I have to use the following:

var c intif a > b {c = a} else {c = b}

Sorry I cannot remember the name if this control statement and I couldn't find the info in-site or through google search. :/

12

Best Answer


As the comments mentioned, Go doesn't support ternary one liners. The shortest form I can think of is this:

var c intif c = b; a > b {c = a}

But please don't do that, it's not worth it and will only confuse people who read your code.

As the others mentioned, Go does not support ternary one-liners. However, I wrote a utility function that could help you achieve what you want.

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

Here are some test cases to show how you can use it

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

For fun, I wrote more useful utility functions such as:

IfThen(1 == 1, "Yes") // "Yes"IfThen(1 != 1, "Woo") // nilIfThen(1 < 2, "Less") // "Less"IfThenElse(1 == 1, "Yes", false) // "Yes"IfThenElse(1 != 1, nil, 1) // 1IfThenElse(1 < 2, nil, "No") // nilDefaultIfNil(nil, nil) // nilDefaultIfNil(nil, "") // ""DefaultIfNil("A", "B") // "A"DefaultIfNil(true, "B") // trueDefaultIfNil(1, false) // 1FirstNonNil(nil, nil) // nilFirstNonNil(nil, "") // ""FirstNonNil("A", "B") // "A"FirstNonNil(true, "B") // trueFirstNonNil(1, false) // 1FirstNonNil(nil, nil, nil, 10) // 10FirstNonNil(nil, nil, nil, nil, nil) // nilFirstNonNil() // nil

If you would like to use any of these, you can find them here https://github.com/shomali11/util

I often use the following:

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

basically the same as @Not_a_Golfer's but using type inference.

Thanks for pointing toward the correct answer.

I have just checked the Golang FAQ (duh) and it clearly states, this is not available in the language:

Does Go have the ?: operator?

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

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

additional info found that might be of interest on the subject:

  • Rosetta Code for Conditional Structures in Go
  • Ternary Operator in Go experiment from this guy

One possible way to do this in just one line by using a map, simple I am checking whether a > b if it is true I am assigning c to a otherwise b

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

However, this looks amazing but in some cases it might NOT be the perfect solution because of evaluation order. For example, if I am checking whether an object is not nil get some property out of it, look at the following code snippet which will panic in case of myObj equals nil

type MyStruct struct {field1 stringfield2 string }var myObj *MyStructmyObj = nil myField := map[bool]string{true: myObj.field1, false: "empty!"}[myObj != nil}

Because map will be created and built first before evaluating the condition so in case of myObj = nil this will simply panic.

Not to forget to mention that you can still do the conditions in just one simple line, check the following:

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

A very similar construction is available in the language

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

*

i.e.

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

Use lambda function instead of ternary operator

Example 1

to give the max int

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

Example 2

Suppose you have this must(err error) function to handle errors and you want to use it when a condition isn't fulfilled.(enjoy at https://play.golang.com/p/COXyo0qIslP)

package mainimport ("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 errorif 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)}

Sometimes, I try to use anonymous function to achieve defining and assigning happen at the same line. like below:

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

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

Like user2680100 said, in Golang you can have the structure:

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

This is useful to shortcut some expressions that need error checking, or another kind of boolean checking, like:

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

With this you can achieve something like (in C):

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

But is evident that this sugar in Golang have to be used with moderation, for me, personally, I like to use this sugar with max of one level of nesting, like:

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

You can also implement ternary expressions with functions like func Ternary(b bool, a interface{}, b interface{}) { ... } but i don't like this approach, looks like a creation of a exception case in syntax, and creation of this "features", in my personal opinion, reduce the focus on that matters, that is algorithm and readability, but, the most important thing that makes me don't go for this way is that fact that this can bring a kind of overhead, and bring more cycles to in your program execution.

You can use a closure for this:

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 := truedoif(condition, func() { dothis() }, func() { dothat() })}

The only gripe I have with the closure syntax in Go is there is no alias for the default zero parameter zero return function, then it would be much nicer (think like how you declare map, array and slice literals with just a type name).

Or even the shorter version, as a commenter just suggested:

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 := truedoif(condition, dothis, dothat)}

You would still need to use a closure if you needed to give parameters to the functions. This could be obviated in the case of passing methods rather than just functions I think, where the parameters are the struct associated with the methods.

As everyone else pointed out, there's no ternary operator in Go.

For your particular example though, if you want to use a single liner, you could use Max.

import "math"...c := math.Max(a, b)

Ternary ? operator alternatives | golang if else one lineYou can’t write a short one-line conditional in Go language ; there is no ternary conditional operator.Read more about if..else of Golang