[Go WebAPI ] Go言語入門~Webアプリを作ろう~

この記事は約11分で読めます。

 

今回はGo言語でWebアプリを作成していきます!! WebAPI

 

前回は

[ Golang ] Go 言語入門~ Web スクレイピング ~
今回は、Go言語を用いて、Webスクレイピングのプログラムを実装します。プログラムを使って、webにアクセスし、取得したデータを見やすいように整形します。webの仕組みを理解する時に、とても勉強になると思います。

 

ゴール

  • Go言語でWEBアプリを作りながら、流れを知ること
  • フレームワークを使った開発のメリットを体験すること

制作物

  • フレームワーク無しのWEBアプリ(WebAPI,Webページ)
  • フレームワーク有りのWEBアプリ(WebAPI、Webページ)

事前知識

WebAPIとWebページは何が違うのでしょうか。

抽象的な違いはこのような感じです。

WebAPI

WEBページ

Webアプリにおいて、フロントのJavascriptで見た目を制御している場合はWebAPIを使って、データを取得し、見た目を更新します。

例としては、SPA(Single Page Application)や、スマホアプリ等で、WebAPIが使われます。

 

一方、アクセス毎に静的なページを返す場合は、後者のようにそもそも見た目もサーバ側で作成します。

例としては、wordpressなどに使われています。(wordpressはPHPで作れられていますが)

今回はこの二つを作ってみます。

とりあえず、動くものを作ってみる

これがサーバの雛形です。

package main

import (
	"net/http"
)

func main() {
	http.HandleFunc("/ping", handler)
	http.ListenAndServe(":8080", nil)
}

func handler(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
	w.Write([]byte("pong"))
}

とても短くて簡単にできそうじゃないですか?

これはlocalhost:8080/pingにアクセスすると、pongと返してくれるアプリです。

パッケージ

net/http…http接続する際に必要な機能がある標準パッケージです。

コード説明

func main(){
	http.HandleFunc("/ping", handler)

	fmt.Println("server start port:8080")
	http.ListenAndServe(":8080", nil)
}

まず、http.HandleFuncで、webページのルーティングを登録していきます。今回だと/pingにアクセスした時に、handler関数を呼び出すという処理を登録しています。

http.ListenAndServeで、どのポートで公開するかを指定しています。今回だと、他のポートと被らないように8080ポートで公開するようにしています。

 

func handler(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
	w.Write([]byte("pong"))
}

次にhandler関数についてです。

  • http.ResponseWriterはレスポンスに関する構造体→情報を返す時に利用
  • http.Requestはリクエストに関する構造体→リクエストに含まれている情報を取得するときに使う

w.WriteHeader(http.StatusOK)で、レスポンスにステータスコードを書き込んでいます。可読性を上げるために、200を打つところを、http.StatusOKを用いています。

w.Write([]byte(“pong”))でpongという文字列をバイト列に変換して書き込んでいます。

handler関数の引数等は難しそうに見えるかもしれませんが、おまじないだと思ってください。

フレームワーク無しで作成する

WebAPI

package main

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

func main() {
	http.HandleFunc("/api", ApiHandler)

	http.ListenAndServe(":8080", nil)
}

type User struct {
	Name string
	Age  int
}

func ApiHandler(w http.ResponseWriter, r *http.Request) {
	user := User{
		Name: "example",
		Age:  20,
	}
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	json.NewEncoder(w).Encode(user)
}

http://localhost:8080/apiにアクセスすると、user情報がjson形式で出力されているはずです。

パッケージ

“encoding/json”…jsonを扱うための標準パッケージです。WebAPI作成で利用しました。

コード説明

type User struct {
	Name string
	Age  int
}

func ApiHandler(w http.ResponseWriter, r *http.Request) {
	user := User{
		Name: "example",
		Age:  20,
	}
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	json.NewEncoder(w).Encode(user)
}

新しいところはここです。

User構造体を作成しました。今回は直打ちで設定してますが、これがデータベース等から取得してきたと仮定してください。

w.Header().Set(“Content-Type”, “application/json”)でレスポンスのデータタイプがjson形式だと明示しています。

json.NewEncoder(w).Encode(user)が結構重要です。

http.ResponseWriterをnewEncoderの引数とする事で、レスポンスにデータを書き込む準備をしています。

Encodeメソッドでは、引数の構造体をマッピングします。

Webページ

ディレクトリは以下のようになります

.
├── main.go
└── views
    └── index.tmpl
package main

import (
	"html/template"
	"net/http"fa
)

func main() {
	http.HandleFunc("/", StaticHandler)
	http.ListenAndServe(":8080", nil)
}

