GoとpostgreSQLで簡単なAPIサーバを実装する
概要
Go言語の文法を一通り学習し終えたため、アプリ開発に挑戦しました。今回は、GoのプログラムとpostgreSQLで、簡単なAPIを実装しました。処理の流れとしては、以下のようになります。
サンプルデータ
postgreSQLには、簡単に学生情報データ(student_name, email, tel)を作成しています。そして、Goの方には全学生の情報を取得するプログラムと、学生の名前を指定して情報を取得するプログラムの2つを用意しています。
実装
"net/http"パッケージを使用して、APIサーバーを実装しています。ただ、このパッケージだけだと"/users/ユーザー名"のようなユーザー指定のリクエストに対してうまく処理できないことが分かりました。そこで、"github.com/gorilla/mux"パッケージを使用し、リクエストパスを柔軟に処理できるようにしました。
package main import ( "database/sql" "encoding/json" "fmt" "log" "net/http" "github.com/gorilla/mux" _ "github.com/lib/pq" ) // 学生情報 type Student struct { Name string `json:"name"` Email string `json:"email"` Tel string `json:"tel"` } // エラー情報 type ErrorInfo struct { Message string `json:"error_message"` } // 学生情報を全取得 func AllStudentInfo(w http.ResponseWriter, r *http.Request) { db, err := sql.Open("postgres", "host=db port=5432 user=postgres password=postgres dbname=postgresdb sslmode=disable") // クエリの作成・実行 rows, err := db.Query("SELECT * FROM student") if err != nil { log.Fatal(err) } defer rows.Close() // 実行結果をStudent型に変換 students := []Student{} for rows.Next() { var studentname string var email string var tel string if err := rows.Scan(&studentname, &email, &tel); err != nil { log.Fatal(err) } tmpstudent := Student{studentname, email, tel} students = append(students, tmpstudent) } // json形式のデータに変換 jsonstr, err := json.Marshal(students) if err != nil { log.Fatal(err) } // jsonデータを出力 w.Header().Set("Content-Type", "application/json") fmt.Fprintf(w, string(jsonstr)) } // 指定の学生情報を取得 func StudentInfo(w http.ResponseWriter, r *http.Request) { db, err := sql.Open("postgres", "host=db port=5432 user=postgres password=postgres dbname=postgresdb sslmode=disable") // URLからユーザ名を取得 vars := mux.Vars(r) name := vars["name"] // クエリの作成・実行 row := db.QueryRow("SELECT * FROM student WHERE student_name = $1", name) // 実行結果をStudent型に変換 student := Student{} if err := row.Scan(&student.Name, &student.Email, &student.Tel); err != nil { jsonstr, err := json.Marshal(ErrorInfo{err.Error()}) if err != nil { log.Fatal(err) } w.Header().Set("Content-Type", "application/json") fmt.Fprintf(w, string(jsonstr)) return } // json形式のデータに変換 jsonstr, err := json.Marshal(student) if err != nil { log.Fatal(err) } // jsonデータを出力 w.Header().Set("Content-Type", "application/json") fmt.Fprintf(w, string(jsonstr)) } func main() { // リスナの登録 r := mux.NewRouter() r.HandleFunc("/users/{name}", StudentInfo) r.HandleFunc("/", AllStudentInfo) http.Handle("/", r) http.ListenAndServe(":80", nil) }
実行結果
実行結果は以下のようになりました。"/"でアクセスした場合、全学生の情報をJSON形式で返しています。"/users/ユーザー名"でアクセスした場合、特定の学生情報のみをJSON形式で返しています。
感想
Go言語を学習し始めて間もないですが、文法がシンプルだったり、パッケージが豊富で分かり易かったため、実装しやすかったです。APIサーバーの実装方法を整理できたので、次はフロントエンドの開発に挑戦したいと思います。