-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
singleflight: Add an example #73
base: master
Are you sure you want to change the base?
Conversation
singleflight/example_test.go
Outdated
wg.Add(1) | ||
go func(i int) { | ||
ctrval, _ := g.Do("key", func() (interface{}, error) { | ||
counter++ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like how this example basically teaches people how to write data races. You have to already understand how singleflight works to understand why this perhaps is safe.
Use atomic.AddInt32 instead? And then put a same-line // atomic
comment on the var counter int32 // atomic
line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
singleflight/example_test.go
Outdated
@@ -0,0 +1,37 @@ | |||
package singleflight |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing copyright header.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
singleflight/example_test.go
Outdated
} | ||
// Sleep so all of the goroutines start before we send a message on the | ||
// channel | ||
time.Sleep(10 * time.Millisecond) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm never a fan of sleeps in tests. Use a channel or something to wait for everybody to get in there instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I played around with this but I don't think it's possible. Thread 1 enters the function body, but I don't think threads 2-5 have a way to broadcast to thread 1 that they have also entered the Do() and are waiting for the results. The test for this functionality also uses a sleep. :(
I think the example is getting a little too complex, so I got rid of the threads and just added a comment explaining the behavior.
5ea4293
to
ef32c4f
Compare
singleflight/example_test.go
Outdated
} | ||
|
||
func Example() { | ||
var g singleflight.Group |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is generally a global variable. With this style of example (func Example), it will show the whole file, right? So I think you can move this out? Then you'd want to name it something better than "g".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
ef32c4f
to
f3f9685
Compare
f3f9685
to
f63e6c5
Compare
Check errors too. |
f63e6c5
to
8340aba
Compare
Done. Thank you for the review! And sorry for being so slow.
|
Copyright Google isn't right. You're not a Google employee I don't think? I'd make it match the rest of Go and be copyright The Go Authors. |
Ah, sorry, I copied it from another file in that repo. Should I update the On Saturday, October 29, 2016, Brad Fitzpatrick [email protected]
Kevin Burke |
Just one for now. Once a non-Googler touches other files they can update it. |
8340aba
to
fdb9e97
Compare
Done |
singleflight/example_test.go
Outdated
func expensiveNetworkCall() (interface{}, error) { | ||
time.Sleep(1) | ||
atomic.AddInt32(&counter, 1) | ||
return counter, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a data race. You're reading from counter without atomics.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yikes. Should be fixed now. Thanks for sticking with this through several rounds.
fdb9e97
to
5680294
Compare
Looks like you still have that data race to fix, @kevinburke :-) |
Yikes. I think I forgot to push my branch months ago when I left this
comment. Let me double check
…On Thu, Dec 22, 2016 at 07:28 Hunter Blanks ***@***.***> wrote:
Looks like you still have that data race to fix, @kevinburke
<https://github.com/kevinburke> :-)
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#73 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAOSI6xQFVCqigIGlirJsqVwTgCfC0r-ks5rKpcOgaJpZM4KeD5v>
.
|
singleflight/example_test.go
Outdated
} | ||
|
||
func Example() { | ||
// No matter how many threads call Do, only one network call per key will |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no "threads"
singleflight/example_test.go
Outdated
// No matter how many threads call Do, only one network call per key will | ||
// be in progress at any time. Callers that share a key will get the same | ||
// results as an in-flight call with that key. | ||
v, err := networkGroup.Do("key", expensiveNetworkCall) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Normally this expensiveNetworkCall is a closure, closing over the key
value. Maybe show an addition of +1 instead and say:
// Imagine this is something expensive:
return n + 1, nil
And make your "key" be:
n := 41
group.Do(strconv.Itoa(n), func(...) {..
(no need to mention 'network')
5680294
to
f1fb5e5
Compare
Apologies for the delay, but I've finally made the changes you requested. |
I was curious about the best way to initialize a Group - it turns out you just do `var g Group` - but figured this package could use a package-level example demonstrating an example use case.
f1fb5e5
to
91138e8
Compare
var counter int32 | ||
var group singleflight.Group | ||
|
||
func Example() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be a testing case, like TestSingleFlightExample, and use testing.T
for checking?
I was curious about the best way to initialize a Group - it turns out you just
do
var g Group
- but figured this package could use a package-level exampledemonstrating an example use case.
I've signed the CLA.