Giuseppe Percuoco
Giuseppe Percuoco

Reputation: 121

Using the variable on range scope `x` in function literal (scopelint)

func TestGetUID(t *testing.T) {
    namespace := "lkfm"
    expecteduid := "fake_uid"
    var tests = []struct {
        description string
        expected    string
        namespace   string
        objs        []runtime.Object
    }{
        {"PositiveScenario", expecteduid, namespace, []runtime.Object{simpleNamespace(namespace)}},
    }

    for _, x := range tests {
        t.Run(x.description, func(t *testing.T) {
            client := fake.NewSimpleClientset(x.objs...)
            actual := getUID(client, x.namespace)
            assert.Equal(t, x.expected, actual)
        })
    }
}

Lint give me some problem on :

and it reports this error : "Using the variable on range scope x in function literal (scopelint)"

Upvotes: 5

Views: 4224

Answers (1)

icza
icza

Reputation: 417777

x is the loop variable which is reused in each iteration. And you create a function literal which you pass to t.Run(). The compiler does not know (does not have guarantee) whether the created and passed function literal is not called after t.Run() returns, in which case the function literal would refer to the loop variable which will be overwritten with the value of the next iteration. This is rarely–if ever–the intention. It's often the source of nasty bugs, even data race if the function literal is executed concurrently in another gorotuine.

So go vet warns about such uses.

Often the solution is to pass the value of the loop variable to the function literal as an argument, or create a copy of the loop variable and refer to the copy. Since the signature of your function literal is fixed (you can't change it), create a copy of the variable, e.g.:

x2 := x

And refer to x2 inside the function literal. This will make go vet happy.

Also, since the intention of making a copy is clear, you may use the same name, e.g. x := x, which copy will shadow the loop variable. After the above short variable declaration, the identifier x will refer to the local copy (and not the loop variable). In general this may cause confusion, but here the intention is clear and acceptable.

Upvotes: 14

Related Questions