基于VSCode打造跨平台Golang开发调试环境-附带源码

36 阅读10分钟

一、前言

开发者开发Golang项目时常用开发编辑器与调试工具,如VIM、Jetbrain Goland和VS Code。

VIM编辑器: 极客的炫技军刀,强大的VIM插件使其可以支持几乎所有的编程语言,优异高效的管理文件技术及纯终端的页面,激发开发者像“打怪兽升级”一样,刺激而充满乐趣。唯一缺点是入门门槛高,需要记住相关操作指令并融化为肌肉记忆,还有配合插件及插件配置项,增加初学者的学习成本。

Jetbrains Goland: 不得不说是一款优秀的Golang IDE平台,可以轻松设置断点调试、代码跳转、语法高亮、查看函数引用、设置构建参数和自定义属于个人风格的主题等配置。它的缺点是商业版需要付费,但有绿色版(笔者不推荐此侵权行为)。

VSCODE: 微软推出的一款适配所有类型语言的IDE高效开发平台,传说为原来Eclipse核心成员领衔打造。极其丰富的插件开发市场和基于LSP语言服务协议实现智能编码使得开源的VSCODE编辑器迅速获得开发者青睐。当前,由AI大模型赋能的IDE平台也是基于开源的VSCODE项目内置AI Agent,不得不说,VSCODE IDE正在成为一个平替VIM终端编程平台满足极客需求的强大工具。

本文旨在带领初学者开启一场从0到1的基于VSCODE平台搭建一套Golang开发环境之旅,包括Golang安装、VSCode安装、插件安装、扩展工具安装、运行和调试配置和从编码-构建-启动-验证全生命周期任务管理Golang项目。以代码片段和配置导航为主,文字描述为辅,追求简洁易懂且方便读者亲手实践验证。本文验证环境为Window 10,而Mac OS或是Ubuntu之类的Linux系统笔者也验证过,插件和工具配置类同,不作赘述。

源码下载地址在文末,读者可以直接下载并启动调试和一键式测试-构建-验证。

还有一些非主流IDE工具,笔者未作研究,不予评论。

二、Golang安装

2.1 下载

国内网站

这里选择源码包而非安装包,如go1.25.0.windows-amd64.zip

2.2 安装

  1. GOROOT 解压下载的压缩包到GOROOT目录

goroot.png 2) GOPATH 工作区设置,创建三个目录src、bin和pkg。

src: 存放golang项目

bin: 存放golang插件所依赖的工具或是由go install安装的二进制程序

pkg: 存放go mod tidy下载的第三方依赖库

gopath.png

2.3 设置

2.3.1 系统环境变量

env.png

set AR=ar
set CC=gcc
set CGO_CFLAGS=-O2 -g
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-O2 -g
set CGO_ENABLED=0
set CGO_FFLAGS=-O2 -g
set CGO_LDFLAGS=-O2 -g
set CXX=g++
set GCCGO=gccgo
set GO111MODULE=
set GOAMD64=v1
set GOARCH=amd64
set GOAUTH=netrc
set GOBIN=
set GOCACHE=C:\Users\Administrator\AppData\Local\go-build
set GOCACHEPROG=
set GODEBUG=
set GOENV=C:\Users\Administrator\AppData\Roaming\go\env
set GOEXE=.exe
set GOEXPERIMENT=
set GOFIPS140=off
set GOFLAGS=
set GOGCCFLAGS=-m64 -fno-caret-diagnostics -Qunused-arguments -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=C:\Users\Administrator\AppData\Local\Temp\go-build1012173332=/tmp/go-build -gno-record-gcc-switches
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMOD=NUL
set GOMODCACHE=G:\go-workspace\pkg\mod
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=G:\go-workspace
set GOPRIVATE=
set GOPROXY=https://goproxy.cn,direct
set GOROOT=G:\go
set GOSUMDB=sum.golang.org
set GOTELEMETRY=on
set GOTELEMETRYDIR=C:\Users\Administrator\AppData\Roaming\go\telemetry
set GOTMPDIR=
set GOTOOLCHAIN=auto
set GOTOOLDIR=G:\go\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.24.2
set GOWORK=
set PKG_CONFIG=pkg-config

2.3.2 依赖包代理

go env -w GOPROXY=https://goproxy.cn,direct

2.4 代码片段

2.4.1 服务端

package main

