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?

簡単なAPIを作ってみたまとめ

Last updated at Posted at 2024-09-27

簡単なAPIを作ってみた

APIについて色々読んだりしてみたものの、設計ルールをがっつり盛り込んでAPIを設計するほどのアイデアが出てこなかったのでまずはAPIを作る事に慣れようの回とした。

今回はローカルホストだけどこんな感じに返ってくるAPIを作ってみた。

参考リンク

今回はこちらをメインに参考

Go公式で参考にしたページ

APIの設計ルール諸々紹介されている記事

準備

使用したのはGo言語。PythonのFlaskでも作れるらしい。
(上記に挙げていないけど)色々なAPIの作成に関する記事を見て、読みやすいなと思った事と、Go言語に触った事がないので触ってみたくてGoを使用した。

  • 開発環境:VS Code

まずは拡張機能からGoをインストール。
image.png

VS CodeでGoのフォルダとファイルを作成する。例えばこんな感じ。

この時点で適当にコード書いてデバッグするとgo.modファイルが見つからないよというエラーが発生する。(画像はgo.mod作成後。go.modがない場合にデバッグすると見つからないエラーが発生する。)
なのでVS Codeのターミナルでコマンド go mod init <好きなモジュール名(今回はapi)>を実行してファイルを作成する。
作成されたファイルの中身はこちら(一応備忘録として)。

作成

作成したコードはこちら。
Goのコードが手探り状態だったので、全然もう少し上手く書き直せそうではある。

Go
package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
)

type Holiday struct {
	MonthMessage string
	Date         string
	Holiday_Data string
}

func handleRequests() {
	http.HandleFunc("/", homePage)
	http.HandleFunc("/January", returnHolidayData_Jan)
	// 省略しているのでコメントアウト http.HandleFunc("/February", returnHolidayData_Feb)
	// 省略しているのでコメントアウト http.HandleFunc("/March", returnHolidayData_Mar)
	// 省略しているのでコメントアウト http.HandleFunc("/April", returnHolidayData_Apr)
	http.HandleFunc("/May", returnHolidayData_May)

	log.Fatal(http.ListenAndServe(":8081", nil))
}

func homePage(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Welcome to the HomePage!")
	fmt.Println("Endpoint Hit: homePage")
}

func returnHolidayData_Jan(w http.ResponseWriter, r *http.Request) {
	holiday := []Holiday{}
	arr_date := []string{"1/1", "1/8"}
	arr_name := []string{"元日", "成人の日"}

	for i := 0; i < 2; i++ {
		Msg_txt := fmt.Sprintf(" 1月の%dつ目のお休み", i+1)
		holiday = append(
			holiday,
			Holiday{MonthMessage: Msg_txt, Date: arr_date[i], Holiday_Data: arr_name[i]})
	}
	json.NewEncoder(w).Encode(holiday)
}

//2月~4月は省略

func returnHolidayData_May(w http.ResponseWriter, r *http.Request) {
	holiday := []Holiday{}
	arr_date := []string{"5/3", "5/4", "5/5"}
	arr_name := []string{"憲法記念日", "みどりの日", "こどもの日"}

	for i := 0; i < 3; i++ {
		Msg_txt := fmt.Sprintf(" 5月の%dつ目のお休み", i+1)
		holiday = append(
			holiday,
			Holiday{MonthMessage: Msg_txt, Date: arr_date[i], Holiday_Data: arr_name[i]})
	}
	json.NewEncoder(w).Encode(holiday)
}

func main() {
	handleRequests()
}

コードの詳細

基本的にはメインに参考した記事を元に作成した。
自分の中でへぇ~となったところを以下でピックアップ。

import

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
)

作るために上記4つのインポートが必要。
net/httpはAPIリクエスト、レスポンスを処理するために必要なHTTPサーバを実装するために必要なパッケージ。
encoding/jsonはJSONデータを扱うために必要なパッケージ。

JSONの中身の型

type Holiday struct {
	MonthMessage string
	Date         string
	Holiday_Data string
}

それぞれの値は文字列型に設定。
実際に返す内容は以下のようになる。

func handleRequests()とhttp.HandleFunc

func handleRequests() {
	http.HandleFunc("/", homePage)
    http.HandleFunc("/January", returnHolidayData_Jan)

ここではリクエストのURI(//January)からどの関数を呼び出すかを決めている。リクエストが来た時にどのような内容を返すのかのハンドリングはここで設定できるのだなと。もっとこうびっくりするようなコードを書くのかと勝手に想像していました何故か。

ポートの指定

log.Fatal(http.ListenAndServe(":8081", nil))

リクエストを受け付けるポート番号はこちらで指定。他の通信と競合しないように気を付ける。
実際のリクエストも、リクエストを受け付けるポートを指定している事がわかる。

呼び出される関数の中身

呼び出される関数
func returnHolidayData_May(w http.ResponseWriter, r *http.Request) {
	holiday := []Holiday{}
	arr_date := []string{"5/3", "5/4", "5/5"}
	arr_name := []string{"憲法記念日", "みどりの日", "こどもの日"}

	for i := 0; i < 3; i++ {
		Msg_txt := fmt.Sprintf(" 5月の%dつ目のお休み", i+1)
		holiday = append(
			holiday,
			Holiday{MonthMessage: Msg_txt, Date: arr_date[i], Holiday_Data: arr_name[i]})
	}
	json.NewEncoder(w).Encode(holiday)
}

呼び出される関数returnHolidayData_Mayと呼び出し元はこちら。

呼び出し元
func handleRequests() {
//省略
http.HandleFunc("/May", returnHolidayData_May)

実際のJSONの中身は呼び出される関数returnHolidayData_Mayにて作成。
上記で紹介したJSONの中身の型Holidayholidayを宣言。ややこしい。
クラスとインスタンスに似てるなとふんわり感じた。
今回は1月~5月ごとにその月の休日をレスポンスとして返す設計とした。
そのため、returnHolidayData_Mayでは、5月の休日の日付、休日の名前を配列に格納。

holiday := []Holiday{}
	arr_date := []string{"5/3", "5/4", "5/5"}
	arr_name := []string{"憲法記念日", "みどりの日", "こどもの日"}

for文は休日の数だけ回す。
数字直入れではなくて配列の長さで回した方が良いね。
JSONの中身の型Holidayのそれぞれの項目MonthMessageDateHoliday_Dataに値を入れつつ、holidayに追加して返す。

	for i := 0; i < 3; i++ {
		Msg_txt := fmt.Sprintf(" 5月の%dつ目のお休み", i+1)
		holiday = append(
			holiday,
			Holiday{MonthMessage: Msg_txt, Date: arr_date[i], Holiday_Data: arr_name[i]})
	}

諸々値を入れたholidayを最後にエンコード。

	json.NewEncoder(w).Encode(holiday)

デバッグしてレスポンスを確認

上記のコードをデバッグする。

ポップアップが表示されるので「許可」をクリック。
これでリクエスト、レスポンスを処理できる状態となる。

Postmanで/Mayのリクエストを送信すると200 OKと返ってきている事を確認できる。
image.png

ボディをJSONに変更する。

holidayの中身がレスポンスとして返ってきている事が分かる。

さいごに

Go言語の書き方に慣れてくればもう少しレスポンスの中身は綺麗に書けそうだと感じた。
それと次回はAPIの設計ルールを元に、DBの用意と、メソッド周り含めて作りたいAPIの構成を考えた上で、リベンジしたい。

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?