Hey everyone, I"m Emmanuel Katto from Dubai, United Arab Emirates (UAE), I’ve encountered an issue with a recursive function, and I’m hoping to get some advice or suggestions on what might be going wrong.
Here’s a quick overview of the setup:
I have a recursive function play(b)
where b
is a struct that contains two slices (s
and w
). These slices hold structs with a few fields: string1
, string2
, and bool
.
Inside the play(b)
function, there’s a piece of code like this:
bNew := mm(bIn)
bOrigIn := bIn
play(bNew)
play()
calls itself recursively, and the recursion eventually returns back up. The issue I’m seeing is that, after returning from some levels of recursion, bIn
and bOrigIn
are both different from how they were before the recursive call, even though they should have been unchanged.
The Problem:
- The function reaches a certain recursion depth (say 23 levels) and then continues deeper for another 10 levels.
- When returning back to level 23,
bIn
has changed from its original value. What’s strange is thatbOrigIn
has also changed in exactly the same way asbIn
(which suggests they are somehow linked). - However,
bNew
remains unchanged as expected.
Additional Details:
bIn
contains slicess
andw
, each with 9 elements.- When returning to level 23, the 9th element of slice
w
has been modified. Specifically, it now contains the value from the 9th element of slices
, but with the boolean flipped, and the 9th element froms
is removed. - This change is made by a function
mm(bIn)
at some point during the recursion.
The Core Questions:
- Why is
bIn
andbOrigIn
changing when they should be local variables?
- Since both
bIn
andbOrigIn
are function-level variables (not package-level), why do they appear to be affected by changes that occur in the recursion?
- Is this a slicing issue?
- I suspect that since Go slices are reference types (i.e., they point to the same underlying array), the changes made in the recursion might be affecting both
bIn
andbOrigIn
because they share references to the same memory locations. If that’s the case, is this why both of them are modified when only one should have been?
- What should I look for to prevent this?
- Are there any best practices for handling slices and recursion in Go to avoid unintended side effects like this? Specifically, should I be copying the slices (or the struct) before passing them into functions like
mm()
to ensure that changes don’t propagate unexpectedly?
What I’ve Tried:
- I’ve tried both
:=
and=
for creatingbOrigIn := bIn
, but the issue persists either way. - I’m aware that slices in Go are reference types, so any modification to one slice in a function can affect the original slice unless I explicitly copy it.
Looking for Advice:
If anyone has suggestions on how to handle this scenario or ways to avoid these kinds of slice reference issues, I’d greatly appreciate your thoughts!
Thanks for reading!
Emmanuel Katto