import (
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
)

type Book struct {
	ID     string  `json:"id"`
	Title  string  `json:"title"`
	Author string  `json:"author"`
	Price  float64 `json:"price"`
}

var bookDB = map[string]Book{
	"1": {ID: "1", Title: "《Go语言实战》", Author: "William Kennedy", Price: 89.0},
	"2": {ID: "2", Title: "《Gin框架入门与实战》", Author: "张三", Price: 59.0},
	"3": {ID: "3", Title: "《REST API 设计指南》", Author: "李四", Price: 69.0},
}

func main() {
	r := gin.Default()

	v1 := r.Group("/v1")
	{
		v1.GET("/books/:id", getBookByID)
	}

	err := r.Run(":8088")
	if err != nil {
		panic("Lauch http server failed: " + err.Error())
	}
}

func getBookByID(c *gin.Context) {
	bookID := c.Param("id")

	if bookID == "1" {
		// Mock handle delay
		time.Sleep(10 * time.Second)
	}

	book, exists := bookDB[bookID]
	if !exists {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    404,
			"message": "Book not found",
			"data":    nil,
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "Hit success",
		"data":    book,
	})
}

2.4.2 服务端测试

package main

import (
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"testing"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/assert"
)

// go test -v -coverprofile=coverage.out && go tool cover -html=coverage.out
func TestMain(m *testing.M) {
	gin.SetMode(gin.TestMode) 
	m.Run()
}

// /opt/go/bin/go test -test.fullpath=true -timeout 30s -run ^TestGetBookByID$ gitlab.lionaitech.com/golang-vscode/server
// go test -timeout 30s -run ^TestGetBookByID$ ./server -v
func TestGetBookByID(t *testing.T) {
	r := gin.Default()
	v1 := r.Group("/v1")
	{
		v1.GET("/books/:id", getBookByID)
	}

	testCases := []struct {
		name           string        
		bookID         string        
		expectedStatus int         
		expectedCode   int      
		expectedTitle  string        
		expectedDelay  time.Duration
	}{
		{
			name:           "获取存在的图书(ID=1,带延时)",
			bookID:         "1",
			expectedStatus: http.StatusOK,
			expectedCode:   200,
			expectedTitle:  "《Go语言实战》",
			expectedDelay:  10 * time.Second,
		},
		{
			name:           "获取存在的图书(ID=2,无延时)",
			bookID:         "2",
			expectedStatus: http.StatusOK,
			expectedCode:   200,
			expectedTitle:  "《Gin框架入门与实战》",
			expectedDelay:  0,
		},
		{
			name:           "获取不存在的图书(ID=4)",
			bookID:         "4",
			expectedStatus: http.StatusNotFound,
			expectedCode:   404,
			expectedTitle:  "",
			expectedDelay:  0,
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			req, _ := http.NewRequest("GET", "/v1/books/"+tc.bookID, nil)
			startTime := time.Now()
			w := httptest.NewRecorder()
			
			r.ServeHTTP(w, req)
		
			elapsed := time.Since(startTime)

			assert.Equal(t, tc.expectedStatus, w.Code)
			
			var response map[string]interface{}
			// err := gin.UnmarshalJSON(w.Body.Bytes(), &response)
			err := json.Unmarshal(w.Body.Bytes(), &response)
			assert.NoError(t, err, "解析响应 JSON 失败")

			assert.Equal(t, float64(tc.expectedCode), response["code"])
			if tc.expectedTitle != "" {
				data := response["data"].(map[string]interface{})
				assert.Equal(t, tc.expectedTitle, data["title"])
				assert.Equal(t, tc.bookID, data["id"])
			} else {
				assert.Nil(t, response["data"])
				assert.Equal(t, "Book not found", response["message"])
			}

			if tc.expectedDelay > 0 {
				assert.GreaterOrEqual(t, elapsed, tc.expectedDelay, "ID=1 的请求延时不足10秒")
			} else {
				assert.Less(t, elapsed, 1*time.Second, "非ID=1的请求不应有长延时")
			}
		})
	}
}

server-unit-test.png

2.4.3 客户端

package main

import (
	"context"
	"fmt"
	"net/http"
	"sync"
        "context"
	"encoding/json"
	"io"
	"time"
)

type Response struct {
	Code    int         `json:"code"`
	Message string      `json:"message"`
	Data    interface{} `json:"data"`
}

