Skip to content

Instantly share code, notes, and snippets.

@mauleyzaola
Forked from dragonsinth/getfriends_select.go
Created October 28, 2022 03:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mauleyzaola/28bc539f708f0b3a155d20911f433367 to your computer and use it in GitHub Desktop.
Save mauleyzaola/28bc539f708f0b3a155d20911f433367 to your computer and use it in GitHub Desktop.
GetFriends using select
func GetFriends(ctx context.Context, user int64) (map[string]*User, error) {
g, ctx := errgroup.WithContext(ctx)
friendIds := make(chan int64)
// Produce
g.Go(func() error {
defer close(friendIds)
for it := GetFriendIds(user); ; {
if id, err := it.Next(ctx); err != nil {
if err == io.EOF {
return nil
}
return fmt.Errorf("GetFriendIds %d: %s", user, err)
} else {
select {
case <-ctx.Done():
return ctx.Err()
case friendIds <- id:
}
}
}
})
friends := make(chan *User)
// Map
workers := int32(nWorkers)
for i := 0; i < nWorkers; i++ {
g.Go(func() error {
defer func() {
// Last one out closes shop
if atomic.AddInt32(&workers, -1) == 0 {
close(friends)
}
}()
for id := range friendIds {
if friend, err := GetUserProfile(ctx, id); err != nil {
return fmt.Errorf("GetUserProfile %d: %s", user, err)
} else {
select {
case <-ctx.Done():
return ctx.Err()
case friends <- friend:
}
}
}
return nil
})
}
// Reduce
ret := map[string]*User{}
g.Go(func() error {
for friend := range friends {
ret[friend.Name] = friend
}
return nil
})
return ret, g.Wait()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment