消息关闭
    暂无新消息!

go实现个留言本-----------------

问题作者 : 枕头2017-06-29发布
go实现个留言本


一、分析

   要实现这个下面是几个重要的东西。

  1.数据库操作(go怎么操作数据库)、
  2.输出js,css,图片等
  3.html显示


 为什么会有以上的几个问题.下面一一分析

1.数据库操作。
   go并没有提供对应的数据库操作的包。只提供了数据库的接口。各种数据库必须自己去实现数据库操作的接口。
   感谢开源社区,这些别人帮你实现了。然后我们只需要导入对应的包即可。


2.输出js,css,图片
  这也是个问题。这的确是个问题。上次的代码只是实现了动态页面的显示。但是js和图片这些是不同的他们有着不同的http头(不懂可以去查查http协议的东西)。不能简单的只输出内容。
  信号go给我们考虑好了其http包里面有方法可实现。没法go不是专门的web服务器。一般这都是web服务器干的事情。

3.html显示
  html显示的时候如果我们在代码里面直接输出,那么一旦我们每次 仅仅只是更改点html的代码却要重新编译。是不是很痛苦。
 感谢go为我们提供了template包。我们可以用模板。
 


好吧以上问题找到了 解决的方向。那么开始吧。

我们实现一个留言本。


一个留言本的基本功能就是。提交留言,显示留言。
为了使得这个项目好理解和容易实现我们尽量简单。所以这个例子代码会非常的烂。请别砸砖头。囧!


先上go代码:
package main
import (
    "database/sql"
    "fmt"
    _ "github.com/go-sql-driver/mysql"
    "html/template"
    "log"
    "net/http"
    "time"
)
type Message struct {
    Id         int
    Uname      string
    Email      string
    Content    string
    InsertTime string
}
func CheckErr(err error) {
    if err != nil {
        fmt.Println("ddddddddddd")
        panic(err)
    }
}
func bookList(w http.ResponseWriter, r *http.Request) {
    var id int
    var insert_time int
    var uname string
    var content string
    var email string
    db, err := sql.Open("mysql", "root:123456@tcp(172.20.10.80:3306)/test?charset=utf8")
    CheckErr(err)
    rows, err := db.Query("select id, uname,content, email, insert_time from book")
    CheckErr(err)
    var msgSlice []*Message
    for rows.Next() {
        err = rows.Scan(&id, &uname, &content, &email, &insert_time)
        CheckErr(err)
        msg := new(Message)
        msg.Id = id
        msg.InsertTime = time.Unix(int64(insert_time), 0).Format("2006-01-02 15:04:05")
        msg.Uname = uname
        msg.Content = content
        msg.Email = email
        //fmt.Fprintf(w, id)
        msgSlice = append(msgSlice, msg)
    }
    t, err := template.ParseFiles("index.html")
    if err != nil {
        log.Println(err)
    }
    t.Execute(w, &msgSlice)
}
func add(w http.ResponseWriter, r *http.Request) {
    err := r.ParseForm()
    uname := "hahahah 没有"
    content := r.FormValue("content")
    email := r.FormValue("email")
    insertTime := time.Now().Unix()
    db, err := sql.Open("mysql", "root:123456@tcp(172.20.10.80:3306)/test?charset=utf8")
    CheckErr(err)
    stmt, err := db.Prepare("insert into book(uname,content, email, insert_time)values(?,?,?,?)")
    if _, err := stmt.Exec(uname, content, email, insertTime); err == nil {
        //w.Write([]byte("ok"))
    }
    bookList(w, r)
    db.Close()
}
func main() {
    http.HandleFunc("/", bookList)
    http.HandleFunc("/list", bookList)
    http.HandleFunc("/add", add)
    http.Handle("/static/", http.FileServer(http.Dir("./"))) 
    //http.HandleFunc("/", sayhelloName)       //设置访问的路由
    err := http.ListenAndServe(":9090", nil) //设置监听的端口
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}


首先我们勇mysql建立了个 数据库test.有一张表:

CREATE TABLE `book` (
  `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `uname` CHAR(1) DEFAULT NULL,
  `email` VARCHAR(32) NOT NULL,
  `content` TEXT,
  `insert_time` INT(10) UNSIGNED NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8



uname 用户名
content 留言内容
insert_time 留言时间


然后为了操作数据库,我们导入了第三方包  _ "github.com/go-sql-driver/mysql"
这个包数据怎么弄了?首先你在系统中安装git吧(真麻烦 囧,这个自行google)
另外你得设置个gopath 可以是任意目录 第三方包惠粗在这个目录
然后通过命令go get github.com/go-sql-driver/mysql
这样第三方包就会被下载下来了。

然后才是操作数据库:

  db, err := sql.Open("mysql", "root:123456@tcp(172.20.10.80:3306)/test?charset=utf8")
这里是连接数据库
mysql是数据库类型
root账号
123456密码
tcp是协议类型
172.20.10.80数据库地址
3306 端口号
/test 这个是数据库库名
utf8 编码类型 建议就用utf8吧。因为go默认是utf8 编码的(鄙视哈居然不能用中文当变量名,看看java或者c#)

操作数据库 看代码应该基本没太大问题。这里略过。


  http.Handle("/static/", http.FileServer(http.Dir("./"))) 这个设置了静态路由。记住路径是以最后编译的exe文件的位置来算的


然后是模板代码:

<!doctype html>
<html>
    <header>
    <title>留言本</title>
    <link type="text/css" rel="stylesheet" href="static/main.css"/>
    </header>
    <body>
        <div id="container">
        <h4>go语言留言本</h4>
            {{range .}}
            <div class="list">
                <span>{{.Email}}</span>{{.InsertTime}}发表:
                <p>{{.Content}}</p>
            </div>
            {{end}}
        </div>
        <div class="subform">
            <form action="/add" method="post">
            <em for="email">您的邮箱:</em><input type="text" id="email" name="email" /></br>
            <textarea cols="100" rows="5" name="content">
                ....
            </textarea></br>
            <input type="submit" value="提交">
            </form>
        </div>
    </body>
</html>

range 表示循环  点表示当前的对象 即 t.Execute(w, &msgSlice)中的msgSlice对象。
这里要注意 对象中的属性 必须是对外可见的 即Email Content 都必须是首字母大写的。
否则没法解析
而循环中的.Email 就是表示的msgSlice对象数组(slice)中的email属性。

贴下css和文件结构:
body{font-family: Verdana,Arial,Helvetica,sans-serif;font-size:12px}
textarea{font-family: Verdana,Arial,Helvetica,sans-serif;}
input[type=button] {-webkit-appearance: button;}
img{border:0px;}
.list{margin:5px;border:#cccccc 1px solid;min-height:100px}
.list span{margin:0 5px 0 5px;font-weight: bold;}
.list p{text-indent:2em}


文件结构:
-----
|----static
        |----main.css
----main.go
----index.html



然后go run 就ok了。


最后介绍个win下的go开发工具liteIde用起来还不错。并且其还有中文版的。
(完)







43个回答

︿ 1
导入"github.com/go-sql-driver/mysql"这个包是不是意味着编译代码的时候必须联网?