'Static global variables in Go
I am new in Go language and I need some help. I have declared a global variable but the problem is that it does not keep its value. It would be solved with a static variable but no such variables exist in Go. How should I solve this?
gID
is a global variable. This function is called twice. On the first call if
code is executed. On the second, else
code is executed. I want the second struct Learner
instance, to get first Learner's instance ID.
I have to mention that NewLearner is called twice from two different files from different packages.
func NewLearner(name string, peerURLs types.URLs, clusterName string, now *time.Time) *Learner {
l := &Learner{
RaftAttributes: RaftAttributes{PeerURLs: peerURLs.StringSlice()},
Attributes: Attributes{Name: name},
}
var b []byte
sort.Strings(l.PeerURLs)
for _, p := range l.PeerURLs {
b = append(b, []byte(p)...)
}
b = append(b, []byte(clusterName)...)
if now != nil {
b = append(b, []byte(fmt.Sprintf("%d", now.Unix()))...)
hash := sha1.Sum(b)
l.ID = types.ID(binary.BigEndian.Uint64(hash[:8]))
gID=l.ID
return l
} else {
l.ID = gID
return l
}
}
Solution 1:[1]
The fact that the package variable doesn't keep its value might be caused by concurrency. I would solve your problem that way. Use a package variable with a mutex around in case the function is called concurrently.
import "sync"
var(
gID uint64
muID sync.Mutex
)
func myfunc(param bool) {
var id uint64
if param {
id = newID()
muID.Lock()
gID = id
muID.Unlock()
} else {
muID.Lock()
id = gID
muID.Unlock()
}
}
Solution 2:[2]
How about using a channel? You can have channel (global in your context) of uint64
.
idChan := make(chan uint64)
And then inside your if condition you can put the gID
in the idChan
and read the same from your else
condition.. something like this:
if now != nil {
b = append(b, []byte(fmt.Sprintf("%d", now.Unix()))...)
hash := sha1.Sum(b)
l.ID = types.ID(binary.BigEndian.Uint64(hash[:8]))
idChan <- l.ID
return l
} else {
l.ID <- idChan
return l
}
Do remember to close your channel appropriately though if you dont want to use it anywhere else anymore.
Although, i must advise that such stuffs are usually better and more safely handled by goroutines with waitgroups probably since you actually want to share a value. In your case something like maybe a goroutine that does if part and another that does the else part and then share this channel amongst those two goroutines and wait on the wait groups for code that depends on these goroutines completion. That really is what concurrency is.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Dolanor |
Solution 2 | Nik |