type User struct {
	Name string
	Age  int
}

func StaticHandler(w http.ResponseWriter, r *http.Request) {
	user := User{
		Name: "example",
		Age:  20,
	}
	tmpl := template.Must(template.ParseFiles("./views/index.tmpl"))
	tmpl.Execute(w, user)
}
<!--- views/index.tmpl -->
<!DOCTYPE html>
<html>
<body>
    <p>Name={{.Name}}</p>
    <p>Age={{.Age}}</p>
</body>
</html>

http://localhost:8080にアクセスすると、user情報が表示されていると思います。

パッケージ

“html/template”…静的ファイルを生成したり、処理を加える時に使用する標準パッケージです。

コード説明

WebAPIとの違いは最後のレスポンスデータの書き方です。先ほどは、json形式で返すところを、テンプレートで返すというところですね。

template.Must(template.ParseFiles(“./views/index.tmpl”))で”./views/index.tmpl”ファイルを呼び出しています。(おまじないだと思ってください)

tmpl.Execute(w, user)でuser構造体を静的ページに埋め込んで、レスポンスしています。

index.tmplを見てください。

{{.Name}}でUser構造体のNameプロパティを参照しています。

パッケージ無し

おまじないが多いですよね。次に、フレームワークを見てましょう。

フレームワーク有りで作成する

今回はWebAPIとページを同時にコード上で書きます。

package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	r := gin.Default()
	r.GET("/api", ApiHandler)
	r.GET("/", StaticHandler)
	r.Run() // listen and serve on 0.0.0.0:8080
}

type User struct {
	Name string
	Age  int
}

func StaticHandler(c *gin.Context) {
	user := User{
		Name: "example",
		Age:  20,
	}
	c.HTML(http.StatusOK, "views/index.tmpl", gin.H{
		"Name": user.Name,
		"Age":  user.Age,
	})
}

func ApiHandler(c *gin.Context) {
	user := User{
		Name: "example",
		Age:  20,
	}
	c.JSON(200, gin.H{
		"Name": user.Name,
		"Age":  user.Age,
	})
}

パッケージ

“github.com/gin-gonic/gin”…Webアプリを作るためのフレームワークを搭載した外部パッケージ

コード説明

func main() {
	r := gin.Default()
	r.GET("/api", ApiHandler)
	r.GET("/", StaticHandler)
	r.Run() // listen and serve on 0.0.0.0:8080
}

mainの処理では、最初にフレームワークを用いたルータを初期化し、公開しています。かなり短くなりましたね。

 

func ApiHandler(c *gin.Context) {
	user := User{
		Name: "example",
		Age:  20,
	}
	c.JSON(200, gin.H{
		"Name": user.Name,
		"Age":  user.Age,
	})
}

Handlerで変わったのはresponseWriterやRequestがgin.Contextになっている事です。二つがContextに含まれています。

APIではc.JSON()というメソッドを用いる事で、勝手にJson形式で返却してくれます。

func StaticHandler(c *gin.Context) {
	user := User{
		Name: "example",
		Age:  20,
	}
	c.HTML(http.StatusOK, "views/index.tmpl", gin.H{
		"Name": user.Name,
		"Age":  user.Age,
	})
}

ページでは、c.HTMLメソッドで、静的ページに構造体を埋め込んで、返却してくれます。

フレームワークまとめ

かなり読みやすくなっていると思います。フレームワークの内部では、先ほどの長い処理コードがあるのですが、開発者側では直感的にわかりやすいコードで実装する事ができます。

またフレームワークは多機能なので、色々な機能があるので、是非調べてください。

 

まとめ

今回はWebアプリを作成してみました。

これ以外にも、まだデータを保持する処理(データベース)を用いていなかったり、ログイン機能であったりなど、サービスを作る上では様々処理を利用する必要が有ります。

しかし、どのサービスもここから始まるので、覚えておいて損はないです。

 

次回は、モチベーションを高めるために、基礎だけでなく、上のコードを用いてチャットアプリを作ってみます。

 

追記

[ Golang ] 1時間でできる MP3 の音楽を再生するCLIツールを作成

また、この知識を使って、アプリを作ってみましょう!

以下で掲示板を作成するチュートリアルを書きました!

Golang 入門 : Webサイト(簡易掲示板 ) を作成 part1-プロジェクト作成
Golang で Webアプリ( 掲示板 )を作成してみます。とても勉強になるので、DB(MySQL)への接続も取り扱うので、一通りWebサービス作成を体験できると思います。また、web初めての方でもGoで簡単に作れるようにしているので、是非作成してみてください。
タイトルとURLをコピーしました