0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Go言語(プログラミング)入門メモ㉗

Posted at

HTTPリクエストの送信

Webページなどでデータをやりとりする際は、HTTPという取り決めに従う必要がある。Goの標準パッケージを利用して、HTTPリクエストを送信する。

Getリクエストの送信

net/httpは、WebサーバやWebクライアントを作るためのパッケージ。
http.Get関数では、指定したURLにGETリクエストを送信できる。ここでは、「http://example.com」にアクセスし、返り値を変数respに格納する。エラーハンドリングは行わず、_でエラーは無視する。
また、Getリクエストの結果であるレスポンスボディは、クローズする必要があるので「defer resp.Body.Close()」を実行しておく。
次に「io.ReadAll(resp.Body)」で読み取った内容を変数bodyに代入する。最後に、「fmt.Println(string(body))」で表示すると、アクセスしたURLのHTMLが表示される。

package main

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

func main() {
	resp, _ := http.Get("http://example.com")
	defer resp.Body.Close()
	body, _ := io.ReadAll(resp.Body)
	fmt.Println(string(body))
}

※補足
急に出てきたresp.Bodyってなんだと思ったので調べると、
respは、HTTPステータスコード、ヘッダー、および本文を含むHTTPレスポンス全体を表すオブジェクトで、HTTPレスポンスの本文(ボディ)のみを表したのがresp.Bodyということだった。
※補足終わり

結果は以下のように表示される。
image.png

net/urlパッケージでURLの解析を行う。

URLが正しい形式か解析するには、net/urlパッケージをインポートしてurl.Parse関数を使う。url.Parse関数は、引数に渡した文字列を解析し、返り値としてURL型の構造体を返す。文字列がURLの形式でなかればエラーを返す。
「http://example.com」を解析してみる。

package main

import (
	"fmt"
	"net/url"
)

func main() {
	base, err := url.Parse("http://example.com")
	fmt.Println(base, err)
}

結果は以下のように表示される
image.png
URL部分を編集して、エラーが起こるようにしてみる。

package main

import (
	"fmt"
	"net/url"
)

func main() {
	base, err := url.Parse("http://exam ple.com") //スペースを入れる
	fmt.Println(base, err)
}

結果は以下のように表示される
image.png

クエリパラメータの追加

HTTPリクエストの際、URLの後ろに追加して渡す値のことを、クエリパラメータという。クエリパラメータによりサーバーに対して特定のリクエストを行う。
「http://example.com/test?a=1&b=2」というURLの場合、「?a=1&b=2」のように?の後ろに追加しているのがクエリパラメータ。
このクエリパラメータは、変数aに1、変数bに2をそれぞれ指定している。
ResolveReferenceメソッドを使用するとクエリパラメータを追加することができる。
まず、url.Parse関数で「http://example.com」のあとにつなげるURL「/test?a=1&b=2」を書き、変数referenceに代入する。
次に、変数baseと変数referenceから、アクセスするURLを生成する。「base.ResolveReference(reference)」として変数baseと変数referenceをつなげたURLを作成し、String()で文字列にして、変数endpointに代入する。

package main

import (
	"fmt"
	"net/url"
)

func main() {
	base, _ := url.Parse("http://example.com")
	reference, _ := url.Parse("/test?a=1&b=2")
	endpoint := base.ResolveReference(reference).String()
	fmt.Println(endpoint)

}

表示結果は以下のようになりクエリパラメータが追加されていることが分かる。
image.png

http.NewRequest関数でリクエストを作成する

http.NewRequest関数でリクエストを作成し、Getリクエストを送信する方法を実行する。
まずは、http.NewRequest関数でリクエストを作成する。引数にはHTTPメソッドとURLをそれぞれ一つ目、二つ目に指定する。三つ目の引数は、リクエストボディ(送信するデータ)を指定するが、今回はGETメソッドなのでnilを指定。(リクエストボディはPOSTなどを使用する際に指定する。)

package main

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

func main() {
	base, _ := url.Parse("http://example.com")
	reference, _ := url.Parse("/test?a=1&b=2")
	endpoint := base.ResolveReference(reference).String()
	fmt.Println(endpoint)
	req, _ := http.NewRequest("Get", endpoint, nil)
}

