diff --git a/docs/settings.md b/docs/settings.md
index 1a98e1ec1e..ed12cf7b9b 100644
--- a/docs/settings.md
+++ b/docs/settings.md
@@ -210,12 +210,14 @@ Feature level setting to enable/disable code lens for references and run/debug t
 | --- | --- |
 | `references` | If true, enables the references code lens. Uses guru. Recalculates when there is change to the document followed by scrolling. Unnecessary when using the language server; use the call graph feature instead. <br/> Default: `false` |
 | `runtest` | If true, enables code lens for running and debugging tests <br/> Default: `true` |
+| `runmain` | If true, enables code lens for running main func <br/> Default: `true` |
 
 Default:
 ```
 {
 	"references" :	false,
 	"runtest" :	true,
+	"runmain" :	true,
 }
 ```
 ### `go.formatFlags`
@@ -497,7 +499,7 @@ Allowed Options: `package`, `workspace`, `off`
 Default: `"package"`
 ### `gopls`
 
-Customize `gopls` behavior by specifying the gopls' settings in this section. For example, 
+Customize `gopls` behavior by specifying the gopls' settings in this section. For example,
 ```
 "gopls" : {
 	"build.directoryFilters": ["-node_modules"]
diff --git a/package.json b/package.json
index 77a98294b4..c7cc2b030b 100644
--- a/package.json
+++ b/package.json
@@ -489,6 +489,11 @@
         "title": "Go: Reset Global State",
         "description": "Reset keys in global state to undefined."
       },
+      {
+        "command": "go.runMain",
+        "title": "Go: Run main() func on file",
+        "description": "Run main() func on file"
+      },
       {
         "command": "go.explorer.refresh",
         "title": "Go Explorer: Refresh",
@@ -1606,12 +1611,18 @@
               "type": "boolean",
               "default": true,
               "description": "If true, enables code lens for running and debugging tests"
+            },
+            "runmain": {
+              "type": "boolean",
+              "default": true,
+              "description": "If true, enables code lens for running main func"
             }
           },
           "additionalProperties": false,
           "default": {
             "references": false,
-            "runtest": true
+            "runtest": true,
+            "runmain": true
           },
           "description": "Feature level setting to enable/disable code lens for references and run/debug tests",
           "scope": "resource"
diff --git a/src/goMain.ts b/src/goMain.ts
index 7f51928118..17c8beb3e5 100644
--- a/src/goMain.ts
+++ b/src/goMain.ts
@@ -60,6 +60,7 @@ import { GO111MODULE, goModInit, isModSupported } from './goModules';
 import { playgroundCommand } from './goPlayground';
 import { GoReferencesCodeLensProvider } from './goReferencesCodelens';
 import { GoRunTestCodeLensProvider } from './goRunTestCodelens';
+import { GoMainCodeLensProvider, runMainFunc } from './goMainCodelens';
 import { disposeGoStatusBar, expandGoStatusBar, outputChannel, updateGoStatusBar } from './goStatus';
 import {
 	debugPrevious,
@@ -210,9 +211,11 @@ If you would like additional configuration for diagnostics from gopls, please se
 		})
 	);
 	const testCodeLensProvider = new GoRunTestCodeLensProvider();
+	const mainCodeLensProvider = new GoMainCodeLensProvider();
 	const referencesCodeLensProvider = new GoReferencesCodeLensProvider();
 
 	ctx.subscriptions.push(vscode.languages.registerCodeLensProvider(GO_MODE, testCodeLensProvider));
+	ctx.subscriptions.push(vscode.languages.registerCodeLensProvider(GO_MODE, mainCodeLensProvider));
 	ctx.subscriptions.push(vscode.languages.registerCodeLensProvider(GO_MODE, referencesCodeLensProvider));
 
 	// debug
@@ -481,6 +484,7 @@ If you would like additional configuration for diagnostics from gopls, please se
 
 			if (updatedGoConfig['enableCodeLens']) {
 				testCodeLensProvider.setEnabled(updatedGoConfig['enableCodeLens']['runtest']);
+				mainCodeLensProvider.setEnabled(updatedGoConfig['enableCodeLens']['runmain']);
 				referencesCodeLensProvider.setEnabled(updatedGoConfig['enableCodeLens']['references']);
 			}
 
@@ -564,6 +568,12 @@ If you would like additional configuration for diagnostics from gopls, please se
 		})
 	);
 
+	ctx.subscriptions.push(
+		vscode.commands.registerCommand('go.runMain', (args) => {
+			runMainFunc()
+		})
+	)
+
 	ctx.subscriptions.push(
 		vscode.commands.registerCommand('go.show.commands', () => {
 			const extCommands = getExtensionCommands();
diff --git a/src/goMainCodelens.ts b/src/goMainCodelens.ts
new file mode 100644
index 0000000000..ce375e15d2
--- /dev/null
+++ b/src/goMainCodelens.ts
@@ -0,0 +1,121 @@
+/* eslint-disable @typescript-eslint/no-unused-vars */
+/* eslint-disable @typescript-eslint/no-explicit-any */
+/*---------------------------------------------------------
+ * Copyright (C) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
+ *--------------------------------------------------------*/
+
+'use strict';
+
+import vscode = require('vscode');
+import cp = require('child_process');
+
+import { CancellationToken, CodeLens, TextDocument } from 'vscode';
+import { getGoConfig } from './config';
+import { GoBaseCodeLensProvider } from './goBaseCodelens';
+import { GoDocumentSymbolProvider } from './goOutline';
+import { getBinPath } from './util';
+import { envPath, getCurrentGoRoot } from './utils/pathUtils';
+import { reject } from 'lodash';
+
+export class GoMainCodeLensProvider extends GoBaseCodeLensProvider {
+	private readonly mainRegex = /^main$/;
+
+	public async provideCodeLenses(document: TextDocument, token: CancellationToken): Promise<CodeLens[]> {
+		if (!this.enabled) {
+			return [];
+		}
+		const config = getGoConfig(document.uri);
+		const codeLensConfig = config.get<{ [key: string]: any }>('enableCodeLens');
+		const codelensEnabled = codeLensConfig ? codeLensConfig['runmain'] : false;
+		if (!codelensEnabled || !document.fileName.match('main.go')) {
+			return [];
+		}
+
+		const codelenses = await Promise.all([
+			this.getCodeLensForMainFunc(document, token)
+		]);
+		return ([] as CodeLens[]).concat(...codelenses);
+	}
+
+	// Return the first main function
+	private async getMainFunc(
+		doc: vscode.TextDocument,
+		token: vscode.CancellationToken
+	): Promise<vscode.DocumentSymbol | undefined> {
+		const documentSymbolProvider = new GoDocumentSymbolProvider(true);
+		const symbols = await documentSymbolProvider.provideDocumentSymbols(doc, token);
+		if (!symbols || symbols.length === 0) {
+			return;
+		}
+		const symbol = symbols[0];
+		if (!symbol) {
+			return;
+		}
+		const children = symbol.children;
+
+		return children.find(sym => sym.kind === vscode.SymbolKind.Function && this.mainRegex.test(sym.name));
+	}
+
+	private async getCodeLensForMainFunc(document: TextDocument, token: CancellationToken): Promise<CodeLens[]> {
+		const mainPromise = async (): Promise<CodeLens[]> => {
+			const mainFunc = await this.getMainFunc(document, token);
+			if (!mainFunc) {
+				return [];
+			}
+
+			return [
+				new CodeLens(mainFunc.range, {
+					title: 'run main',
+					command: 'go.runMain',
+					arguments: [{ functionName: mainFunc.name }]
+				})
+			];
+		};
+
+		return await mainPromise();
+	}
+}
+
+const mainFuncOutputChannel = vscode.window.createOutputChannel('Go Main');
+
+export async function runMainFunc() {
+	let outputChannel = mainFuncOutputChannel
+	const goRuntimePath = getBinPath('go');
+	if (!goRuntimePath) {
+		vscode.window.showErrorMessage(
+			`Failed to run "go run ." as the "go" binary cannot be found in either GOROOT(${getCurrentGoRoot}) or PATH(${envPath})`
+		);
+		return Promise.resolve(false);
+	}
+
+	const editor = vscode.window.activeTextEditor;
+	const documentUri = editor ? editor.document.uri : null;
+	const args = ['run', documentUri.path];
+
+	outputChannel.clear()
+	outputChannel.show(true)
+	outputChannel.appendLine(["Running main func: ", goRuntimePath, ...args].join(' '))
+
+	cp.execFile(
+		goRuntimePath,
+		args,
+		{ },
+		(err, stdout, stderr) => {
+			try {
+				if (err) {
+					outputChannel.appendLine(err.message);
+					return;
+				}
+				if (stdout) {
+					outputChannel.append(stdout);
+				}
+				if (stderr) {
+					outputChannel.append(stderr);
+				}
+			} catch (e) {
+				reject(e);
+			}
+		}
+	)
+}
\ No newline at end of file