※これは解答です。どうしても課題が解けない場合、ご利用ください。
練習問題 #1: FizzBuzz APIを作ろう
package main
import (
"fmt"
"log"
"net/http"
"strconv"
"github.com/julienschmidt/httprouter"
)
func FizzBuzz(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
num, err := strconv.Atoi(p.ByName("num"))
if err != nil || num < 1 {
http.Error(w, fmt.Sprintf("%d Bad Request", http.StatusBadRequest), http.StatusBadRequest)
return
}
var str string
for i := 1; i <= num; i++ {
if i%15 == 0 {
str += fmt.Sprintf("%d: %s\n", i, "FizzBuzz!")
} else if i%5 == 0 {
str += fmt.Sprintf("%d: %s\n", i, "Buzz")
} else if i%3 == 0 {
str += fmt.Sprintf("%d: %s\n", i, "Fizz")
} else {
str += fmt.Sprintf("%d:\n", i)
}
}
fmt.Fprintf(w, str)
}
func main() {
router := httprouter.New()
router.GET("/FizzBuzz/:num", FizzBuzz)
err := http.ListenAndServe(":8080", router)
if err != nil {
log.Fatal(err)
}
}
練習問題 #2: プロフィール取得APIを作ろう
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"github.com/julienschmidt/httprouter"
)
type Profile struct {
Name string `json:"name"`
Age int `json:"age"`
Gender string `json:"gender"`
FavoriteFoods []string `json:"favorite_foods"`
}
var bob Profile = Profile{
Name: "Bob",
Age: 25,
Gender: "Man",
FavoriteFoods: []string{"Hamburger", "Cookie", "Chocolate"},
}
var alice Profile = Profile{
Name: "Alice",
Age: 24,
Gender: "Woman",
FavoriteFoods: []string{"Apple", "Orange", "Melon"},
}
func GetProfile(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
name := p.ByName("name")
var resProfile Profile
if name == "Bob" {
resProfile = bob
} else if name == "Alice" {
resProfile = alice
} else {
http.Error(w, fmt.Sprintf("%d Not Found", http.StatusNotFound), http.StatusNotFound)
return
}
bytes, err := json.Marshal(resProfile)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
}
fmt.Fprintf(w, string(bytes))
}
func main() {
router := httprouter.New()
router.GET("/Profile/:name", GetProfile)
err := http.ListenAndServe(":8080", router)
if err != nil {
log.Fatal(err)
}
}
練習問題 #3: プロフィール保存APIを作ろう
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"github.com/julienschmidt/httprouter"
)
type Profile struct {
Name string `json:"name"`
Age int `json:"age"`
Gender string `json:"gender"`
FavoriteFoods []string `json:"favorite_foods"`
}
var savedProfiles map[string]Profile = map[string]Profile{}
func PostProfile(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
defer r.Body.Close()
body, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
var reqProfile Profile
err = json.Unmarshal(body, &reqProfile)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if reqProfile.Name == "" {
http.Error(w, "name is required.", http.StatusBadRequest)
return
}
savedProfiles[reqProfile.Name] = reqProfile
fmt.Fprintf(w, fmt.Sprintf("%d Created", http.StatusCreated))
}
func main() {
router := httprouter.New()
router.POST("/Profile", PostProfile)
err := http.ListenAndServe(":8080", router)
if err != nil {
log.Fatal(err)
}
}
練習問題 #4: プロフィール取得APIを拡張しよう
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"github.com/julienschmidt/httprouter"
)
type Profile struct {
Name string `json:"name"`
Age int `json:"age"`
Gender string `json:"gender"`
FavoriteFoods []string `json:"favorite_foods"`
}
var savedProfiles map[string]Profile = map[string]Profile{}
func PostProfile(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
defer r.Body.Close()
body, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
var reqProfile Profile
err = json.Unmarshal(body, &reqProfile)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if reqProfile.Name == "" {
http.Error(w, "name is required.", http.StatusBadRequest)
return
}
savedProfiles[reqProfile.Name] = reqProfile
fmt.Fprintf(w, fmt.Sprintf("%d Created", http.StatusCreated))
}
func GetProfile(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
name := p.ByName("name")
resProfile, found := savedProfiles[name]
if !found {
http.Error(w, fmt.Sprintf("%d Not Found", http.StatusNotFound), http.StatusNotFound)
return
}
bytes, err := json.Marshal(resProfile)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
}
fmt.Fprintf(w, string(bytes))
}
func main() {
router := httprouter.New()
router.POST("/Profile", PostProfile)
router.GET("/Profile/:name", GetProfile)
err := http.ListenAndServe(":8080", router)
if err != nil {
log.Fatal(err)
}
}
練習問題 #5: APIクライアントを作ろう
get_client.go
package main
import (
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
)
func main() {
name := flag.String("name", "", "Name")
flag.Parse()
resp, err := http.Get(fmt.Sprintf("http://localhost:8080/Profile/%s", *name))
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
bytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(bytes))
}
post_client.go
package main
import (
"bytes"
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"strings"
)
type Profile struct {
Name string `json:"name"`
Age int `json:"age"`
Gender string `json:"gender"`
FavoriteFoods []string `json:"favorite_foods"`
}
func main() {
profile := parseArgs()
fmt.Printf("%+v\n", profile)
jsonStr, err := json.Marshal(profile)
if err != nil {
log.Fatal(err)
}
req, err := http.NewRequest("POST", "http://localhost:8080/Profile", bytes.NewBuffer([]byte(jsonStr)))
if err != nil {
log.Fatal(err)
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
func parseArgs() Profile {
name := flag.String("name", "", "Name")
age := flag.Int("age", 0, "Age")
gender := flag.String("gender", "", "Gender")
foods := flag.String("foods", "", "Favorite foods")
flag.Parse()
return Profile{
Name: *name,
Age: *age,
Gender: *gender,
FavoriteFoods: strings.Split(*foods, " "),
}
}
練習問題 #6: HTMLを返そう
index.html.tpl
<html>
<body>
<h1>Hello golang!</h1>
<div><a href="/profile/Alice">Alice</a></div>
<div><a href="/profile/Bob">Bob</a></div>
</body>
</html>
profile.html.tpl
<html>
<body>
<h1>Hello golang!</h1>
<div>Name: {{ .Name }}</div>
<div>Age: {{ .Age }}</div>
<div>Gender: {{ .Gender }}</div>
<div>Favorite Foods: {{ .FavoriteFoods }}</div>
</body>
</html>
html_server.go
package main
import (
"fmt"
"html/template"
"log"
"net/http"
"github.com/julienschmidt/httprouter"
)
type Profile struct {
Name string `json:"name"`
Age int `json:"age"`
Gender string `json:"gender"`
FavoriteFoods []string `json:"favorite_foods"`
}
var bob Profile = Profile{
Name: "Bob",
Age: 25,
Gender: "Man",
FavoriteFoods: []string{"Hamburger", "Cookie", "Chocolate"},
}
var alice Profile = Profile{
Name: "Alice",
Age: 24,
Gender: "Woman",
FavoriteFoods: []string{"Apple", "Orange", "Melon"},
}
func Index(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
t := template.Must(template.ParseFiles("templates/index.html.tpl"))
err := t.ExecuteTemplate(w, "index.html.tpl", nil)
if err != nil {
log.Fatal(err)
}
}
func GetProfile(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
name := p.ByName("name")
var resProfile Profile
if name == "Bob" {
resProfile = bob
} else if name == "Alice" {
resProfile = alice
} else {
http.Error(w, fmt.Sprintf("%d Not Found", http.StatusNotFound), http.StatusNotFound)
return
}
t := template.Must(template.ParseFiles("templates/profile.html.tpl"))
err := t.ExecuteTemplate(w, "profile.html.tpl", resProfile)
if err != nil {
log.Fatal(err)
}
}
func main() {
router := httprouter.New()
router.GET("/", Index)
router.GET("/profile/:name", GetProfile)
err := http.ListenAndServe(":8080", router)
if err != nil {
log.Fatal(err)
}
}