I have two for loops that are running in their own goroutine and they check different keys in a map many times. One of the for loops use a ticker for 1 second intervals so that is why I have to wait for time.Sleep(time.Second *2) instead of 1 second or less.
For example of one goroutine would be:
go func(){
timer1 := time.NewTicker(time.Second)
for _ = range timer1.C{
if randomMap("someKey")=="test" || randomMap("somethingElse")=="blah" {
fmt.Println("Hello world")
}
if some condition is met{
return
{
}
}()
While this goroutine is running I delete the someKey from the randomMap and it gives an error. I cannot check if the key exist because the very act of checking the map to see if a key exist gives a runtime error.
The only solution I was able to work around was to implement an extra if statement in the for loop to check if a condition indicated whether or the key from randomMap was deleted. So before I deleted the key in randomMap I would first change a conditional variable. Then I had to use time.Sleep(time.Second * 2) in order to give enough time for the goroutines to hit the correct conditional statement indicating the key in randomMap was deleted.
For example:
func someFunctiontoDeleteMapKey(){
randomMap.isDeleted = true
time.Sleep(time.Second * 2)
delete(randomMap, "someKey")
}
func someOtherFunctionInADifferentFile(){
go func(){
timer1 := time.NewTicker(time.Second)
for _ = range timer1.C{
if randomMap.isDeleted == false{
if randomMap("someKey")=="test" || randomMap("somethingElse")=="blah" {
fmt.Println("Hello world")
}
if some condition is met{
return
}
}else{
return
}
}
}()
}
It feels clumsy to have to call time.Sleep. Is there a way I could use channels to “wait” for the goroutine until it hits return?
Edit: Why is tabs disabled in the editor? So painful.
How do I go about doing this? I tried doing it but somehow it didn’t work. My functions are spread across in different files/scopes. I tried to use the someChannel := make(chan bool, 1) and
<- someChannel which will cause the goroutine to wait at that point until a boolean is passed to someChannel but when I do pass a boolean the someChannel does not proceed and it gets stucked there. I think it has to do because of scope issue.
I tried different ways such as moving the someChannel := make(chan bool, 1) to out a outer scope or passing in the someChannel through the goroutine function as a parameter but my program would still be stuck when it hit the <-someChannel. My program compiles fine and no errors are given during run time so I don’t know what I am doing wrong.
See how the <- done is holding off the program at that point until true is passed to the done channel. There are working in two different functions so their scope is not the same which is what I am trying to reproduce but on a much larger scale.
Yes, this is what I need in theory. Now I am trying to currently implement your idea in my code.
I originally made a global map so I only want one copy of it and every times its accessed/modified its the same original copy. This implementation is not good as its giving me these nil map errors.
So my question regarding the code you posted, is the m map[string]int64 a copy when its passed as s *S or is the actual map being passed in(no copy being made)?
I see the pointer in the method receiver s *S so I am assuming its passing the address and no copies are being made. But I am not certain.
Edit: okay so the golang blog says to make concurrent maps like, I guess thats how should I do it:
var counter = struct{
sync.RWMutex
m map[string]int
}{m: make(map[string]int)}
Sure. Just be sure to call counter.Lock() and counter.Unlock() around any counter.m[X] code.
*S is of type pointer-to-S-type. So it is passing a pointer to a location. When s.property is modified, only a single instance is modified, the instance *S points to.