49

Is there a builtin way to cast bools to integers or vice versa? I've tried normal casting, but since they use different underlying types, conversion isn't possible the classic way. I've poured over some of the specification, and I haven't found an answer yet.

worr
  • 759
  • 1
  • 5
  • 9
  • ` i != 0` to set an int to a bool. See https://stackoverflow.com/a/62737936/12817546. `if` statement to set a bool to an integer. See https://stackoverflow.com/a/62726854/12817546. –  Jul 10 '20 at 00:22

7 Answers7

60

Int to bool is easy, just x != 0 will do the trick. To go the other way, since Go doesn't support a ternary operator, you'd have to do:

var x int
if b {
    x = 1
} else {
    x = 0
}

You could of course put this in a function:

func Btoi(b bool) int {
    if b {
        return 1
    }
    return 0
 }

There are so many possible boolean interpretations of integers, none of them necessarily natural, that it sort of makes sense to have to say what you mean.

In my experience (YMMV), you don't have to do this often if you're writing good code. It's appealing sometimes to be able to write a mathematical expression based on a boolean, but your maintainers will thank you for avoiding it.

SteveMcQwark
  • 2,169
  • 16
  • 9
  • 2
    Note that the `else` in the first example is unnecessary as `x` will be initialized to `0`, as demonstrated in the answer by Cerise Limón. – Bjorn Feb 22 '21 at 07:13
22

Here's a trick to convert from int to bool:

x := 0
newBool := x != 0 // returns false

where x is the int variable you want to convert from.

Sameh Sharaf
  • 1,103
  • 1
  • 13
  • 15
10

There are no conversions from bool to integer types or vice versa.

Use the inequality operator to convert integers to bool values:

b := i != 0

Use an if statement to convert a bool to an integer type:

var i int
if b {
    i = 1
}

Because the zero value for integer types is 0, the else branch shown in other answers is not necessary.

Charlie Tumahai
  • 113,709
  • 12
  • 249
  • 242
10
var a int = 3
var b bool = a != 0

I just dropped this into the demo box on the golang front page:

package main

import "fmt"

func main() {
 var a int = 3
 var b bool = a != 0
    fmt.Println("Hello, 世界", b)
}

Output:

Hello, 世界 true
Matt Joiner
  • 112,946
  • 110
  • 377
  • 526
9

Just to show TMTOWTDT

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    fmt.Println(bool2int(true))
    fmt.Println(bool2int(false))
}

func bool2int(a bool) uint64 {
    return *(*uint64)(unsafe.Pointer(&a))&1
}

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

jch
  • 5,382
  • 22
  • 41
Vorsprung
  • 32,923
  • 5
  • 39
  • 63
  • Cool. Does this work across platforms? I mean, Go encodes the boolean as the least significant bit across platforms? – Everton Mar 07 '19 at 05:05
  • 1
    I think that on most (Intel) platforms we are little endian and the code above will work. To make it more portable I guess that you could add a step to convert to Network order which is always big endian and then look at the other end of the bytes – Vorsprung Mar 07 '19 at 11:43
  • 2
    If I see this in a company code, I will `git blame` it then report it to HR. – jsgoupil Sep 10 '21 at 16:52
  • @jsgoupil haha yes, this way of doing it is a pretty bad idea! – Vorsprung Sep 13 '21 at 07:03
1

You could use maps:

package main

var (
   isZero = map[int]bool{0: true}
   intVal = map[bool]int{true: 1}
)

func main() {
   println(isZero[-2]) // false
   println(isZero[-1]) // false
   println(isZero[0]) // true
   println(isZero[1]) // false
   println(isZero[2]) // false
   
   println(intVal[false]) // 0
   println(intVal[true]) // 1
}
Zombo
  • 1
  • 62
  • 391
  • 407
0

To set a numeric type from a bool, the if statement is the best you can do. See @MuffinTop very-good answer and https://stackoverflow.com/a/38627381/12817546. This is also true for setting boolean and string types from a bool.

package main

import (
    . "fmt"
    . "strconv"
)

func main() {
    var e []interface{}
    t := true
    if t {
        by := []byte{'G', 'o'}
        r := []rune{rune(by[0]), 111}
        f := 70.99
        s := Sprintf("%.f", f)
        i, _ := Atoi(s) // Atoi "ASCII to integer"
        bo := !(t == true)
        // var bo bool = t != true
        e = []interface{}{by[0], r[0], f, s, i, bo}
    }
    checkType(e)
}

func checkType(s []interface{}) {
    for k, _ := range s {
        // uint8 71, int32 71, float64 70.99, string 71, int 71, bool false
        Printf("%T %v\n", s[k], s[k])
    }
}

You can use bo := !(t == true) as @SamehShara said or var bo bool = t != true as @MattJoiner said to set a bool. Here t a bool with a value of true is set to bo a bool with a value of false.

To set a "true" or "false" string from a true or false bool use fmt.Sprintf("%v", t). See https://stackoverflow.com/a/47413424/12817546. strconv.ParseBool("true") for the reverse. See https://stackoverflow.com/a/53093945/12817546. Quotes edited.

  • A boolean, numeric, or string type can be set to another type. For`[]byte` see https://stackoverflow.com/a/62725637/12817546, for `float64` see https://stackoverflow.com/a/62753031/12817546, `int` see https://stackoverflow.com/a/62737936/12817546, `[]rune` see https://stackoverflow.com/a/62739051/12817546, and for `string` see https://stackoverflow.com/a/62740786/12817546. –  Jul 07 '20 at 09:36