diff --git a/lib/datasource/go/goproxy.ts b/lib/datasource/go/goproxy.ts
index 01f341989ae64bd4dc7f1818be3020472a62f174..b6e6fb97adeee111578f07a5ab3e7f0e6ef43bc2 100644
--- a/lib/datasource/go/goproxy.ts
+++ b/lib/datasource/go/goproxy.ts
@@ -156,10 +156,10 @@ export async function versionInfo(
   return result;
 }
 
-export async function getReleases(
-  config: GetReleasesConfig
-): Promise<ReleaseResult | null> {
-  const { lookupName } = config;
+export async function getReleases({
+  lookupName,
+}: GetReleasesConfig): Promise<ReleaseResult | null> {
+  logger.trace(`goproxy.getReleases(${lookupName})`);
 
   const noproxy = parseNoproxy();
   if (noproxy?.test(lookupName)) {
diff --git a/lib/datasource/go/index.ts b/lib/datasource/go/index.ts
index 99c554cbba3cf40d395a7a06f8e27e15d3bb78f8..9a2e2bc46b84d57e0661a0e926b9398c06edc0a0 100644
--- a/lib/datasource/go/index.ts
+++ b/lib/datasource/go/index.ts
@@ -1,117 +1,18 @@
-import { logger } from '../../logger';
-import { regEx } from '../../util/regex';
-import * as github from '../github-tags';
-import * as gitlab from '../gitlab-tags';
 import type { GetReleasesConfig, ReleaseResult } from '../types';
 import * as goproxy from './goproxy';
-import { bitbucket, getDatasource } from './util';
+import { getReleases as directReleases } from './releases-direct';
 
 export { id } from './common';
 
 export const customRegistrySupport = false;
 
-/**
- * go.getReleases
- *
- * This datasource resolves a go module URL into its source repository
- *  and then fetch it if it is on GitHub.
- *
- * This function will:
- *  - Determine the source URL for the module
- *  - Call the respective getReleases in github/gitlab to retrieve the tags
- *  - Filter module tags according to the module path
- */
 export async function getReleases(
   config: GetReleasesConfig
 ): Promise<ReleaseResult | null> {
-  const { lookupName } = config;
-
-  let res: ReleaseResult = null;
-
-  logger.trace(`goproxy.getReleases(${lookupName})`);
-  res = await goproxy.getReleases(config);
+  const res = await goproxy.getReleases(config);
   if (res) {
     return res;
   }
 
-  logger.trace(`go.getReleases(${lookupName})`);
-  const source = await getDatasource(lookupName);
-
-  if (!source) {
-    logger.info(
-      { lookupName },
-      'Unsupported go host - cannot look up versions'
-    );
-    return null;
-  }
-
-  switch (source.datasource) {
-    case github.id: {
-      res = await github.getReleases(source);
-      break;
-    }
-    case gitlab.id: {
-      res = await gitlab.getReleases(source);
-      break;
-    }
-    case bitbucket.id: {
-      res = await bitbucket.getReleases(source);
-      break;
-    }
-    /* istanbul ignore next: can never happen, makes lint happy */
-    default: {
-      return null;
-    }
-  }
-
-  // istanbul ignore if
-  if (!res) {
-    return null;
-  }
-
-  /**
-   * github.com/org/mod/submodule should be tagged as submodule/va.b.c
-   * and that tag should be used instead of just va.b.c, although for compatibility
-   * the old behaviour stays the same.
-   */
-  const nameParts = lookupName.replace(regEx(/\/v\d+$/), '').split('/');
-  logger.trace({ nameParts, releases: res.releases }, 'go.getReleases');
-
-  // If it has more than 3 parts it's a submodule or subgroup (gitlab only)
-  if (nameParts.length > 3) {
-    const prefix = nameParts.slice(3, nameParts.length).join('/');
-    logger.trace(`go.getReleases.prefix:${prefix}`);
-
-    // Filter the releases so that we only get the ones that are for this submodule
-    // Also trim the submodule prefix from the version number
-    const submodReleases = res.releases
-      .filter((release) => release.version?.startsWith(prefix))
-      .map((release) => {
-        const r2 = release;
-        r2.version = r2.version.replace(`${prefix}/`, '');
-        return r2;
-      });
-    logger.trace({ submodReleases }, 'go.getReleases');
-
-    // If not from gitlab -> no subgroups -> must be submodule
-    // If from gitlab and directory one level above has tags -> has to be submodule, since groups can't have tags
-    // If not, it's simply a repo in a subfolder, and the normal tags are used.
-    if (
-      !(source.datasource === gitlab.id) ||
-      (source.datasource === gitlab.id && submodReleases.length)
-    ) {
-      return {
-        sourceUrl: res.sourceUrl,
-        releases: submodReleases,
-      };
-    }
-  }
-
-  if (res.releases) {
-    res.releases = res.releases.filter((release) =>
-      release.version?.startsWith('v')
-    );
-  }
-
-  return res;
+  return directReleases(config);
 }
diff --git a/lib/datasource/go/releases-direct.ts b/lib/datasource/go/releases-direct.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f3a3cdce47faa3eca48b5d637a9b55aff84da7fe
--- /dev/null
+++ b/lib/datasource/go/releases-direct.ts
@@ -0,0 +1,106 @@
+import { logger } from '../../logger';
+import { regEx } from '../../util/regex';
+import * as github from '../github-tags';
+import * as gitlab from '../gitlab-tags';
+import type { GetReleasesConfig, ReleaseResult } from '../types';
+import { bitbucket, getDatasource } from './util';
+
+/**
+ * go.getReleases
+ *
+ * This datasource resolves a go module URL into its source repository
+ *  and then fetch it if it is on GitHub.
+ *
+ * This function will:
+ *  - Determine the source URL for the module
+ *  - Call the respective getReleases in github/gitlab to retrieve the tags
+ *  - Filter module tags according to the module path
+ */
+export async function getReleases(
+  config: GetReleasesConfig
+): Promise<ReleaseResult | null> {
+  const { lookupName } = config;
+
+  let res: ReleaseResult = null;
+
+  logger.trace(`go.getReleases(${lookupName})`);
+  const source = await getDatasource(lookupName);
+
+  if (!source) {
+    logger.info(
+      { lookupName },
+      'Unsupported go host - cannot look up versions'
+    );
+    return null;
+  }
+
+  switch (source.datasource) {
+    case github.id: {
+      res = await github.getReleases(source);
+      break;
+    }
+    case gitlab.id: {
+      res = await gitlab.getReleases(source);
+      break;
+    }
+    case bitbucket.id: {
+      res = await bitbucket.getReleases(source);
+      break;
+    }
+    /* istanbul ignore next: can never happen, makes lint happy */
+    default: {
+      return null;
+    }
+  }
+
+  // istanbul ignore if
+  if (!res) {
+    return null;
+  }
+
+  /**
+   * github.com/org/mod/submodule should be tagged as submodule/va.b.c
+   * and that tag should be used instead of just va.b.c, although for compatibility
+   * the old behaviour stays the same.
+   */
+  const nameParts = lookupName.replace(regEx(/\/v\d+$/), '').split('/');
+  logger.trace({ nameParts, releases: res.releases }, 'go.getReleases');
+
+  // If it has more than 3 parts it's a submodule or subgroup (gitlab only)
+  if (nameParts.length > 3) {
+    const prefix = nameParts.slice(3, nameParts.length).join('/');
+    logger.trace(`go.getReleases.prefix:${prefix}`);
+
+    // Filter the releases so that we only get the ones that are for this submodule
+    // Also trim the submodule prefix from the version number
+    const submodReleases = res.releases
+      .filter((release) => release.version?.startsWith(prefix))
+      .map((release) => {
+        const r2 = release;
+        r2.version = r2.version.replace(`${prefix}/`, '');
+        return r2;
+      });
+    logger.trace({ submodReleases }, 'go.getReleases');
+
+    // If not from gitlab -> no subgroups -> must be submodule
+    // If from gitlab and directory one level above has tags -> has to be submodule, since groups can't have tags
+    // If not, it's simply a repo in a subfolder, and the normal tags are used.
+    if (
+      !(source.datasource === gitlab.id) ||
+      (source.datasource === gitlab.id && submodReleases.length)
+    ) {
+      return {
+        sourceUrl: res.sourceUrl,
+        releases: submodReleases,
+      };
+    }
+  }
+
+  if (res.releases) {
+    res.releases = res.releases.filter((release) =>
+      release.version?.startsWith('v')
+    );
+  }
+
+  return res;
+}