Is it safe to swap two integers by `a, b = b, a` in golang?

147 Views Asked by At
package main

import "fmt"

func main() {
    a := 1
    b := 2

    fmt.Printf("Before Swap: %v %v\n", a, b)
    a, b = b, a
    fmt.Printf(" After Swap: %v %v\n", a, b)
}

The output is:

Before Swap: 1 2  
 After Swap: 2 1

It looks good. I just wonder:

Is it safe to swap two integers by a, b = b, a in golang?

2

There are 2 best solutions below

1
Bhojendra Rauniyar On

Yes, it is. When you have same variable type, you can swipe them.

i := []int{1, 2, 3, 4}
i[0], i[1], i[2], i[3] = i[3], i[2], i[1], i[0]
// now, i is: []int{4, 3, 2, 1}
// btw, you could also range over slice and swipe them

From the docs

In assignments, each value must be assignable to the type of the operand to which it is assigned, with the following special cases:

  1. Any typed value may be assigned to the blank identifier.
  2. If an untyped constant is assigned to a variable of interface type or the blank identifier, the constant is first implicitly converted to its default type.
  3. If an untyped boolean value is assigned to a variable of interface type or the blank identifier, it is first implicitly converted to type bool.
0
cuonglm On

Yes, it's safe to swap two variables using:

a, b = b, a

The assignment happens in two steps:

  • The right hand side of the assignment is evaluated first.
  • Then the evaluated values will be assigned to the left hand side in left-to-right order.

In other words, a, b = b, a will be rewritten roughly to:

tmpB := b
tmpA := a
a = tmpB
b = tmpA

That's why the assignment is safe.


In fact, the compiler is smart enough to avoid a second temporary variable, so a, b = b, a will be rewritten as:

tmpA := a
a = b
b = tmpA
$ cat x.go 
package p

func f(a, b int) {
    a, b = b, a
}
$ go tool compile -W x.go

before walk f
.   AS2 tc(1) # x.go:4:7
.   AS2-Lhs
.   .   NAME-p.a esc(no) Class:PPARAM Offset:0 OnStack Used int tc(1) # x.go:3:8
.   .   NAME-p.b esc(no) Class:PPARAM Offset:0 OnStack Used int tc(1) # x.go:3:11
.   AS2-Rhs
.   .   NAME-p.b esc(no) Class:PPARAM Offset:0 OnStack Used int tc(1) # x.go:3:11
.   .   NAME-p.a esc(no) Class:PPARAM Offset:0 OnStack Used int tc(1) # x.go:3:8
after walk f
.   BLOCK # x.go:4:7
.   BLOCK-List
.   .   AS tc(1) # x.go:4:7
.   .   .   NAME-p..autotmp_2 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used int tc(1) # x.go:4:7
.   .   .   NAME-p.a esc(no) Class:PPARAM Offset:0 OnStack Used int tc(1) # x.go:3:8
.   .   AS tc(1) # x.go:4:7
.   .   .   NAME-p.a esc(no) Class:PPARAM Offset:0 OnStack Used int tc(1) # x.go:3:8
.   .   .   NAME-p.b esc(no) Class:PPARAM Offset:0 OnStack Used int tc(1) # x.go:3:11
.   .   AS tc(1) # x.go:4:7
.   .   .   NAME-p.b esc(no) Class:PPARAM Offset:0 OnStack Used int tc(1) # x.go:3:11
.   .   .   NAME-p..autotmp_2 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used int tc(1) # x.go:4:7