func doRequest(ctx context.Context, reqURL string, method string, body io.Reader, ret interface{}) error {
	req, err := http.NewRequestWithContext(ctx, method, reqURL, body)
	if err != nil {
		return err
	}

	client := &http.Client{Timeout: 5 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if err := json.NewDecoder(resp.Body).Decode(ret); err != nil {
		return err
	}

	return nil
}


func main() {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	var wg sync.WaitGroup
	wg.Add(2)

	urls := []string{
		"http://localhost:8088/v1/books/1",
		"http://localhost:8088/v1/books/2",
	}

	for _, url := range urls {
		go func(reqURL string) {
			defer wg.Done()
			defer func() {
				cancel()
				fmt.Printf("reqURL %s has been canceled.\n", reqURL)
			}()

			var resp Response
			if err := doRequest(ctx, reqURL, http.MethodGet, nil, &resp); err != nil {
				return
			}

			fmt.Printf("%s has received reponse successfully\n", reqURL)
			fmt.Printf("Response: %+v\n", resp)
		}(url)
	}

	wg.Wait()
	fmt.Println("Any request-response has been done.")
}

2.4.4 客户端测试

package main

import (
	"context"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"testing"
	"time"
)

type TestResponse struct {
	Message string `json:"message"`
	Value   int    `json:"value"`
}

func TestDoRequest(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		response := TestResponse{Message: "success", Value: 42}
		json.NewEncoder(w).Encode(response)
	}))
	defer server.Close()

	t.Run("Normal request with valid response", func(t *testing.T) {
		var result TestResponse
		err := doRequest(context.Background(), server.URL, "GET", nil, &result)

		if err != nil {
			t.Errorf("Expected no error, got %v", err)
		}

		if result.Message != "success" {
			t.Errorf("Expected message 'success', got '%s'", result.Message)
		}

		if result.Value != 42 {
			t.Errorf("Expected value 42, got %d", result.Value)
		}

		// Only for debug.
		t.Fatalf("Test passed")
	})
}

// TestDoRequestWithTimeout test timeout function.
func TestDoRequestWithTimeout(t *testing.T) {
	slowServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		time.Sleep(100 * time.Millisecond)
		w.Header().Set("Content-Type", "application/json")
		response := TestResponse{Message: "slow", Value: 100}
		json.NewEncoder(w).Encode(response)
	}))
	defer slowServer.Close()

	// 使用带超时的上下文
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond)
	defer cancel()

	var result TestResponse
	err := doRequest(ctx, slowServer.URL, "GET", nil, &result)

	if err == nil {
		t.Error("Expected a timeout error, but got none")
	}
}

client-unit-test.png

2.4.5 运行

go mod init

go mod tidy

1) 单元测试
1.1) 服务端测试
go test -timeout 30s -run ^TestGetBookByID$ ./server -v

1.2) 客户端测试
go.exe test -test.fullpath=true -timeout 30s -run ^TestDoRequest$ github.com/sword-fisher-fly/vscode-golang/client -v

2) 运行
2.1) 服务端
go run server/server.go

2.2) 客户端
go run client/client.go

启动服务端 run-server.png 运行客户端

run-client.png

三、Vscode安装

说明

以下.vscode目录可以手动创建,相关配置文件也可以手动创建并添加配置内容。当然,还可以通过快捷键或是点击相关导航按钮功能项后,由vscode自动创建相关文件后添加配置内容。

3.1 页面布局

3.1.1 菜单 & 面板

layouts.png

3.1.2 命令面板

ctrl+shift+p

command-palette.png

3.2 插件安装

3.2.1 插件市场

选择Go Team At Google

go-ext.png

3.2.2 智能工具

go-tools.png

LSP服务器

tasklist | findstr gopls
gopls.exe                    14764 Console                    1    843,988 K
gopls.exe                    10528 Console                    1     26,408 K

3.3 自定义配置

配置用户开发环境,特别注意go.alternateTools配置项需要根据自己的安装环境设置,否则,执行任务会报找不到go相关工具错误。