上記のコードで変数reqに代入したHTTPリクエストは変数endpointに代入したURL「http://example.com/test?a=1&b=2」を指定している。このクエリパラメータは、「req/URL.Query()」のようにQueryメソッドで取り出すことができる。

package main

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

func main() {
	base, _ := url.Parse("http://example.com")
	reference, _ := url.Parse("/test?a=1&b=2")
	endpoint := base.ResolveReference(reference).String()
	fmt.Println(endpoint)
	req, _ := http.NewRequest("Get", endpoint, nil)
	q := req.URL.Query()
	fmt.Println(q)
}

以下のように表示される。
image.png

Addメソッドでクエリパラメータを追加する

http.NewRequest関数でリクエストを作成する場合はAddメソッドでクエリパラメータを追加できる。
次のコードでは。「q.Add("c","3&%")」で変数qにクエリパラメータを追加している。
変数qのクエリパラメータを、変数reqのHTTPリクエストに反映するには、「req.URL.RawQueery」に値を代入する。ただしその際にq.Encode()のようにして、Encodeメソッドを使ってエンコードする必要がある。

package main

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

func main() {
	base, _ := url.Parse("http://example.com")
	reference, _ := url.Parse("/test?a=1&b=2")
	endpoint := base.ResolveReference(reference).String()
	fmt.Println(endpoint)
	req, _ := http.NewRequest("Get", endpoint, nil)
	q := req.URL.Query()
	q.Add("c", "3&%")
	fmt.Println(q)
	fmt.Println(q.Encode())
	req.URL.RawQuery = q.Encode()
}

実行結果は以下のように表示される。
image.png
マップを見ると、クエリパラメータに「c:[3&%]」が追加されていることが分かる。一方エンコードしたクエリパラメータは、「c=3%26%25」のように「&」が「%26」、「%」が「%25」にエンコードされていることが分かる。(URL表記では&は区切り文字なのでそのまま入れることはできない。%も同様)

http.ClientでHTTPリクエストを送信する

作成したHTTPリクエストを使ってGETリクエストを行うにはhttp.Clientという型でクライアントを作る必要がある。
「var client *http.Client = &http.Client{}」というクライアントを宣言し、「clinet.Do(req)」で変数reqのHTTPリクエストを実行し、実行結果を変数respに代入する。
io.ReadAllで内容を読み取ると「http://example.com」の内容が表示される。
(このページはクエリパラメータを渡してもレスポンスに変化がない)

package main

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

func main() {
	base, _ := url.Parse("http://example.com")
	reference, _ := url.Parse("/test?a=1&b=2")
	endpoint := base.ResolveReference(reference).String()
	fmt.Println(endpoint)
	req, _ := http.NewRequest("Get", endpoint, nil)
	q := req.URL.Query()
	q.Add("c", "3&%")
	fmt.Println(q)
	fmt.Println(q.Encode())
	req.URL.RawQuery = q.Encode()

	var client *http.Client = &http.Client{}
	resp, _ := client.Do(req)
	body, _ := io.ReadAll(resp.Body)
	fmt.Println(string(body))
}

結果は以下のように表示される
image.png

学習に使用した教材

・『入門】Golang基礎入門 + 各種ライブラリ + 簡単なTodoWebアプリケーション開発(Go言語)』M.A EduTech
https://www.udemy.com/course/golang-webgosql/?utm_medium=udemyads&utm_source=bene-msa&utm_campaign=responsive&utm_content=top-1&utm_term=general&msclkid=81e2f24a32cc185d275d953d60760226&couponCode=NEWYEARCAREERJP

・『シリコンバレー一流プログラマーが教える Goプロフェッショナル大全』酒井 潤 (著)
https://www.amazon.co.jp/%E3%82%B7%E3%83%AA%E3%82%B3%E3%83%B3%E3%83%90%E3%83%AC%E3%83%BC%E4%B8%80%E6%B5%81%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%83%BC%E3%81%8C%E6%95%99%E3%81%88%E3%82%8B-Go%E3%83%97%E3%83%AD%E3%83%95%E3%82%A7%E3%83%83%E3%82%B7%E3%83%A7%E3%83%8A%E3%83%AB%E5%A4%A7%E5%85%A8-%E9%85%92%E4%BA%95-%E6%BD%A4/dp/4046070897

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?