I have a package "tools" that expose a method that must execute some logic only one time. The next calls don't do nothing.
The file tools/tools.go is like:
package tools
import (
"fmt"
"sync"
)
var writed = false
var mutex = sync.Mutex{}
func OnlyOneWrite() {
mutex.Lock()
defer mutex.Unlock()
if writed {
return
}
writed = true
// some stuff that must happen only once
fmt.Println("I must be printed only one time")
}
Next i have a test inside the A package. The file a/a_test.go looks like:
package a_test
import (
"testing"
"lock_example/tools"
)
func TestA(t *testing.T) {
const arbitraryGoRoutines = 30
for i := 0; i < arbitraryGoRoutines; i++ {
tools.OnlyOneWrite()
}
}
When i run the test:
go test -v ./a/...
=== RUN TestA
I must be printed only one time
--- PASS: TestA (0.00s)
PASS
ok lock_example/a 0.002s
Perfect, only one print.
BUT, i have another package with the same logic b/b_test.go as follow:
package b
import (
"testing"
"lock_example/tools"
)
func TestB(t *testing.T) {
const arbitraryGoRoutines = 30
for i := 0; i < arbitraryGoRoutines; i++ {
tools.OnlyOneWrite()
}
}
When i run the two tests:
go test -v ./...
=== RUN TestA
I must be printed only one time
--- PASS: TestA (0.00s)
PASS
ok lock_example/a (cached)
=== RUN TestB
I must be printed only one time
--- PASS: TestB (0.00s)
PASS
ok lock_example/b 0.002s
? lock_example/tools [no test files]
Happen two prints!
(also, i try with sync.Once, but the problem persists)
Questions
- When i run the
tools.OnlyOneWrite()i understand that a new variablewritedis created per package, two that start in false. Is this true? - What alternatives i have? I been thinking in a lock with a file, but the situation is similar, can happen that the
os.Createis called at the same time by the package A an B printing again two times
Use case of the real world
I been creating some integration tests, but i need to run a setup in the database (some CREATE TABLE, INSERTS...). So i create this package "tools" that makes that.
The package A refers to the integration tests of some process of my API, same for B. Twice call this func of the package "tools"
And the problem is A and B call the method that interact with the DB twice creating errors of "table already exists" (or if i surpass that, a duplicated primary key)
CREATE TABLE IF NOT EXISTSso it is created only once, as well as declaring columns as aPRIMARY KEYso no duplicates can be inserted, etc. You may also benefit from usingTRANSACTIONandROLLBACK...createsaren't mine and i can't modify that