我自己是PHP 後端工程師,常常在寫網頁、常碰Javascript , html , css 等等,所以,在學這個Go的過程當中,也來學習用go寫一個網頁吧!

Go 與網頁常常有用到的一個套件就叫做 net/http , 他同時也可以做網頁的爬蟲,等等讓我娓娓道來~

網頁版HelloWorld !

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
package main
import (
  "log"
  "net/http"
)

func viewHandler(writer http.ResponseWriter, request *http.Request){
  message := []byte("Hello World")
  _,err := writer.Write(message)
  if err != nil {
    log.Fatal(err)
  }
}

func main(){
  http.HandleFunc("/hello",viewHandler)
  err := http.ListenAndServe("localhost:8080",nil)
  log.Fatal(err)
}

Template

如果網頁只是簡單的HelloWorld 怎麼行?在Go 裡面還有另外一個套件:html/template , 而使用Execute 的第二個參數可以將資料塞入樣板中。而樣板中很重要的是可以使用{{.}} 等符號

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package main
import (
  "log"
  "net/http"
  "html/template"
)

type TemplateData struct {
	Name string
}

func viewHandler(writer http.ResponseWriter, request *http.Request){
  html, err := template.ParseFiles("view.html")
 
  if err != nil {
    log.Fatal(err)
  }
  data := TemplateData{Name:"Jimmy"}
  err = html.Execute(writer,data) 
 
 if err != nil {
    log.Fatal(err)
  }
}

func main(){
  http.HandleFunc("/",viewHandler)
  err := http.ListenAndServe("localhost:8080",nil)
  log.Fatal(err)
}

上面我們有一段template.ParseFiles("view.html") ,而view.html 就像以下這樣寫

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>Hello World</h1>
    #Name: {{.Name}}
</body>
</html>

接下來,讓這裡筆記一下樣板中常見的樣式

  1. {{.Name}} : 塞入名稱為Name
  2. {{ if .Paid }} … {{ end }}: if paid 為 true , 才能執行if 的區塊
  3. {{ range .Charges }} … {{ . }}… {{ end}}: for 迴圈的區塊,根據Charges 裡面的項目依序列出資料

最後,寫個Todolist 吧!

完整程式碼請參考我的github : https://github.com/r567tw/golang-simple-todolist 首先是主程式:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package main

import (
	"bufio"
	"html/template"
	"log"
	"net/http"
	"os"
	"fmt"
)

type TodoList struct {
	Todos []string
}

func getTodos(fileName string) []string {
	var todos []string
	file, err := os.Open(fileName)
	if os.IsNotExist(err) {
		return nil
	}
	defer file.Close()
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		todos = append(todos, scanner.Text())
	}
	return todos
}

func viewHandler(writer http.ResponseWriter, request *http.Request) {
	html, err := template.ParseFiles("view.html")
	todos := getTodos("todolist.txt")
	if err != nil {
		log.Fatal(err)
	}

	todolist := TodoList{
		Todos:  todos,
	}

	err = html.Execute(writer, todolist)

	if err != nil {
		log.Fatal(err)
	}
}

func todoCreateHandler(writer http.ResponseWriter, request *http.Request) {
	task := request.FormValue("task")

	file, _ := os.OpenFile("todolist.txt", os.O_WRONLY | os.O_APPEND | os.O_CREATE , os.FileMode(0600))
	fmt.Fprintln(file, task)
	defer file.Close()
	http.Redirect(writer, request, "/", http.StatusFound)
}

func main() {

	http.HandleFunc("/", viewHandler)
	http.HandleFunc("/todo/create", todoCreateHandler)

	err := http.ListenAndServe("localhost:8080", nil)
	log.Fatal(err)
}

我將Todo 存在檔案todolist.txt 當中

之後就是簡單地建立一下我的呈現畫面,因為我將創建的表單也放進同一頁,所以我就只要單一個檔案:view.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>Golang Simple Todo list</h1>

    <form action="/todo/create" method="post">
        <input type="text" name="task">
        <button>Create Todo</button>
    </form>
    <ul>
        {{range .Todos}}
            <li>{{.}}</li>
        {{end}}
    </ul>
</body>
</html>

小君曰:我要學習的還很多咧