DevGang
Авторизоваться

Golang: Выполнение HTTP запросов

В этом посте мы рассмотрим, как можно делать HTTP-запросы, используя Go. Мы будем использовать пакет net/http, который предоставляет все необходимое для создания HTTP-запросов или создания новых http-серверов. То есть, этот пакет поможет нам сделать все что связано с «http».

Чтобы проверить, что мы сделали правильные запросы, мы будем использовать httpbin, который является хорошим сервисом для тестирования наших запросов на локальных компьютерах.

Простой HTTP-запрос

Давайте сделаем очень простой GET запрос и посмотрим, как мы можем прочитать ответ. Мы отправим простой HTTP-запрос GET на https://httpbin.org/get и прочитаем ответ. Для этого мы можем просто импортировать пакет net/http и использовать вызов функции http.Get:

package main

import (
	"net/http"
	"log"
	"io/ioutil"
)

func main() {
	MakeRequest()
}

func MakeRequest() {
	resp, err := http.Get("https://httpbin.org/get")
	if err != nil {
		log.Fatalln(err)
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatalln(err)
	}

	log.Println(string(body))
}

Мы создали отдельную функцию MakeRequest и вызвали ее из нашей основной функции. Внутри этой функции мы передали URL-адрес http.Get и получили два значения - объект ответа и переменную с ошибками, которые могли произойти во время вызова. Мы проверили, есть ли какие-либо ошибки. Если ошибок не было, ошибка будет равна nil. Обратите внимание, что эта ошибка будет сообщаться только в том случае, если возникла проблема с подключением к серверу и получением ответа. Однако, если сервер отправляет http ответ 500 (что является внутренней ошибкой сервера), вы получите этот код состояния и сообщение об ошибке на соответствующем объекте, а не в переменной err.

Затем мы читаем resp.Body, который реализует интерфейс io.ReadCloser, и мы можем использовать ioutil.ReadAll, чтобы полностью прочитать ответ. Эта функция также возвращает два значения - байтовый срез ([]byte) и err. Опять же, мы проверяем любые возможные ошибки при чтении тела ответа. Если ошибок не было, мы печатаем тело. Обратите внимание на string(body). Здесь мы преобразуем байтовый срез в строку. Если мы этого не сделаем, log.Println будет распечатывать представление байтового фрагмента, списка всех байтов в этом фрагменте, индивидуально. Но нам нужно строковое представление. Поэтому мы идем вперед и делаем преобразование.

Мы увидим, что напечатанный вывод представляет собой JSON объект в виде строки. Итак, в следующем примере мы увидим, как мы можем отправлять и читать сообщения в формате JSON.

Отправка и получение запросов в JSON

Теперь давайте отправим сообщение в формате JSON. Как мы это сделаем? Если вы пришли из Python/Node/Ruby, вы возможно уже использовали для формирования JSON объектов (словари), далее предавали их в свою любимую библиотеку и устанавливали нужный формат передачи данных. Ваша библиотека выполняла для вас преобразование объекта в JSON и отправляла запрос с требуемыми заголовками. В Go, однако, все более явно и меньше магии, что на самом деле хорошо. Вы будете знать, что делаете и как вы это делаете.

В Go мы сначала преобразуем нашу структуру данных в байтовый срез, содержащий JSON-представление данных. Затем мы передаем его запросу с соответствующим типом контента. Давайте посмотрим на пример кода:

func MakeRequest() {

	message := map[string]interface{}{
		"hello": "world",
		"life":  42,
		"embedded": map[string]string{
			"yes": "of course!",
		},
	}

	bytesRepresentation, err := json.Marshal(message)
	if err != nil {
		log.Fatalln(err)
	}

	resp, err := http.Post("https://httpbin.org/post", "application/json", bytes.NewBuffer(bytesRepresentation))
	if err != nil {
		log.Fatalln(err)
	}

	var result map[string]interface{}

	json.NewDecoder(resp.Body).Decode(&result)

	log.Println(result)
	log.Println(result["data"])
}

Сначала мы создали message, переменная, которая представляет собой карту, содержащую string, int и другую встроенную карту. Затем мы вызвали функцию json.Marshal чтобы получить массив []byte из нашей структуры. Далее мы также делаем проверку на ошибки, которые могли возникнуть во время преобразования структуры. Затем мы делаем запрос POST, используя функцию http.Post. Мы передаем url, наш тип контента (application/json), а затем мы создаем и передаем новый объект bytes.Buffer из нашей переменной bytesRepresentation. Зачем нам здесь создавать буфер? Функция http.Post ожидает реализации io.Reader. Поэтому мы могли бы даже прочитать эту часть с диска или сети. В нашем случае мы можем просто создать буфер байтов, который реализует интерфейс io.Reader. Мы отправляем запрос и проверяем наличие ошибок.

Затем мы объявляем другую переменную result (которая также является типом map) для хранения результатов, возвращаемых из запроса. Сначала мы могли прочитать полное тело (как и в предыдущем примере), а затем сделать json.Unmarshal на нем. Однако, поскольку resp.Body возвращает объект io.Reader, мы можем просто передать его json.NewDecoder, а затем вызвать функцию Decode на нем. Помните, мы должны передать указатель на наш объект map, поэтому мы передали переменную как &result вместо result. Функция Decode также возвращает вторым параметром ошибку. Но мы предполагали, что это не имеет значения и не проверяем ее. Мы зарегистрировали result и result["data"]. Служба httpbin отправляет различную информацию о запросе в качестве ответа.

#Golang
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу