code: func fetchGroupVersionResources(d DiscoveryInterface, apiGroups *metav1.APIGroupList) (map[schema.GroupVersion]*metav1.APIResourceList, map[schema.GroupVersion]error) {
  	groupVersionResources := make(map[schema.GroupVersion]*metav1.APIResourceList)
  	failedGroups := make(map[schema.GroupVersion]error)
  
  	wg := &sync.WaitGroup{}
  	resultLock := &sync.Mutex{}
  	for _, apiGroup := range apiGroups.Groups {
  		for _, version := range apiGroup.Versions {
  			groupVersion := schema.GroupVersion{Group: apiGroup.Name, Version: version.Version}
  			wg.Add(1)
  			go func() {
  				defer wg.Done()
  				defer utilruntime.HandleCrash()
  
  				apiResourceList, err := d.ServerResourcesForGroupVersion(groupVersion.String())
  
  				// lock to record results
  				resultLock.Lock()
  				defer resultLock.Unlock()
  
  				if err != nil {
  					// TODO: maybe restrict this to NotFound errors
  					failedGroups[groupVersion] = err
  				}
  				if apiResourceList != nil {
  					// even in case of error, some fallback might have been returned
  					groupVersionResources[groupVersion] = apiResourceList
  				}
  			}()
  		}
  	}
  	wg.Wait()
  
  	return groupVersionResources, failedGroups
  }
docs: // fetchServerResourcesForGroupVersions uses the discovery client to fetch the resources for the specified groups in parallel.