The function go is still recursive with the var, as it calls itself. It just isn’t a pure function (in the functional programming sense). But of course recursion is often used instead of loops to avoid mutable state.
Also, go in fib is a tailrecursive function. This is actually ensured by the compiler, as you put the @annotation.tailrecursive above it. If it wasn’t this would cause an error. To check yourself, if a function is tailrecursive, you have to look at all positions, where the function calls itself. If the call is the last thing the function does, i.e. the value returned by the recursive call is the value returned by the outer go call, the function is tail-recursive. If you do further operations on the value after the call, it is no longer in tail position and cannot be optimized. For example, if you’d replace the call in your code with go(b, c) + 1, this would need to do the + 1 operation after the go call returned, so the recursive call wouldn’t be the last operation.