{
  "go.useLanguageServer": true,
  "editor.formatOnSave": true,
  "go.formatTool": "goimports",
  "go.alternateTools": {
      "go": "G:\\go\\bin\\go.exe"
  },
  // "go.alternateTools": {
  //   "go": "/opt/go/bin/go"
  // },
  "gopls": {
    "usePlaceholders": true,
    "completeUnimported": true
  },
  "debug.console.fontSize": 14,
  "debug.console.lineHeight": 15,
  "debug.allowBreakpointsEverywhere": true,
  "debug.showInStatusBar": "always",
  "debug.showVariableTypes": true
}

3.4 代码目录

project-folder.png

3.5 调试设置

3.5.1 单元测试

client-unit-select-test.png


{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch client test function",
            "type": "go",
            "request": "launch",
            "mode": "test",
            "program": "${workspaceFolder}/client",
            "args": [
                "-test.run",
                "TestDoRequest.*"
            ],
            "dlvFlags": [
                "--listen=:2345",
                "--check-go-version=false"
            ]
        },
        {
            "name": "Launch server test function",
            "type": "go",
            "request": "launch",
            "mode": "test",
            "program": "${workspaceFolder}/server",
            "args": [
                "-test.run",
                "TestGetBookByID"
            ],
            "dlvFlags": [
                "--listen=:2345",
                "--check-go-version=false"
            ]
        },
        {
            "name": "Launch client test: Select DoRequest Function",
            "type": "go",
            "request": "launch",
            "mode": "test",
            "program": "${workspaceFolder}/client",
            "args": [
                "-test.run",
                "${input:selectTestFunction}" // 引用自定义输入变量
            ],
            "dlvFlags": [
                "--listen=:2345",
                "--check-go-version=false"
            ]
        },
        {
            "name": "Launch Chrome",
            "request": "launch",
            "type": "chrome",
            "url": "http://localhost:8080/v1/books/3",
            "webRoot": "${workspaceFolder}"
        },
        {
            "name": "Launch server",
            "type": "go",
            "request": "launch",
            "mode": "debug",
            "program": "${workspaceFolder}/server/server.go",
            "dlvFlags": [
                "--listen=:2345",
                "--check-go-version=false"
            ]
        },
        {
            "name": "Launch client",
            "type": "go",
            "request": "launch",
            "mode": "debug",
            "program": "${workspaceFolder}/client",
            "dlvFlags": [
                "--listen=:2347",
                "--check-go-version=false"
            ]
        },
    ],
    "inputs": [
        {
            "id": "selectTestFunction",
            "type": "pickString",
            "description": "Select DoRequest test function to run",
            "options": [
                "TestDoRequest",
                "TestDoRequestWithTimeout"
            ],
            "default": "TestDoRequest"
        }
    ]
}

3.5.2 断点设置

server.go设置路由处理函数,设置观察变量值

set-breakpoints-and-launch-server.png

3.5.3 完整配置

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch client test function",
            "type": "go",
            "request": "launch",
            "mode": "test",
            "program": "${workspaceFolder}/client",
            "args": [
                "-test.run",
                "TestDoRequest.*"
            ],
            "dlvFlags": [
                "--listen=:2345",
                "--check-go-version=false"
            ]
        },
        {
            "name": "Launch server test function",
            "type": "go",
            "request": "launch",
            "mode": "test",
            "program": "${workspaceFolder}/server",
            "args": [
                "-test.run",
                "TestGetBookByID"
            ],
            "dlvFlags": [
                "--listen=:2345",
                "--check-go-version=false"
            ]
        },
        {
            "name": "Launch client test: Select DoRequest Function",
            "type": "go",
            "request": "launch",
            "mode": "test",
            "program": "${workspaceFolder}/client",
            "args": [
                "-test.run",
                "${input:selectTestFunction}" // 引用自定义输入变量
            ],
            "dlvFlags": [
                "--listen=:2345",
                "--check-go-version=false"
            ]
        },
        {
            "name": "Launch Chrome",
            "request": "launch",
            "type": "chrome",
            "url": "http://localhost:8088/v1/books/3",
            "webRoot": "${workspaceFolder}"
        },
        {
            "name": "Launch server",
            "type": "go",
            "request": "launch",
            "mode": "debug",
            "program": "${workspaceFolder}/server/server.go",
            "dlvFlags": [
                "--listen=:2345",
                "--check-go-version=false"
            ]
        },
        {
            "name": "Launch client",
            "type": "go",
            "request": "launch",
            "mode": "debug",
            "program": "${workspaceFolder}/client",
            "dlvFlags": [
                "--listen=:2347",
                "--check-go-version=false"
            ]
        },
    ],
    "inputs": [
        {
            "id": "selectTestFunction",
            "type": "pickString",
            "description": "Select DoRequest test function to run",
            "options": [
                "TestDoRequest",
                "TestDoRequestWithTimeout"
            ],
            "default": "TestDoRequest"
        }
    ]
}

