io/ioutilパッケージ
ファイルの操作は,
全体の読み出し
ioutil.
は,io.
を渡すと,[]byte
型で返します。先ほどの*os.
の読み出しでは直接Read()
を呼んでいたため十分な長さの[]byte
を用意する必要がありましたが,
// ファイルの中身をすべて読み出す
file, _ := os.Open("./file.txt")
message, err := ioutil.ReadAll(file)
これはio.
を実装したすべての型で使用できるため,
ファイルの読み書き
ファイル操作に特化したメソッドも用意されています。
ioutil.
は,[]byte
として読み出します。
// ファイルの中身をすべて読み出す
message, err := ioutil.ReadFile("./file.txt")
iotuil.
は,[]byte
型のデータを書き込みます。第三引数にはファイルのパーミッションを8進数で指定します。
message := []byte("hello world\n")
err := ioutil.WriteFile("./file.txt", message, 0666)
これらを用いて先ほどの操作を書き直すと,
package main
import (
"fmt"
"io/ioutil"
"log"
)
func main() {
// ファイルにメッセージを書き込む
hello := []byte("hello world\n")
err := ioutil.WriteFile("./file.txt", hello, 0666)
if err != nil { // エラー処理
log.Fatal(err)
}
// ファイルの中身を全て読み出す
message, err := ioutil.ReadFile("./file.txt")
if err != nil { // エラー処理
log.Fatal(err)
}
fmt.Print(string(message)) // 文字列にして表示
}
特にファイルI/
net/httpパッケージ
net/
- 注1)
- あくまでサンプルでありセキュリティの観点は省略します。
hello world サーバ
まず,
package main
import (
"fmt"
"net/http"
)
func IndexHandler(w http.ResponseWriter,
r *http.Request) {
fmt.Fprint(w, "hello world")
}
func main() {
http.HandleFunc("/", IndexHandler)
http.ListenAndServe(":3000", nil)
}
ここでは,http.
でルーティングの設定をします。http.
は次のような定義になっています。
func HandleFunc(pattern string,
handler func(ResponseWriter, *Request))
第一引数はパスのパターンで,/
)
第二引数は2つの引数を受け取る関数になっており,IndexHandler
で実装しています。Request
にはリクエストの情報が入っており,ResponseWriter
に書き込むことでレスポンスを返せます。ResponseWriter
は名前のとおりio.
なので,fmt.
を用いて文字列を書き込んでいます。
最後にmain()
では,http.
にポートを指定してサーバを起動しています。第二引数は今回は使わないためnil
を指定します。
このプログラムを実行し,http://
にアクセスして,hello world
が表示されれば成功です
$ go run server.go
JSON/HTMLサーバ
ここではPOSTで送信されたJSONデータをファイルに保存し,
このサーバは,
type Person struct {
ID int `json:"id"`
Name string `json:"name"`
}
サーバは,
POST
処理はPersonHandler
に実装し,/persons
のパスに対して登録します。ここではPOSTリクエストを処理するため,http.
の値で分岐し,
処理が成功した場合はレスポンスとして201 CREATED
を返すため,ResponseWriter.
にnet/
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"os"
)
type Person struct {
ID int `json:"id"`
Name string `json:"name"`
}
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)
}
サーバを起動したら,
$ curl http://localhost:3000/persons -d '{"id":1,"name":"gopher"}'
idを1としたため,gopher
が格納されているはずです。
$ cat 1.txt
gopher
GET
GETが来た場合は,
クエリパラメータはResponseWriter.
から取得できます。この値は文字列であるため,Atoi()
を用います。
// パラメータを取得
id, err := strconv.Atoi(r.URL.Query().Get("id"))
if err != nil {
log.Fatal(err)
}
ここでは,id
に対するファイルを開き,