LoginSignup
3
3

More than 5 years have passed since last update.

Goをちょっとだけさわってみる

Last updated at Posted at 2016-02-21

チュートリアルを触れてみる。

1. ファイル読み書きのサンプル

fmtとio/ioutilは基本なんでインポートしてねみたいです。
もちろんメインメソッドが呼ばれます。
この辺は名前から察するに分かりやすいですね。

wiki.go
package main

import (
    "fmt"
    "io/ioutil"
)

func main() {
    p1 := &Page{Title: "TestPage", Body: []byte("This is a sample Page.")}
    p1.save()
    p2, _ := loadPage("TestPage")
    fmt.Println(string(p2.Body))
}

type Page struct {
    Title string
    Body  []byte
}


func (p *Page) save() error {
    filename := p.Title + ".txt"
    return ioutil.WriteFile(filename, p.Body, 0600)
}

func loadPage(title string) (*Page, error) {
    filename := title + ".txt"
    body, err := ioutil.ReadFile(filename)
    if err != nil {
        return nil, err
    }
    return &Page{Title: title, Body: body}, nil
}

ビルドして実行。簡単です。

[murotanimari]$ go build wiki.go

 ~/gowiki
[murotanimari]$ ./wiki
This is a sample Page.

2. サーバーを立ててみる

net.goを作成します。

net.go
package main

import (
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
}

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

コンパイルして実行します。

[murotanimari]$ go build net.go

 ~/gowiki
[murotanimari]$ ./net

http://localhost:9090/
にアクセスすると
「Hi there, I love !」
と表示されます。
あら簡単。

3. ファイル書き込みのサンプル作成

net.go
package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
)

type Page struct {
    Title string
    Body  []byte
}

func main() {
    http.HandleFunc("/view/", viewHandler)
    http.HandleFunc("/edit/", editHandler)
    http.HandleFunc("/save/", saveHandler)
    http.ListenAndServe(":9090", nil)
}

/**
  Handler
**/
func viewHandler(w http.ResponseWriter, r *http.Request) {
    title := r.URL.Path[len("/view/"):]
    fmt.Println(title);
    p, _ := loadPage(title)
    fmt.Println(p.Title);
    fmt.Fprintf(w, "<h1>%s</h1><div>%s</div><br><a href=/edit/%s>Go Edit</a>", p.Title, p.Body,p.Title)
}

func editHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Println(r.URL);
    title := r.URL.Path[len("/edit/"):]
    p, err := loadPage(title)
    if err != nil {
        p = &Page{Title: title}
    }
    fmt.Fprintf(w, "<h1>Editing %s</h1>"+
        "<form action=\"/save/%s\" method=\"POST\">"+
        "<textarea name=\"body\">%s</textarea><br>"+
        "<input type=\"submit\" value=\"Save\">"+
        "</form>",
        p.Title, p.Title, p.Body)
}

func saveHandler(w http.ResponseWriter, r *http.Request) {
    title := r.URL.Path[len("/save/"):]
    body := r.FormValue("body")
    p := &Page{Title: title, Body: []byte(body)}
    p.save()
    http.Redirect(w, r, "/view/"+title, http.StatusFound)
}

/**
  IO Utils
**/
func loadPage(title string) (*Page, error) {
    filename := title + ".txt"
    fmt.Println(filename);
    body, err := ioutil.ReadFile(filename)
    if err != nil {
        return nil, err
    }
    return &Page{Title: title, Body: body}, nil
}
func (p *Page) save() error {
    filename := p.Title + ".txt"
    return ioutil.WriteFile(filename, p.Body, 0600)
}

ビルド&起動

go build ./net.go
./netで起動します。
http://localhost:9090/edit/test

スクリーンショット 2016-02-21 14.44.51.png
スクリーンショット 2016-02-21 14.45.28.png

4. テンプレートの利用

net.goがあるディレクトリにtmplというテンプレートディレクトリを作成して下記の2テンプレートを登録します。

view.html
<h1>{{.Title}}</h1>

<p>[<a href="/edit/{{.Title}}">edit</a>]</p>

<div>{{printf "%s" .Body}}</div>
edit.html
<h1>Editing {{.Title}}</h1>

<form action="/save/{{.Title}}" method="POST">
<div><textarea name="body" rows="20" cols="80">{{printf "%s" .Body}}</textarea></div>
<div><input type="submit" value="Save"></div>
</form>

net.goで正規表現でのパス解析、テンプレート利用、ハンドラーの再利用などのロジックを追加します。

net.go
package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "regexp"
    "errors"
    "html/template"
)

var validPath = regexp.MustCompile("^/(edit|save|view)/([a-zA-Z0-9]+)$")
var templates = template.Must(template.ParseFiles("tmpl/edit.html", "tmpl/view.html"))

type Page struct {
    Title string
    Body  []byte
}

func main() {
    /*http.HandleFunc("/view/", viewHandler)
    http.HandleFunc("/edit/", editHandler)
    http.HandleFunc("/save/", saveHandler)
    */
    http.HandleFunc("/view/", makeHandler(viewHandler))
    http.HandleFunc("/edit/", makeHandler(editHandler))
    http.HandleFunc("/save/", makeHandler(saveHandler))

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

/**
  Handler
**/
func makeHandler(fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        m := validPath.FindStringSubmatch(r.URL.Path)
        if m == nil {
            http.NotFound(w, r)
            return
        }
        fn(w, r, m[2])
    }
}

func viewHandler(w http.ResponseWriter, r *http.Request, title string) {
    p, err := loadPage(title)
    fmt.Println(p.Title);
    if err != nil {
         http.Redirect(w, r, "/edit/"+title, http.StatusFound)
         return
    }
    renderTemplate(w, "view", p)
}

func editHandler(w http.ResponseWriter, r *http.Request, title string) {
    p, err := loadPage(title)
    if err != nil {
        p = &Page{Title: title}
    }
    renderTemplate(w, "edit", p)
}

func saveHandler(w http.ResponseWriter, r *http.Request, title string) {
    body := r.FormValue("body")
    p := &Page{Title: title, Body: []byte(body)}
    err := p.save()
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    http.Redirect(w, r, "/view/"+title, http.StatusFound)
}

/**
  IO Utils
**/
func loadPage(title string) (*Page, error) {
    filename := title + ".txt"
    fmt.Println(filename);
    body, err := ioutil.ReadFile(filename)
    if err != nil {
        return nil, err
    }
    return &Page{Title: title, Body: body}, nil
}
func (p *Page) save() error {
    filename := p.Title + ".txt"
    return ioutil.WriteFile(filename, p.Body, 0600)
}

/**
  Other Utils
**/
func getTitle(w http.ResponseWriter, r *http.Request) (string, error) {
    m := validPath.FindStringSubmatch(r.URL.Path)
    if m == nil {
        http.NotFound(w, r)
        return "", errors.New("Invalid Page Title")
    }
    return m[2], nil // The title is the second subexpression.
}

func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
    err := templates.ExecuteTemplate(w, tmpl+".html", p)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

http://localhost:9090/edit/ANewPage
にアクセス。
スクリーンショット 2016-02-21 15.25.38.png

edit以下に指定されたファイルの作成、編集が可能になりました。

https://github.com/MariMurotani/GooTest
結果はこちらにアップ。
次は、labstack/echoをやってみましょう。
https://github.com/labstack/echo

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3