3.6 任务设置

3.6.1 文件清理

{
            "label": "clean-server",
            "type": "shell",
            "windows": {
                "command": "cmd",
                "args": [
                    "/c",
                    "if exist \"${workspaceFolder}\\server.exe\" del \"${workspaceFolder}\\server.exe\""
                ]
            },
            "linux": {
                "command": "bash",
                "args": [
                    "-c",
                    "if [ -f \"${workspaceFolder}/server.linux\" ]; then rm -f \"${workspaceFolder}/server.linux\"; fi"
                ]
            },
            "osx": {
                "command": "zsh",
                "args": [
                    "-c",
                    "if [ -f \"${workspaceFolder}/server.osx\" ]; then rm -f \"${workspaceFolder}/server.osx\"; fi"
                ]
            },
            "presentation": {
                "reveal": "silent",
                "panel": "new"
            },
            "problemMatcher": [],
            "detail": "Clean server binary file"
}

3.6.2 单元测试

{
            "label": "test-server",
            "type": "shell",
            // 1)
            // "windows": {
            //     "command": "cmd",
            //     "args": [
            //         "/c",
            //         "go test -v -timeout 30s -cover \"${workspaceFolder}\\server\" -coverprofile=\"${workspaceFolder}\\coverage.out\" && go tool cover -html=\"${workspaceFolder}\\coverage.out\" -o \"${workspaceFolder}\\coverage.html\""
            //     ]
            // },
            // 2)
            "windows": {
                "command": "go",
                "args": [
                    "test",
                    "-v",
                    "-timeout",
                    "30s",
                    "-cover",
                    "\"${workspaceFolder}\\server\"",
                    "-coverprofile",
                    "\"${workspaceFolder}\\coverage.out\""
                ],
            },
            "linux": {
                "command": "bash",
                "args": [
                    "-c",
                    "go test -v -timeout 30s -cover \"${workspaceFolder}/server\" -coverprofile=coverage.out && go tool cover -html=coverage.out -o coverage.html"
                ]
            },
            "osx": {
                "command": "zsh",
                "args": [
                    "-c",
                    "go test -v -timeout 30s -cover \"${workspaceFolder}/server\""
                ]
            },
            "presentation": {
                "reveal": "always",
                "panel": "new",
                "focus": false,
                "echo": true
            },
            "problemMatcher": [
                {
                    "owner": "go",
                    "fileLocation": "absolute",
                    "pattern": {
                        "regexp": "^(.*?):(\\d+):(\\d+):\\s+(error|warning):\\s+(.*)$",
                        "file": 1,
                        "line": 2,
                        "column": 3,
                        "severity": 4,
                        "message": 5
                    },
                    "background": {
                        "activeOnStart": true,
                        "beginsPattern": "^=== RUN   .*$",
                        "endsPattern": "^(PASS|FAIL|SKIP)\\s+.*$"
                    }
                }
            ],
            "detail": "Run Go unit tests (Windows/Linux/macOS) - with coverage and 30s timeout"
}

3.6.3 构建

{
            "label": "build-server",
            "type": "shell",
            "command": "",
            "args": [],
            "windows": {
                "command": "go",
                "args": [
                    "build",
                    "-v",
                    "-o",
                    "\"${workspaceFolder}\\server.exe\"",
                    "./server/..."
                ],
            },
            "linux": {
                "command": "go",
                "args": [
                    "build",
                    "-v",
                    "-o",
                    "${workspaceFolder}/server.linux",
                    "./server/..."
                ],
            },
            "osx": {
                "command": "go",
                "args": [
                    "build",
                    "-v",
                    "-o",
                    "${workspaceFolder}/server.osx",
                    "./server/..."
                ],
            },
            "group": "build",
            "presentation": {
                "reveal": "always",
                "panel": "new"
            },
            "problemMatcher": "$go",
            "detail": "Cross platform build, build server package"
}

