You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golang场景下如何正确组织代码消除HTTP请求函数重复逻辑

Golang 重复HTTP请求逻辑重构方案

两个函数的公共逻辑高度重合,核心差异只有请求参数、请求头配置、响应提取规则三点,直接抽离公共请求基函数即可消除所有重复代码,同时可以顺手修复原代码中错误处理缺失、全局变量初始化不合理的隐患。

重构思路

把所有公共逻辑(创建HTTP客户端、构造请求实例、发送请求、关闭响应体、读取响应内容)封装成内部复用函数,可变部分通过参数传入:

  • 固定公共逻辑:请求构建、发送、响应读取、资源回收全流程封装
  • 可变参数透传:请求方法、URL、自定义请求头通过参数传入
  • 差异化响应处理:由上层调用方拿到响应对象/响应体后,自行实现token提取、JSON解析等逻辑

重构后代码

package main

import (
	"fmt"
	"io"
	"net/http"
)

const (
	cloudAPIBase  = "https://cloud-platform-api.com/api"
	apiVersion    = "35.0"
	basicAuthHash = "<auth-hash>"
)

// doRequest 内部通用HTTP请求执行函数,封装所有公共逻辑
func doRequest(method, url string, headers map[string]string) (*http.Response, []byte, error) {
	client := &http.Client{}
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		return nil, nil, fmt.Errorf("build request failed: %w", err)
	}

	for k, v := range headers {
		req.Header.Add(k, v)
	}

	res, err := client.Do(req)
	if err != nil {
		return nil, nil, fmt.Errorf("send request failed: %w", err)
	}
	defer res.Body.Close()

	body, err := io.ReadAll(res.Body)
	if err != nil {
		return nil, nil, fmt.Errorf("read response body failed: %w", err)
	}

	return res, body, nil
}

// GetToken 获取云平台访问令牌
func GetToken() (string, error) {
	headers := map[string]string{
		"Accept":        fmt.Sprintf("application/*+xml;version=%s", apiVersion),
		"Authorization": "Basic " + basicAuthHash,
	}
	res, _, err := doRequest(http.MethodPost, cloudAPIBase+"/sessions", headers)
	if err != nil {
		return "", err
	}
	return res.Header.Get("x-vmware-vcloud-access-token"), nil
}

// HTTPGetter 调用云平台业务API获取JSON响应
func HTTPGetter(method, url, accessToken string) (*http.Response, []byte, error) {
	headers := map[string]string{
		"Accept":        fmt.Sprintf("application/json;version=%s", apiVersion),
		"Authorization": "Bearer " + accessToken,
	}
	return doRequest(method, url, headers)
}

关键优化说明

  • 移除全局accessToken变量:原实现在包加载阶段就同步调用getToken(),一旦token请求失败会直接导致程序启动崩溃,也无法支持token过期自动刷新的场景,改为调用方按需获取、传入token的方式更灵活可控
  • 补全错误传递:原代码仅通过fmt.Println打印错误,不向上返回错误值,会导致请求失败后后续逻辑拿到空对象运行触发空指针,现在所有错误都包装后返回给上层统一处理
  • 常量统一管理:把API版本号、服务地址、基础认证串这类固定配置抽成常量,避免硬编码散落在多个函数中增加维护成本
  • 替换废弃API:原代码使用的ioutil.ReadAll在Go 1.16版本后已迁移至io.ReadAll,重构后直接使用标准库新接口
  • 使用标准库常量:用http.MethodPost这类标准库预定义常量替代手写的HTTP方法字符串,减少笔误概率

内容的提问来源于stack exchange,提问作者Vladimir Fomin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 21:18:23