I'm learning Go, and this is my first attempt at a command-line tool that uses the GitHub API to calculate the average time that takes for a pull request to get merged for a particular organisation or repository.
The algorithm follows a very simple approach:
- Get all the repositories for an organisation.
- For each repository, get all the
closed
pull requests. - Calculate the average time using
merged_at
andcreated_at
of each pull request.
For large organisations/projects, step 2 can take a long time, especially if it can't get all the pull requests from a single result page. So I want to execute that part concurrently.
Here's the part of the code that does that: GitHub
c := make(chan Result, len(repos))
var wg sync.WaitGroup
for _, repo := range repos {
wg.Add(1)
go func(val Repository) {
if cmd.Debug {
fmt.Printf("Executing goroutine for value: %s", val.Name)
}
pullRequests, err := getPullRequests(ctx, client, val)
c <- Result{PullRequests: pullRequests, Err: err}
wg.Done()
}(repo)
}
wg.Wait()
close(c)
timeAccumulator := float64(0)
prAccumulator := int64(0)
var cmdErr error
for result := range c {
pullRequests, err := result.PullRequests, result.Err
if err != nil {
cmdErr = err
break
}
for _, pullRequest := range pullRequests {
if pullRequest.GetMergedAt().IsZero() {
continue
}
delta := pullRequest.GetMergedAt().Sub(pullRequest.GetCreatedAt()).Hours()
timeAccumulator += delta
prAccumulator++
if cmd.Debug {
fmt.Printf("PR: %s\nCreated at: %v\nMerged at:%v\nDelta in hours: %f\n", pullRequest.GetTitle(), pullRequest.GetCreatedAt(), pullRequest.GetMergedAt(), delta)
}
}
}
It works, but I'd like to get some feedback about the WaitGroup
usage. It does feel that I don't need it here, because looping over range c
would take results until the channel is closed. It's just not clear to me when I should really close the channel without a WaitGroup
.
And of course any other feedback is really welcomed!