Go 學習筆記(6): 寫一個網頁吧!

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

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

網頁版HelloWorld !

 1package main
 2import (
 3  "log"
 4  "net/http"
 5)
 6
 7func viewHandler(writer http.ResponseWriter, request *http.Request){
 8  message := []byte("Hello World")
 9  _,err := writer.Write(message)
10  if err != nil {
11    log.Fatal(err)
12  }
13}
14
15func main(){
16  http.HandleFunc("/hello",viewHandler)
17  err := http.ListenAndServe("localhost:8080",nil)
18  log.Fatal(err)
19}

Template

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

 1package main
 2import (
 3  "log"
 4  "net/http"
 5  "html/template"
 6)
 7
 8type TemplateData struct {
 9	Name string
10}
11
12func viewHandler(writer http.ResponseWriter, request *http.Request){
13  html, err := template.ParseFiles("view.html")
14 
15  if err != nil {
16    log.Fatal(err)
17  }
18  data := TemplateData{Name:"Jimmy"}
19  err = html.Execute(writer,data) 
20 
21 if err != nil {
22    log.Fatal(err)
23  }
24}
25
26func main(){
27  http.HandleFunc("/",viewHandler)
28  err := http.ListenAndServe("localhost:8080",nil)
29  log.Fatal(err)
30}

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

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

 1package main
 2
 3import (
 4	"bufio"
 5	"html/template"
 6	"log"
 7	"net/http"
 8	"os"
 9	"fmt"
10)
11
12type TodoList struct {
13	Todos []string
14}
15
16func getTodos(fileName string) []string {
17	var todos []string
18	file, err := os.Open(fileName)
19	if os.IsNotExist(err) {
20		return nil
21	}
22	defer file.Close()
23	scanner := bufio.NewScanner(file)
24	for scanner.Scan() {
25		todos = append(todos, scanner.Text())
26	}
27	return todos
28}
29
30func viewHandler(writer http.ResponseWriter, request *http.Request) {
31	html, err := template.ParseFiles("view.html")
32	todos := getTodos("todolist.txt")
33	if err != nil {
34		log.Fatal(err)
35	}
36
37	todolist := TodoList{
38		Todos:  todos,
39	}
40
41	err = html.Execute(writer, todolist)
42
43	if err != nil {
44		log.Fatal(err)
45	}
46}
47
48func todoCreateHandler(writer http.ResponseWriter, request *http.Request) {
49	task := request.FormValue("task")
50
51	file, _ := os.OpenFile("todolist.txt", os.O_WRONLY | os.O_APPEND | os.O_CREATE , os.FileMode(0600))
52	fmt.Fprintln(file, task)
53	defer file.Close()
54	http.Redirect(writer, request, "/", http.StatusFound)
55}
56
57func main() {
58
59	http.HandleFunc("/", viewHandler)
60	http.HandleFunc("/todo/create", todoCreateHandler)
61
62	err := http.ListenAndServe("localhost:8080", nil)
63	log.Fatal(err)
64}

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

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

 1<!DOCTYPE html>
 2<html lang="en">
 3<head>
 4    <meta charset="UTF-8">
 5    <meta http-equiv="X-UA-Compatible" content="IE=edge">
 6    <meta name="viewport" content="width=device-width, initial-scale=1.0">
 7    <title>Document</title>
 8</head>
 9<body>
10    <h1>Golang Simple Todo list</h1>
11
12    <form action="/todo/create" method="post">
13        <input type="text" name="task">
14        <button>Create Todo</button>
15    </form>
16    <ul>
17        {{range .Todos}}
18            <li>{{.}}</li>
19        {{end}}
20    </ul>
21</body>
22</html>

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


原來可以這麼寫(13): 其實我會一點點Ruby
為什麼我要搬家