Как избежать повторения кода в моем случае в Go

Есть практически две одинаковые фнкции, которые делают примерно одно и тоже. Как правильно было бы организовать код, чтобы избежать повторения в данном случае? Функция httpGetter() обращается к API облачной платформы и получает ответ в виде JSON, который я потом парсю и на его основе из темплейта формирую терраформ манифест. Функция getToken() делает почти тоже самое, только получает токен, который потом используется в функции httpGetter().

var accessToken = getToken()


func httpGetter(method, url string) (*http.Response, []byte) {
    client := &http.Client{}
    req, err := http.NewRequest(method, url, nil)
    if err != nil {
        fmt.Println(err)
    }
    req.Header.Add("Accept", "application/json;version=35.0")
    req.Header.Add("Authorization", "Bearer "+accessToken)
    res, err := client.Do(req)
    if err != nil {
        fmt.Println(err)
    }
    defer res.Body.Close()
    body, err := ioutil.ReadAll(res.Body)
    if err != nil {
        fmt.Println(err)
    }
    return res, body
}

func getToken() string {
    url := "https://cloud-platform-api.com/api/sessions"
    method := "POST"
    client := &http.Client{}
    req, err := http.NewRequest(method, url, nil)
    if err != nil {
        fmt.Println(err)
    }
    req.Header.Add("Accept", "application/*+xml;version=35.0")
    req.Header.Add("Authorization", "Basic <auth-hash>")
    res, err := client.Do(req)
    if err != nil {
        fmt.Println(err)
    }
    defer res.Body.Close()
    if err != nil {
        fmt.Println(err)
    }
    accessToken := res.Header.Get("x-vmware-vcloud-access-token")
    return accessToken
}

Ответы (1 шт):

Автор решения: aksioto

Можно вынести отправку запросов со всеми проверками в отдельный метод.

func makeRequest(method, url string, headers http.Header) (*http.Response, []byte) {
    client := &http.Client{}
    req, err := http.NewRequest(method, url, nil)
    if err != nil {
        fmt.Println(err)
    }
    req.Header = headers

    res, err := client.Do(req)
    if err != nil {
        fmt.Println(err)
    }
    defer res.Body.Close()
    body, err := ioutil.ReadAll(res.Body)
    if err != nil {
        fmt.Println(err)
    }

    return res, body
}

func httpGetter(method, url string) (*http.Response, []byte) {
    headers := http.Header{
        "Accept":        []string{"application/json;version=35.0"},
        "Authorization": []string{fmt.Sprintf("Bearer %s", accessToken)},
    }
    
    return makeRequest(method, url, headers)
}

func getToken() string {
    headers := http.Header{
        "Accept":        []string{"application/json;version=35.0"},
        "Authorization": []string{fmt.Sprintf("Basic %s", authHash)},
    }
    res, _ := makeRequest("POST", "https://cloud-platform-api.com/api/sessions", headers)
    accessToken := res.Header.Get("x-vmware-vcloud-access-token")

    return accessToken
}
→ Ссылка