Garbage collection acting weirdly on goroutine

Hello guys, I’m facing some issues when trying to use arguments on a goroutine. As I have tried plenty of different alternatives without success, I will describe here the problem. So, I have a function that creates an object of custom type Transaction (with some string and string pointer fields) and I want to do something with this transaction after a defined time duration. For this I have the following code:

func step1 () {
    transaction := Transaction{
        Name: "transactionName",
        Type: "transactionType1",
        ....
    }
    go func (t Transaction){
        trans := t

        fmt.Println(trans)
        time.Sleep(sleepDuration)
        fmt.Println(trans)
        doSomething(trans)
    }(transaction)
}

The issue is that this transaction does not seem to be passed by value, as between the two prints some of the string fields of the transaction has changed to random values. My guess is that after function “step1” returns the transaction object is garbage collected (but I really want to launch this background task and return). However, this doesn’t make sense for me as the value should be passed by value and I also have an explicit copy of the object there.
Any of you know why does this behavior happen and an alternative for it.
(Some of the alternatives I have tried include using not an anonymous function, use the time.AfterFunc method, create an anonymous function which builds another one for the argument. Nothing seems to work.)

Thank you in advance

Are the string fields changing or are the string pointer fields changing? If the former, then could you provide an example I could run and step through? If the latter, then it sounds like doSomething is modifying those fields. Even if you pass a struct by value, if that value contains pointers, then you can modify values through those pointers.

In your example, I don’t see how this could happen, but if you (perhaps accidentally) reference transaction within the goroutine closure instead of t or trans, you’ll access the variable through a reference, so it’s like passing it by pointer: https://play.golang.org/p/e_RQ8EM2o66