use the GOBIN value reported by go env

Teach vscode-go to use the value of GOBIN as reported by `go env`. This is beneficial when VSCode is launched outside of a terminal (e.g. - macOS Dock) where the user's environment variables may not be available.

If GOBIN had been set via `go env -w GOBIN=...`, then the go tools installed by the extension would be deployed there, but the extension would not end up finding them because it only looked for GOBIN as an environment variable. It looks like the extension already supported reading GOROOT, GOPATH, and GOPROXY from `go env`, so this adds GOBIN.

Change-Id: Ib3b0db1d30ae91f2e8ca721f6c7f71eefff41728
GitHub-Last-Rev: a9aade765158475343f4366a8dbcf003a85957ae
GitHub-Pull-Request: golang/vscode-go#93
Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/235197
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
diff --git a/src/goInstallTools.ts b/src/goInstallTools.ts
index 3d8508f..4eb9cec 100644
--- a/src/goInstallTools.ts
+++ b/src/goInstallTools.ts
@@ -372,13 +372,13 @@
 	}
 }
 
-export function updateGoPathGoRootFromConfig(): Promise<void> {
+export function updateGoVarsFromConfig(): Promise<void> {
 	const goroot = getGoConfig()['goroot'];
 	if (goroot) {
 		process.env['GOROOT'] = resolvePath(goroot);
 	}
 
-	if (process.env['GOPATH'] && process.env['GOROOT'] && process.env['GOPROXY']) {
+	if (process.env['GOPATH'] && process.env['GOROOT'] && process.env['GOPROXY'] && process.env['GOBIN']) {
 		return Promise.resolve();
 	}
 
@@ -410,7 +410,7 @@
 	}
 
 	return new Promise<void>((resolve, reject) => {
-		cp.execFile(goRuntimePath, ['env', 'GOPATH', 'GOROOT', 'GOPROXY'], (err, stdout, stderr) => {
+		cp.execFile(goRuntimePath, ['env', 'GOPATH', 'GOROOT', 'GOPROXY', 'GOBIN'], (err, stdout, stderr) => {
 			if (err) {
 				return reject();
 			}
@@ -424,6 +424,9 @@
 			if (!process.env['GOPROXY'] && envOutput[2] && envOutput[2].trim()) {
 				process.env['GOPROXY'] = envOutput[2].trim();
 			}
+			if (!process.env['GOBIN'] && envOutput[3] && envOutput[3].trim()) {
+				process.env['GOBIN'] = envOutput[3].trim();
+			}
 			return resolve();
 		});
 	});
diff --git a/src/goMain.ts b/src/goMain.ts
index ee62766..dc16200 100644
--- a/src/goMain.ts
+++ b/src/goMain.ts
@@ -25,7 +25,7 @@
 import { installCurrentPackage } from './goInstall';
 import {
 	installAllTools, installTools, offerToInstallTools, promptForMissingTool,
-	updateGoPathGoRootFromConfig
+	updateGoVarsFromConfig
 } from './goInstallTools';
 import { startLanguageServerWithFallback, watchLanguageServerConfiguration } from './goLanguageServer';
 import { lintCode } from './goLint';
@@ -63,7 +63,7 @@
 	setGlobalState(ctx.globalState);
 	setWorkspaceState(ctx.workspaceState);
 
-	updateGoPathGoRootFromConfig().then(async () => {
+	updateGoVarsFromConfig().then(async () => {
 		const updateToolsCmdText = 'Update tools';
 		interface GoInfo {
 			goroot: string;
@@ -384,7 +384,7 @@
 				return;
 			}
 			const updatedGoConfig = getGoConfig();
-			updateGoPathGoRootFromConfig();
+			updateGoVarsFromConfig();
 
 			// If there was a change in "toolsGopath" setting, then clear cache for go tools
 			if (getToolsGopath() !== getToolsGopath(false)) {
diff --git a/test/integration/extension.test.ts b/test/integration/extension.test.ts
index 63043d5..7b747d9 100644
--- a/test/integration/extension.test.ts
+++ b/test/integration/extension.test.ts
@@ -20,7 +20,7 @@
 	generateTestCurrentPackage
 } from '../../src/goGenerateTests';
 import { getTextEditForAddImport, listPackages } from '../../src/goImport';
-import { updateGoPathGoRootFromConfig } from '../../src/goInstallTools';
+import { updateGoVarsFromConfig } from '../../src/goInstallTools';
 import { goLint } from '../../src/goLint';
 import { documentSymbols, GoDocumentSymbolProvider, GoOutlineImportsOptions } from '../../src/goOutline';
 import { getAllPackages } from '../../src/goPackages';
@@ -56,7 +56,7 @@
 	let toolsGopath: string;
 
 	suiteSetup(async () => {
-		await updateGoPathGoRootFromConfig();
+		await updateGoVarsFromConfig();
 
 		gopath = getCurrentGoPath();
 		if (!gopath) {