コピペコードで快適生活

明日使えるソースを自分のために

Goことはじめ(net/httpパッケージ)

http://gihyo.jp/dev/feature/01/go_4beginners/0004?page=3
より学んだことメモ。

hello worldを返すだけのhttpサーバ

package main

import (
	"fmt"
	"net/http"
)

//
// http.ResponseWriterがレスポンスデータ
// *http.Requestはリクエストデータ
//
func IndexHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "hello world")
}

func main() {
	// ルーティング設定
	http.HandleFunc("/", IndexHandler)

	// ポートを割り当ててサーバ起動
	http.ListenAndServe(":3000", nil)
}

JSONをPOSTでうけてファイルに保存する

package main

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

type Person struct {
	ID int `json:"id"`
	Name string `json:"name"`
}

//
// http.ResponseWriterがレスポンスデータ
// *http.Requestはリクエストデータ
//
func IndexHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "hello world")
}

func PersonHandler(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close() // 処理の最後にBodyを閉じる

	if r.Method == "POST" {
		// リクエストボディをJSONに変換
		var person Person
		decoder := json.NewDecoder(r.Body)
		err := decoder.Decode(&person)
		if err != nil { // エラー処理
			log.Fatal(err)
		}

		// ファイル名を {id}.txt とする
		filename := fmt.Sprintf("%d.txt", person.ID)
		file, err := os.Create(filename) // ファイルを生成
		if err != nil {
			log.Fatal(err)
		}
		defer file.Close()

		// ファイルにNameを書き込む
		_, err = file.WriteString(person.Name)
		if err != nil {
			log.Fatal(err)
		}

		// レスポンスデータとしてステータスコード201を返す
		w.WriteHeader(http.StatusCreated)
	}
}

func main() {
	// ルーティング設定
	http.HandleFunc("/", IndexHandler)
	http.HandleFunc("/persons", PersonHandler)

	// ポートを割り当ててサーバ起動
	http.ListenAndServe(":3000", nil)
}

GETでうけてtemplateを使ってHTMLを返す

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"
	"strconv"
	"html/template"
	"io/ioutil"
)

type Person struct {
	ID int `json:"id"`
	Name string `json:"name"`
}

// テンプレートのコンパイル
// Mustを使うとエラー時にパニックを起こす
// var t, err := template.personFiles("index.html")
var t = template.Must(template.ParseFiles("index.html"))

//
// http.ResponseWriterがレスポンスデータ
// *http.Requestはリクエストデータ
//
func IndexHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "hello world")
}

func PersonHandler(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close() // 処理の最後にBodyを閉じる

	if r.Method == "POST" {
		// リクエストボディをJSONに変換
		var person Person
		decoder := json.NewDecoder(r.Body)
		err := decoder.Decode(&person)
		if err != nil { // エラー処理
			log.Fatal(err)
		}

		// ファイル名を {id}.txt とする
		filename := fmt.Sprintf("%d.txt", person.ID)
		file, err := os.Create(filename) // ファイルを生成
		if err != nil {
			log.Fatal(err)
		}
		defer file.Close()

		// ファイルにNameを書き込む
		_, err = file.WriteString(person.Name)
		if err != nil {
			log.Fatal(err)
		}

		// レスポンスデータとしてステータスコード201を返す
		w.WriteHeader(http.StatusCreated)
	} else if r.Method == "GET" {
		// パラメータを取得
		id, err := strconv.Atoi(r.URL.Query().Get("id"))
		if err != nil {
			log.Fatal(err)
		}

		filename := fmt.Sprintf("%d.txt", id)
		b, err := ioutil.ReadFile(filename)
		if err != nil {
			log.Fatal(err)
		}

		// personを生成
		person := Person {
			ID: id,
			Name: string(b),
		}

		// レスポンスにエンコーディングしたHTMLを書き込む
		t.Execute(w, person)
	}
}

func main() {
	// ルーティング設定
	http.HandleFunc("/", IndexHandler)
	http.HandleFunc("/persons", PersonHandler)

	// ポートを割り当ててサーバ起動
	http.ListenAndServe(":3000", nil)
}

データを埋め込むには{{ }}で値をくくり,その中に埋め込みたいプロパティを指定する。

<!DOCTYPE html>
<title>person</title>
<h1>{{ .ID }} : {{ .Name }}</h1>