3.6.4 启动

 {
            "label": "run-server",
            "type": "shell",
            "windows": {
                "command": "cmd",
                "args": [
                    "/c",
                    "start \"Server\" \"${workspaceFolder}\\server.exe\""
                ]
            },
            "linux": {
                "command": "bash",
                "args": [
                    "-c",
                    "chmod +x \"${workspaceFolder}/server.linux\" && nohup \"${workspaceFolder}/server.linux\" &"
                ]
            },
            "osx": {
                "command": "zsh",
                "args": [
                    "-c",
                    "chmod +x \"${workspaceFolder}/server.osx\" && nohup \"${workspaceFolder}/server.osx\" &"
                ]
            },
            "presentation": {
                "reveal": "silent",
                "panel": "new"
            },
            "problemMatcher": [],
            "detail": "Launch server in backend"
}

3.6.5 客户端验证

前提

安装gitbash客户端,携带安装curl工具。

{
            "label": "verify-server",
            "type": "shell",
            "windows": {
                "command": "cmd",
                "args": [
                    "/c",
                    "curl -v http://127.0.0.1:8088/v1/books/2"
                ]
            },
            "linux": {
                "command": "bash",
                "args": [
                    "-c",
                    "curl -v http://127.0.0.1:8088/v1/books/2"
                ]
            },
            "osx": {
                "command": "zsh",
                "args": [
                    "-c",
                    "curl -v http://127.0.0.1:8088/v1/books/2"
                ]
            },
            "presentation": {
                "reveal": "always",
                "panel": "new"
            },
            "problemMatcher": [],
            "detail": "Using curl to verify server"
}

3.6.6 工作流

基于上述任务编排依赖工作流,名称为clean-test-build-run-verify-server,通过dependsOn选项设置服务依赖关系及顺序,可以一键选择该任务触发所有任务按顺序运行。

1)设置终端为Powershell

terminal-setting.png

2)执行工作流 Terminal->Run Task-> Select <task>

run-workflow-task.png

workflow-output.png

{
            "label": "clean-test-build-run-verify-server",
            "type": "shell",
            "dependsOn": [
                "clear-server",
                "test-server",
                "build-server",
                "run-server",
                "verify-server"
            ],
            "dependsOrder": "sequence",
            "presentation": {
                "reveal": "always",
                "panel": "new"
            },
            "problemMatcher": [],
            "detail": "Pipeline: clean, test, build, run and verify"
}

3.6.7 完整配置

