Goで簡易的なAPIサーバーを作ってみました。
フレームワークに頼る前に自分でシンプルな構成で立ててみたかったので、今回はフレームワークは使いません
環境
- MacOS 10.15.2
- go version go1.14.4 darwin/amd64
- mysql 8.0.19
インストール
brewに従います。
brew install go
hello world
こんにちは世界
package main
import "fmt"
func main() {
fmt.Printf("hello, world\n")
}
fmt
は入出力系のパッケージです。
他言語でみたことある方は違和感なく使えそうです。
HTTP server 構築
net/http
はHTTP client and server のパッケージです。
なんとたったこれだけでHTTP serverが立てられてしまうそうです。すごい
package main
import (
"fmt"
"log"
"net/http"
)
func homePage(w http.ResponseWriter, r *http.Request){
fmt.Fprintf(w, "Welcome to the HomePage!")
fmt.Println("Endpoint Hit: homePage")
}
func handleRequests() {
http.HandleFunc("/", homePage)
log.Fatal(http.ListenAndServe(":8081", nil))
}
func main() {
handleRequests()
}
Get リクエストを送ると設定しているテキストが返ってきます。
JSON 形式での返却
通常のAPIサーバーではJSON形式が返って来るのが一般的です
struct
と encoding/json
を使って、よくあるAPI形式で結果を返却してみます
https://golang.org/pkg/encoding/json/
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
)
type Article struct {
Title string `json:"Title"`
Desc string `json:"desc"`
Content string `json:"content"`
}
type Articles []Article
func homePage(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Welcome to the HomePage!")
fmt.Println("Endpoint Hit: homePage")
}
func handleRequests() {
http.HandleFunc("/", homePage)
http.HandleFunc("/articles", returnAllArticles)
log.Fatal(http.ListenAndServe(":8081", nil))
}
func returnAllArticles(w http.ResponseWriter, r *http.Request) {
articles := Articles{}
for i := 0; i < 10; i++ {
title := "Hello_%d"
articles = append(
articles,
Article{Title: fmt.Sprintf(title, i), Desc: "Article Description", Content: "Article Content"})
}
fmt.Println("Endpoint Hit: returnAllArticles")
json.NewEncoder(w).Encode(articles)
}
func main() {
handleRequests()
}
こちらの記事を完全参考にしました。。。ありがたいです!
https://hodalog.com/creating-restfulapi-with-golang/
DBの内容を返却
APIで返却する内容はDBへのSQL結果を利用する場合が多いです。
gorm
と言うORMを利用し、実現しました
環境準備
go get でパッケージのインストールをします
$ go get github.com/jinzhu/gorm
$ go get github.com/go-sql-driver/mysql
テーブル作成
gorm でマイグレーションの機能があるのですが普通にcreate tableで作成しました。
CREATE TABLE `gorm-example`.`players` (
`id` INT NOT NULL,
`name` VARCHAR(255) NULL,
`created_at` DATETIME NULL,
`updated_at` DATETIME NULL,
`deleted_at` DATETIME NULL,
PRIMARY KEY (`id`));
DB接続and データ取得
GetDBConn()
GetDBConfig()
でDB接続処理を行い
fetchPlayers
でデータ取得した結果をJSONに変更して返却しています。
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
type Player struct {
gorm.Model
Name string
}
var player Player
var players []Player
func handleRequests() {
http.HandleFunc("/", homePage)
http.HandleFunc("/players", fetchPlayers)
log.Fatal(http.ListenAndServe(":8081", nil))
}
func fetchPlayers(w http.ResponseWriter, r *http.Request) {
db := GetDBConn()
db.Find(&players)
fmt.Println(players)
profJson, _ := json.Marshal(players)
fmt.Fprintf(w, string(profJson))
}
func GetDBConn() *gorm.DB {
db, err := gorm.Open(GetDBConfig())
if err != nil {
panic(err)
}
db.LogMode(true)
return db
}
func GetDBConfig() (string, string) {
DBMS := "mysql"
USER := "root"
PASS := ""
PROTOCOL := ""
DBNAME := "gorm-example"
OPTION := "charset=utf8&parseTime=True&loc=Local"
CONNECT := USER + ":" + PASS + "@" + PROTOCOL + "/" + DBNAME + "?" + OPTION
return DBMS, CONNECT
}
func homePage(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Welcome to the HomePage!")
fmt.Println("Endpoint Hit: homePage")
}
func main() {
handleRequests()
}
データを取得すると想定通りに値が返ってきています。
(何故か大文字になるけど)
参考記事: https://medium.com/@taka.abc.hiko/gorm%E3%81%A8%E3%81%84%E3%81%86orm%E3%81%8C%E8%B6%85%E7%B5%B6%E4%BE%BF%E5%88%A9%E3%81%A0%E3%81%A3%E3%81%9F%E4%BB%B6-8d279489c38f
まとめ
- GoでAPIサーバーを立てるのは、標準ライブラリが揃ってて簡単
- ルーター/認証などフレームワークに乗っ取ったりする部分はどうするかまだわからない