Returning values from sync.Once.Do

4,420 views
Skip to first unread message

Archos

unread,
Sep 16, 2010, 6:57:18 AM9/16/10
to golang-nuts
Working with `sync.Once.Do`, I see, that values can not be directly
returned from there, why?

***
var once sync.Once

func foo() os.Error {
once.Do(func() { return bar(arg1) })
}
***

In change, I've to do:

***
func foo() (e os.Error) {
once.Do(func() { e = bar(arg1) })
return e
}
***

jimmy frasche

unread,
Sep 16, 2010, 7:01:11 AM9/16/10
to Archos, golang-nuts

What would it return the second time it's called?

roger peppe

unread,
Sep 16, 2010, 7:07:35 AM9/16/10
to jimmy frasche, Archos, golang-nuts
it could return the same thing every time.
it's an easy change to make.

Archos

unread,
Sep 16, 2010, 7:22:24 AM9/16/10
to golang-nuts

On Sep 16, 11:01 am, jimmy frasche <soapboxcic...@gmail.com> wrote:
In my case, could return different values

Andrew Gerrand

unread,
Sep 16, 2010, 7:28:51 AM9/16/10
to Archos, golang-nuts
On 16 September 2010 21:22, Archos <raul...@sent.com> wrote:
>> What would it return the second time it's called?
> In my case, could return different values

This raises a lot of questions, the answers to which are non-obvious
(to me at least). The semantics of sync.Once is very simple; I'd go so
far as to say it's beautiful. Why complicate it, when you can get the
behaviour you need with easy-to-read code?

Andrew

Archos

unread,
Sep 16, 2010, 7:32:11 AM9/16/10
to golang-nuts


On Sep 16, 11:28 am, Andrew Gerrand <a...@golang.org> wrote:
> On 16 September 2010 21:22, Archos <raul....@sent.com> wrote:
>
> >> What would it return the second time it's called?
> > In my case, could return different values
>
> This raises a lot of questions, the answers to which are non-obvious
> (to me at least). The semantics of sync.Once is very simple; I'd go so
> far as to say it's beautiful. Why complicate it, when you can get the
> behaviour you need with easy-to-read code?
I agree. It was to know if there was some error

roger peppe

unread,
Sep 16, 2010, 7:48:40 AM9/16/10
to Archos, golang-nuts
On 16 September 2010 12:22, Archos <raul...@sent.com> wrote:
>> What would it return the second time it's called?
> In my case, could return different values

how could it return different values? surely the whole
point of "once" is that the function is called once only.
so there's only one value to return.

your function foo() will always return nil the second
time it's called.

Rob 'Commander' Pike

unread,
Sep 16, 2010, 8:00:09 AM9/16/10
to roger peppe, jimmy frasche, Archos, golang-nuts
On Thu, Sep 16, 2010 at 9:07 PM, roger peppe <rogp...@gmail.com> wrote:
> it could return the same thing every time.
> it's an easy change to make.

the spec would require it to return an interface{}. it seems like
special pleading to me. better to use the function it calls to write
down the value with the type you want. then after any call to
once.Do(f), that value is available, safely.

-rob

Archos

unread,
Sep 16, 2010, 8:02:44 AM9/16/10
to golang-nuts
That is not always true, e.g. on this code snippet:

***

/* Gets the password-file entry for the given UID. */
func GetpwByUid(uid uint32) (f *fieldPasswd, err os.Error) {
//once.Do(func() { return parsePasswd(pwUID, uid) })
oncePasswd.Do(func() { f, err = parsePasswd(pwUID, uid) })
return f, err
}

// Searchs the value into the field of each line
func parsePasswd(name field, value interface{}) (*fieldPasswd,
os.Error) {
...
}
***

When is used a different argument for "GetpwByUid()" then will be
returned a different value.


On Sep 16, 11:48 am, roger peppe <rogpe...@gmail.com> wrote:

jimmy frasche

unread,
Sep 16, 2010, 8:07:15 AM9/16/10
to Archos, golang-nuts

Do you want a function that returns the same output for the same input
without having to redo the calculations? That's not what once.Do is
for.

roger peppe

unread,
Sep 16, 2010, 9:37:34 AM9/16/10
to Archos, golang-nuts
On 16 September 2010 13:02, Archos <raul...@sent.com> wrote:
> That is not always true, e.g. on this code snippet:
>
> ***
>
> /* Gets the password-file entry for the given UID. */
> func GetpwByUid(uid uint32) (f *fieldPasswd, err os.Error) {
>        //once.Do(func() { return parsePasswd(pwUID, uid) })
>        oncePasswd.Do(func() { f, err = parsePasswd(pwUID, uid) })
>        return f, err
> }
[...]

> When is used a different argument for "GetpwByUid()" then will be
> returned a different value.

have you tried it?
assuming oncePasswd remains the same, the argument to oncePasswd.Do
will be evaluated only once - i.e. the value of f and err will be
changed only once, on the first call to GetpwByUid. on subsequent
calls, even though a new closure is created, it will not be called.

roger peppe

unread,
Sep 16, 2010, 9:53:28 AM9/16/10
to Rob 'Commander' Pike, jimmy frasche, Archos, golang-nuts

yes, that's definitely better.
i said it was an easy change to make - i wasn't trying to imply
that i wanted it to happen.

Reply all
Reply to author
Forward
0 new messages