the5fire

关注Python、Django、Vim、Linux、Web开发、团队管理和互联网--Life is short, we need Python.


Go无框架开发Web应用

作者:the5fire | 标签:     | 发布:2013-11-05 5:37 a.m. | 阅读量: 22207, 21165

作为新(网络)时代的编程语言,go本身就具备了web开发的特性,也就是你不需要框架就可以开始写web程序,这比用Python实现更容易。(可以看下之前写的: Python无框架开发网站 <http://www.the5fire.com/python-website-without-framework.html>_ 。

一个完整的网站项目无外乎这几个东西:数据库,页面模板,程序逻辑,路由分发,web服务。下面就通过代码来展示下Go内置的这些东西。

需要三个文件:db.go index.go index.html,各自的作用为:建立数据库链接 处理逻辑和启动服务 模板

首先是db.go的代码,简单几行,就是看起来有些别扭:

.. code:: go

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/go-sql-driver/mysql"
    "log"
)

func getDB(username, userpwd, dbname string) (*sql.DB, error) {
    dataSourceName := fmt.Sprintf("%s:%s@tcp(localhost:3306)/%s?charset=utf8", username, userpwd, dbname)
    db, err := sql.Open("mysql", dataSourceName)
    if err != nil {
        log.Println(err.Error()) //仅仅是显示异常
        return nil, err
    }
    return db, nil
}

然后是index.go,代码稍多,因为我把具体的handler也放这了:

.. code:: go

package main

import (
    _ "github.com/go-sql-driver/mysql"
    "html/template"
    "log"
    "net/http"
)

const (
    username = "root"
    userpwd  = ""
    dbname   = "go_demos"
)

// User is user
type User struct {
    ID   string
    Name string
}

// 单独提出来,方便使用
func render(w http.ResponseWriter, tmplName string, context map[string]interface{}) {
    tmpl, err := template.ParseFiles(tmplName)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    tmpl.Execute(w, context)
    return
}

func indexHandler(w http.ResponseWriter, r *http.Request) {
    db, err := getDB(username, userpwd, dbname)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    rows, err := db.Query("SELECT id, name FROM t1")
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    defer rows.Close()

    var id, name string
    locals := make(map[string]interface{})
    users := []User{}

    for rows.Next() {
        err = rows.Scan(&id, &name)
        if err == nil {
            log.Println(id, name)
            users = append(users, User{id, name})
        }
    }
    locals["users"] = users
    render(w, "index.html", locals)
    return
}

func main() {
    http.HandleFunc("/", indexHandler)
    // http.HandleFunc("/other", otherHandler)
    err := http.ListenAndServe(":8880", nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err.Error())
    }
}

最后就是模板了, index.html:

.. code:: html

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Hello Golang</title>
    </head>
    <body>
    Hello, UserList
    <table border=1>
        <tr>
            <th>ID</th><th>Name</th>
        </tr>
        {{ range .users }}
            <tr>
                <td>{{ .ID }}</td><td>{{ .Name }}</td>
            </tr>
        {{ end }}
    </table>
    </body>
</html>

对应的数据库的表就是这样子:

.. code:: sql

CREATE TABLE `t1` (
  `id` int(11) NOT NULL,
  `name` char(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8

只是简单的一个示范,真正应用的话模板和handler都是要单独放到文件夹中,db模块也不能这么用,这里只是演示下Go开发web应用的大体逻辑。

- from the5fire.com
----EOF-----

微信公众号:Python程序员杂谈


其他分类: