Jump to content

Singleton: Difference between revisions

3,224 bytes added ,  7 years ago
→‎{{header|Go}}: expanded with sync.Once examples
m (added whitespace before the TOC, added other whitespace in the task's preamble.)
(→‎{{header|Go}}: expanded with sync.Once examples)
Line 789:
 
=={{header|Go}}==
'''sync.Once'''
{{works with|Go1}}
 
From the Go standard library, sync.Once provides a way to ensure that some "step," effectively an initialization step, is performed no more than once even if it might be attempted from multiple concurrent goroutines. This capability might be considered similar to some mechanism ensuring that singleton constructor code is only run once.
<lang go>package main
 
import (
"log"
"math/rand"
"sync"
"time"
)
 
var (
instance string
once sync.Once // initialize instance with once.Do
)
 
func claim(color string, w *sync.WaitGroup) {
time.Sleep(time.Duration(rand.Intn(1e8))) // hesitate up to .1 sec
log.Println("trying to claim", color)
once.Do(func() { instance = color })
log.Printf("tried %s. instance: %s", color, instance)
w.Done()
}
 
func main() {
rand.Seed(time.Now().Unix())
var w sync.WaitGroup
w.Add(2)
go claim("red", &w) // these two attempts run concurrently
go claim("blue", &w)
w.Wait()
log.Println("after trying both, instance =", instance)
}</lang>
{{out}}
<pre>
2016/07/01 20:36:02 trying to claim red
2016/07/01 20:36:02 tried red. instance: red
2016/07/01 20:36:02 trying to claim blue
2016/07/01 20:36:02 tried blue. instance: red
2016/07/01 20:36:02 after trying both, instance = red
</pre>
 
'''Packages as singletons'''
 
Go packages are singletons, in a way. Go does not use the word "class," and while Go structs might seem most like classes of other languages, Go packages are also like classes in that they represent an organization of declarations, including data and functions. All declarations in a package form a single ''package block.'' This block is delimited syntactically, has an associated identifier, and its members are accessed by this package identifier. This is much like classes in other languages.
 
Line 797 ⟶ 841:
// package level data declarations serve as singleton instance variables
var X, Y int
 
// package level initialization can serve as constructor code
func init() {
X, Y = 2, 3
}
 
// package level functions serve as methods for a package-as-a-singleton
Line 812 ⟶ 861:
func main() {
// dot selector syntax references package variables and functions
singlep.X = 2
singlep.Y = 3
fmt.Println(singlep.X, singlep.Y)
fmt.Println(singlep.F())
Line 821 ⟶ 868:
2 3
1
</pre>
 
'''Package data initialization with sync.Once'''
 
This example combines the two previous concepts and also shows some additional concepts. It has packages imported with a "diamond" dependency. While both <code>red</code> and <code>blue</code> import <code>single</code>, only a single variable <code>color</code> will exist in memory. The <code>init()</code> mechanism shown above actually runs before <code>main()</code>. In contrast, the <code>sync.Once</code> mechanism can serve as constructor code after <code>main()</code> begins.
 
<lang go>package single
 
import (
"log"
"sync"
)
 
var (
color string
once sync.Once
)
 
func Color() string {
if color == "" {
panic("color not initialized")
}
return color
}
 
func SetColor(c string) {
log.Println("color initialization")
once.Do(func() { color = c })
log.Println("color initialized to", color)
}</lang>
<lang go>package red
 
import (
"log"
 
"single"
)
 
func SetColor() {
log.Println("trying to set red")
single.SetColor("red")
}</lang>
<lang go>package blue
 
import (
"log"
 
"single"
)
 
func SetColor() {
log.Println("trying to set blue")
single.SetColor("blue")
}</lang>
<lang go>package main
 
import (
"log"
"math/rand"
"time"
 
"blue"
"red"
"single"
)
 
func main() {
rand.Seed(time.Now().Unix())
switch rand.Intn(3) {
case 1:
red.SetColor()
blue.SetColor()
case 2:
blue.SetColor()
red.SetColor()
}
log.Println(single.Color())
}</lang>
{{out}}
<pre>
2016/07/01 20:52:18 trying to set red
2016/07/01 20:52:18 color initialization
2016/07/01 20:52:18 color initialized to red
2016/07/01 20:52:18 trying to set blue
2016/07/01 20:52:18 color initialization
2016/07/01 20:52:18 color initialized to red
2016/07/01 20:52:18 red
</pre>
 
1,707

edits

Cookies help us deliver our services. By using our services, you agree to our use of cookies.