将上述所有任务配置整合为一个任务配置文件,通过Terminal->Run Task可以选择指定的任务来运行。 TODO:添加完整工作流执行效果图

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "clean-server",
            "type": "shell",
            "windows": {
                "command": "cmd",
                "args": [
                    "/c",
                    "if exist \"${workspaceFolder}\\server.exe\" del \"${workspaceFolder}\\server.exe\""
                ]
            },
            "linux": {
                "command": "bash",
                "args": [
                    "-c",
                    "if [ -f \"${workspaceFolder}/server.linux\" ]; then rm -f \"${workspaceFolder}/server.linux\"; fi"
                ]
            },
            "osx": {
                "command": "zsh",
                "args": [
                    "-c",
                    "if [ -f \"${workspaceFolder}/server.osx\" ]; then rm -f \"${workspaceFolder}/server.osx\"; fi"
                ]
            },
            "presentation": {
                "reveal": "silent",
                "panel": "new"
            },
            "problemMatcher": [],
            "detail": "Clean server binary file"
        },
        {
            "label": "test-server",
            "type": "shell",
            // 1)
            // "windows": {
            //     "command": "cmd",
            //     "args": [
            //         "/c",
            //         "go test -v -timeout 30s -cover \"${workspaceFolder}\\server\" -coverprofile=\"${workspaceFolder}\\coverage.out\" && go tool cover -html=\"${workspaceFolder}\\coverage.out\" -o \"${workspaceFolder}\\coverage.html\""
            //     ]
            // },
            // 2)
            "windows": {
                "command": "go",
                "args": [
                    "test",
                    "-v",
                    "-timeout",
                    "30s",
                    "-cover",
                    "\"${workspaceFolder}\\server\"",
                    "-coverprofile",
                    "\"${workspaceFolder}\\coverage.out\""
                ],
            },
            "linux": {
                "command": "bash",
                "args": [
                    "-c",
                    "go test -v -timeout 30s -cover \"${workspaceFolder}/server\" -coverprofile=coverage.out && go tool cover -html=coverage.out -o coverage.html"
                ]
            },
            "osx": {
                "command": "zsh",
                "args": [
                    "-c",
                    "go test -v -timeout 30s -cover \"${workspaceFolder}/server\""
                ]
            },
            "presentation": {
                "reveal": "always",
                "panel": "new",
                "focus": false,
                "echo": true
            },
            "problemMatcher": [
                {
                    "owner": "go",
                    "fileLocation": "absolute",
                    "pattern": {
                        "regexp": "^(.*?):(\\d+):(\\d+):\\s+(error|warning):\\s+(.*)$",
                        "file": 1,
                        "line": 2,
                        "column": 3,
                        "severity": 4,
                        "message": 5
                    },
                    "background": {
                        "activeOnStart": true,
                        "beginsPattern": "^=== RUN   .*$",
                        "endsPattern": "^(PASS|FAIL|SKIP)\\s+.*$"
                    }
                }
            ],
            "detail": "Run Go unit tests (Windows/Linux/macOS) - with coverage and 30s timeout"
        },
        {
            "label": "build-server",
            "type": "shell",
            "command": "",
            "args": [],
            "windows": {
                "command": "go",
                "args": [
                    "build",
                    "-v",
                    "-o",
                    "\"${workspaceFolder}\\server.exe\"",
                    "./server/..."
                ],
            },
            "linux": {
                "command": "go",
                "args": [
                    "build",
                    "-v",
                    "-o",
                    "${workspaceFolder}/server.linux",
                    "./server/..."
                ],
            },
            "osx": {
                "command": "go",
                "args": [
                    "build",
                    "-v",
                    "-o",
                    "${workspaceFolder}/server.osx",
                    "./server/..."
                ],
            },
            "group": "build",
            "presentation": {
                "reveal": "always",
                "panel": "new"
            },
            "problemMatcher": "$go",
            "detail": "Cross platform build, build server package"
        },
        {
            "label": "run-server",
            "type": "shell",
            "windows": {
                "command": "cmd",
                "args": [
                    "/c",
                    "start \"Server\" \"${workspaceFolder}\\server.exe\""
                ]
            },
            "linux": {
                "command": "bash",
                "args": [
                    "-c",
                    "chmod +x \"${workspaceFolder}/server.linux\" && nohup \"${workspaceFolder}/server.linux\" &"
                ]
            },
            "osx": {
                "command": "zsh",
                "args": [
                    "-c",
                    "chmod +x \"${workspaceFolder}/server.osx\" && nohup \"${workspaceFolder}/server.osx\" &"
                ]
            },
            "presentation": {
                "reveal": "silent",
                "panel": "new"
            },
            "problemMatcher": [],
            "detail": "Launch server in backend"
        },
        {
            "label": "verify-server",
            "type": "shell",
            "windows": {
                "command": "cmd",
                "args": [
                    "/c",
                    "curl -v http://127.0.0.1:8088/v1/books/2"
                ]
            },
            "linux": {
                "command": "bash",
                "args": [
                    "-c",
                    "curl -v http://127.0.0.1:8088/v1/books/2"
                ]
            },
            "osx": {
                "command": "zsh",
                "args": [
                    "-c",
                    "curl -v http://127.0.0.1:8088/v1/books/2"
                ]
            },
            "presentation": {
                "reveal": "always",
                "panel": "new"
            },
            "problemMatcher": [],
            "detail": "Using curl to verify server"
        },
        {
            "label": "clean-test-build-run-verify-server",
            "type": "shell",
            "dependsOn": [
                "clear-server",
                "test-server",
                "build-server",
                "run-server",
                "verify-server"
            ],
            "dependsOrder": "sequence",
            "presentation": {
                "reveal": "always",
                "panel": "new"
            },
            "problemMatcher": [],
            "detail": "Pipeline: clean, test, build, run and verify"
        }
    ]
}

四、总结

上文简要描述VSCODE IDE平台下Golang开发环境的搭建和基于简单Web后端服务开发、调试及以任务编排方式实现全流程验证。本文所述内容都经笔者亲自实战并反复验证,但可能因个人开发环境差异存在细微差别,如配置中的文件位置设置或golang版本等不一样,读者可以基于错误提示进行调整适配。
希望本文对朋友们进入Golang编程世界有所帮助,如有疑问,欢迎在评论区讨论。

源码下载