diff --git a/action.yml b/action.yml
index 907b028..d51572a 100644
--- a/action.yml
+++ b/action.yml
@@ -14,7 +14,7 @@ inputs:
     description: Used to pull node distributions from go-versions.  Since there's a default, this is typically not supplied by the user.
     default: ${{ github.token }}
   cache:
-    description: 'Used to specify whether go-modules caching is needed or not. Supported values: true, false.'
+    description: 'Used to specify whether go-modules caching is needed. Set to true, if you'd like to enable caching.'
   cache-dependency-path:
     description: 'Used to specify the path to a dependency file: go.sum.'
 runs:
diff --git a/package.json b/package.json
index fd98837..78bac02 100644
--- a/package.json
+++ b/package.json
@@ -23,7 +23,10 @@
   "author": "GitHub",
   "license": "MIT",
   "dependencies": {
+    "@actions/cache": "^1.0.8",
     "@actions/core": "^1.6.0",
+    "@actions/exec": "^1.1.0",
+    "@actions/glob": "^0.2.0",
     "@actions/http-client": "^1.0.6",
     "@actions/io": "^1.0.2",
     "@actions/tool-cache": "^1.5.5",
diff --git a/src/cache-restore.ts b/src/cache-restore.ts
new file mode 100644
index 0000000..33d7283
--- /dev/null
+++ b/src/cache-restore.ts
@@ -0,0 +1,66 @@
+import * as cache from '@actions/cache';
+import * as core from '@actions/core';
+import * as glob from '@actions/glob';
+import path from 'path';
+import fs from 'fs';
+
+import {State, Outputs} from './constants';
+import {
+  getCacheDirectoryPath,
+  getPackageManagerInfo,
+  PackageManagerInfo
+} from './cache-utils';
+
+export const restoreCache = async (
+  packageManager: string, 
+  cacheDependencyPath?: string 
+) => {
+  const packageManagerInfo = await getPackageManagerInfo();
+  const platform = process.env.RUNNER_OS;
+
+  const cachePath = await getCacheDirectoryPath(
+    packageManagerInfo
+  );
+  
+  const goSumFilePath = cacheDependencyPath
+    ? cacheDependencyPath
+    : findGoSumFile(packageManagerInfo);
+  const fileHash = await glob.hashFiles(goSumFilePath);
+
+  if (!fileHash) {
+    throw new Error(
+      'Some specified paths were not resolved, unable to cache dependencies.'
+    );
+  }
+
+  const primaryKey = `go-cache-${platform}-${fileHash}`;
+  core.debug(`primary key is ${primaryKey}`);
+
+  core.saveState(State.CachePrimaryKey, primaryKey);
+
+  const cacheKey = await cache.restoreCache([cachePath], primaryKey);
+  core.setOutput('cache-hit', Boolean(cacheKey));
+
+  if (!cacheKey) {
+    core.info(`${packageManager} cache is not found`);
+    return;
+  }
+
+  core.saveState(State.CacheMatchedKey, cacheKey);
+  core.info(`Cache restored from key: ${cacheKey}`);
+};
+
+const findGoSumFile = (packageManager: PackageManagerInfo) => {
+  let goSumFile = packageManager.goSumFilePattern;
+  const workspace = process.env.GITHUB_WORKSPACE!;
+  const rootContent = fs.readdirSync(workspace);
+
+  const goSumFileExists = rootContent.includes(goSumFile);
+  if (!goSumFileExists) {
+    throw new Error(
+      `Dependencies file  go.sum is not found in ${workspace}. Supported file pattern: ${goSumFile}`
+    );
+  }
+
+  return path.join(workspace, goSumFile);
+};
diff --git a/src/cache-save.ts b/src/cache-save.ts
new file mode 100644
index 0000000..578df0b
--- /dev/null
+++ b/src/cache-save.ts
@@ -0,0 +1,60 @@
+import * as core from '@actions/core';
+import * as cache from '@actions/cache';
+import fs from 'fs';
+import {State} from './constants';
+import {getCacheDirectoryPath, getPackageManagerInfo} from './cache-utils';
+
+// Catch and log any unhandled exceptions.  These exceptions can leak out of the uploadChunk method in
+// @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to
+// throw an uncaught exception.  Instead of failing this action, just warn.
+process.on('uncaughtException', e => {
+  const warningPrefix = '[warning]';
+  core.info(`${warningPrefix}${e.message}`);
+});
+
+export async function run() {
+  try {
+    await cachePackages();
+  } catch (error) {
+    core.setFailed(error.message);
+  }
+}
+
+const cachePackages = async () => {
+  const state = core.getState(State.CacheMatchedKey);
+  const primaryKey = core.getState(State.CachePrimaryKey);
+
+  const packageManagerInfo = await getPackageManagerInfo();
+  
+  const cachePath = await getCacheDirectoryPath(
+    packageManagerInfo,
+  );
+
+  if (!fs.existsSync(cachePath)) {
+    throw new Error(
+      `Cache folder path is retrieved but doesn't exist on disk: ${cachePath}`
+    );
+  }
+
+  if (primaryKey === state) {
+    core.info(
+      `Cache hit occurred on the primary key ${primaryKey}, not saving cache.`
+    );
+    return;
+  }
+
+  try {
+    await cache.saveCache([cachePath], primaryKey);
+    core.info(`Cache saved with the key: ${primaryKey}`);
+  } catch (error) {
+    if (error.name === cache.ValidationError.name) {
+      throw error;
+    } else if (error.name === cache.ReserveCacheError.name) {
+      core.info(error.message);
+    } else {
+      core.warning(`${error.message}`);
+    }
+  }
+};
+
+run();
diff --git a/src/cache-utils.ts b/src/cache-utils.ts
new file mode 100644
index 0000000..b3ad60d
--- /dev/null
+++ b/src/cache-utils.ts
@@ -0,0 +1,49 @@
+import * as core from '@actions/core';
+import * as exec from '@actions/exec';
+
+export interface PackageManagerInfo {
+  goSumFilePattern: string;
+  getCacheFolderCommand: string;
+}
+
+export const defaultPackageManager: PackageManagerInfo = {
+    goSumFilePattern: 'go.sum',
+    getCacheFolderCommand: 'go env GOMODCACHE',
+};
+
+export const getCommandOutput = async (toolCommand: string) => {
+  let {stdout, stderr, exitCode} = await exec.getExecOutput(
+    toolCommand,
+    undefined,
+    {ignoreReturnCode: true}
+  );
+
+  if (exitCode) {
+    stderr = !stderr.trim()
+      ? `The '${toolCommand}' command failed with exit code: ${exitCode}`
+      : stderr;
+    throw new Error(stderr);
+  }
+
+  return stdout.trim();
+};
+
+export const getPackageManagerInfo = async () => {
+  
+  return defaultPackageManager;
+     
+};
+
+export const getCacheDirectoryPath = async (
+  packageManagerInfo: PackageManagerInfo,
+) => {
+  const stdout = await getCommandOutput(
+    packageManagerInfo.getCacheFolderCommand
+  ); 
+
+  if (!stdout) {
+    throw new Error(`Could not get cache folder path.`);
+  }
+
+  return stdout;
+};
diff --git a/src/constants.ts b/src/constants.ts
new file mode 100644
index 0000000..b43d18c
--- /dev/null
+++ b/src/constants.ts
@@ -0,0 +1,8 @@
+export enum State {
+  CachePrimaryKey = 'CACHE_KEY',
+  CacheMatchedKey = 'CACHE_RESULT'
+}
+
+export enum Outputs {
+  CacheHit = 'cache-hit'
+}
diff --git a/src/main.ts b/src/main.ts
index 5837dee..bfb8543 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -2,6 +2,7 @@ import * as core from '@actions/core';
 import * as io from '@actions/io';
 import * as installer from './installer';
 import path from 'path';
+import {restoreCache} from './cache-restore'; 
 import cp from 'child_process';
 import fs from 'fs';
 import {URL} from 'url';
@@ -13,10 +14,11 @@ export async function run() {
     // If not supplied then problem matchers will still be setup.  Useful for self-hosted.
     //
     let versionSpec = core.getInput('go-version');
-
+    
     // stable will be true unless false is the exact input
     // since getting unstable versions should be explicit
     let stable = (core.getInput('stable') || 'true').toUpperCase() === 'TRUE';
+    const cache = core.getInput('cache');
 
     core.info(`Setup go ${stable ? 'stable' : ''} version spec ${versionSpec}`);
 
@@ -41,6 +43,14 @@ export async function run() {
       core.info(`Successfully setup go version ${versionSpec}`);
     }
 
+    if (cache) {
+      if (isGhes()) {
+        throw new Error('Caching is not supported on GHES');
+      }
+      const cacheDependencyPath = core.getInput('cache-dependency-path');
+      await restoreCache(cache, cacheDependencyPath);
+    }
+
     // add problem matchers
     const matchersPath = path.join(__dirname, '..', 'matchers.json');
     core.info(`##[add-matcher]${matchersPath}`);