How to Set Headers in an HTTP GET Request in Go? Full Explanation with Code
\n\nHave you ever tried to send an HTTP GET request to a server, and it returned an authorization error? Or maybe the API ignored your request, even though you knew it should work? In 90% of cases, the problem lies in HTTP headers. They are like a pass to a party: without the right document, you simply won't be let in.
\n\nIn this article, we will break down how to professionally manage headers in HTTP GET requests in Go (Golang). You will learn not only the basic syntax but also the typical pitfalls that even experienced developers fall into. Let's go!
\n\nWhy are Headers Important?
\n\nImagine an HTTP request is an envelope with a letter. The envelope itself (the request body) can be empty, but the information on it (the headers) decides everything:
\n- \n
- Content-Type — data format (JSON, XML, Form) \n
- Authorization — API access key (Bearer token, Basic Auth) \n
- User-Agent — client identification (so you don't get blocked as a bot) \n
- Accept — what response format you expect \n
Without the correct headers, the server simply won't understand what you want from it.
\n\nMethod 1: The Good Old http.Get (and Why It's Not Suitable)
\n\nMany beginners in Go start with http.Get(). It's convenient for testing, but this method has a huge downside — you cannot set headers.
package main\n\nimport (\n "fmt"\n "io/ioutil"\n "net/http"\n)\n\nfunc main() {\n // You cannot add headers this way!\n resp, err := http.Get("https://api.example.com/data")\n if err != nil {\n panic(err)\n }\n defer resp.Body.Close()\n\n body, _ := ioutil.ReadAll(resp.Body)\n fmt.Println(string(body))\n}\n\n\nThis code simply sends a "bare" request. If the API requires an authorization token, you will get a 401 Unauthorized. This approach is not suitable for real projects.
Method 2: Creating Your Own Request (The Correct Way)
\n\nIn Go, for fine-tuning requests, the http.NewRequest() constructor is used. It returns an *http.Request object, with which you can do anything, including setting headers.
Here is the basic structure:
\n\npackage main\n\nimport (\n "fmt"\n "io/ioutil"\n "net/http"\n)\n\nfunc main() {\n // 1. Create a URL\n url := "https://api.github.com/users/golang"\n\n // 2. Create a new GET request\n req, err := http.NewRequest("GET", url, nil)\n if err != nil {\n panic(err)\n }\n\n // 3. Set headers\n req.Header.Set("User-Agent", "MyGoApp/1.0")\n req.Header.Set("Accept", "application/json")\n\n // 4. Send the request via an HTTP client\n client := &http.Client{}\n resp, err := client.Do(req)\n if err != nil {\n panic(err)\n }\n defer resp.Body.Close()\n\n body, _ := ioutil.ReadAll(resp.Body)\n fmt.Println(string(body))\n}\n\n\nNote: we use req.Header.Set(), not req.Header.Add(). The difference is important:
- \n
- Set — replaces the existing value (if such a header already exists) \n
- Add — adds another value to the existing one (creates a duplicate) \n
For most cases, use Set — it's safer.
Method 3: Working with Authorization (Bearer Token)
\n\nThe most common scenario is passing a JWT token. Here's how to do it correctly:
\n\npackage main\n\nimport (\n "fmt"\n "net/http"\n)\n\nfunc main() {\n token := "your_jwt_token_here"\n url := "https://api.example.com/protected"\n\n req, _ := http.NewRequest("GET", url, nil)\n\n // Set the Authorization header\n req.Heade