├── .gitignore
├── README.md
├── cfg.example.json
├── control
├── g
├── config.go
└── const.go
├── handler
└── home_hander.go
├── http
├── cookie
│ └── cookie.go
├── errors
│ └── errors.go
├── helper
│ └── helper.go
├── http.go
├── middleware
│ ├── logger.go
│ └── recovery.go
├── param
│ └── param.go
├── render
│ └── render.go
└── routes.go
├── init
├── main.go
├── model
└── example.go
├── store
└── mysql.go
└── views
├── common
└── error.html
└── home
└── index.html
/.gitignore:
--------------------------------------------------------------------------------
1 | cfg.json
2 | Toruk
3 | /var/*
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Toruk
2 | ### go web 开发脚手架
3 |
4 | 主要由下面几个第三方库集成,简单、灵活,可以快速开发web项目
5 |
6 | * 路由:github.com/gorilla/mux
7 | * 渲染模板:github.com/unrolled/render
8 | * Cookie封装:github.com/gorilla/securecookie
9 | * 中间件:github.com/codegangsta/negroni
10 | * 上下文传输:github.com/gorilla/context
11 |
12 | ### 文件结构
13 |
14 |
15 |
16 | ### 使用方法
17 | 通过修改http/ruote.go 将数据传到对应的handler中,然后在通过render将数据返回回去。
18 | ruote.go
19 |
20 | func configConfRoutes(r *mux.Router) {
21 | r.HandleFunc("/home", handler.HomeIndex).Methods("GET")
22 | }
23 |
24 | handler.go
25 |
26 | func HomeIndex(w http.ResponseWriter, r *http.Request) {
27 | render.HTML(r, w, "home/index")
28 | }
29 |
30 | ### 初始化
31 |
32 | # set $GOPATH and $GOROOT
33 | # 比如你的项目名称叫做 awosome
34 | cd $GOPATH/src
35 | git clone https://github.com/710leo/Toruk.git
36 | mv Toruk awosome
37 | cd awosome
38 | ./init awosome
39 | go get ./...
40 |
41 | ### 编译&运行
42 | ./control build
43 | ./control start
44 |
45 | ### 答疑
46 | 交流QQ群:173502733
47 |
--------------------------------------------------------------------------------
/cfg.example.json:
--------------------------------------------------------------------------------
1 | {
2 | "debug": false,
3 | "http": {
4 | "listen": "0.0.0.0:4200",
5 | "secret": "secret"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/control:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | WORKSPACE=$(cd $(dirname $0)/; pwd)
4 | cd $WORKSPACE
5 |
6 | mkdir -p var
7 |
8 | module=toruk
9 | app=toruk
10 | conf=cfg.json
11 | pidfile=var/app.pid
12 | logfile=var/app.log
13 |
14 | function check_pid() {
15 | if [ -f $pidfile ];then
16 | pid=`cat $pidfile`
17 | if [ -n $pid ]; then
18 | running=`ps -p $pid|grep -v "PID TTY" |wc -l`
19 | return $running
20 | fi
21 | fi
22 | return 0
23 | }
24 |
25 | function start() {
26 | check_pid
27 | running=$?
28 | if [ $running -gt 0 ];then
29 | echo -n "$app now is running already, pid="
30 | cat $pidfile
31 | return 1
32 | fi
33 |
34 | nohup ./$app -c $conf &> $logfile &
35 | echo $! > $pidfile
36 | echo "$app started..., pid=$!"
37 | }
38 |
39 | function stop() {
40 | pid=`cat $pidfile`
41 | kill $pid
42 | echo "$app stoped..."
43 | }
44 |
45 | function restart() {
46 | stop
47 | sleep 1
48 | start
49 | }
50 |
51 | function status() {
52 | check_pid
53 | running=$?
54 | if [ $running -gt 0 ];then
55 | echo "started"
56 | else
57 | echo "stoped"
58 | fi
59 | }
60 |
61 | function tailf() {
62 | tail -f $logfile
63 | }
64 |
65 | function build() {
66 | go build
67 | if [ $? -ne 0 ]; then
68 | exit $?
69 | fi
70 | mv $module $app
71 | ./$app -v
72 | }
73 |
74 | function help() {
75 | echo "$0 pid|reload|build|pack|packbin|start|stop|restart|status|tail"
76 | }
77 |
78 | function pid() {
79 | cat $pidfile
80 | }
81 |
82 | function reload() {
83 | build
84 | restart
85 | tailf
86 | }
87 |
88 | if [ "$1" == "" ]; then
89 | help
90 | elif [ "$1" == "stop" ];then
91 | stop
92 | elif [ "$1" == "start" ];then
93 | start
94 | elif [ "$1" == "restart" ];then
95 | restart
96 | elif [ "$1" == "status" ];then
97 | status
98 | elif [ "$1" == "tail" ];then
99 | tailf
100 | elif [ "$1" == "build" ];then
101 | build
102 | elif [ "$1" == "pid" ];then
103 | pid
104 | elif [ "$1" == "reload" ];then
105 | reload
106 | else
107 | help
108 | fi
109 |
--------------------------------------------------------------------------------
/g/config.go:
--------------------------------------------------------------------------------
1 | package g
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "log"
7 | "sync"
8 |
9 | "github.com/toolkits/file"
10 | )
11 |
12 | type HttpConfig struct {
13 | Listen string `json:"listen"`
14 | Secret string `json:"secret"`
15 | }
16 |
17 | type GlobalConfig struct {
18 | Debug bool `json:"debug"`
19 | Http *HttpConfig `json:"http"`
20 | }
21 |
22 | var (
23 | ConfigFile string
24 | config *GlobalConfig
25 | configLock = new(sync.RWMutex)
26 | )
27 |
28 | func Config() *GlobalConfig {
29 | configLock.RLock()
30 | defer configLock.RUnlock()
31 | return config
32 | }
33 |
34 | func Parse(cfg string) error {
35 | if cfg == "" {
36 | return fmt.Errorf("use -c to specify configuration file")
37 | }
38 |
39 | if !file.IsExist(cfg) {
40 | return fmt.Errorf("configuration file %s is nonexistent", cfg)
41 | }
42 |
43 | ConfigFile = cfg
44 |
45 | configContent, err := file.ToTrimString(cfg)
46 | if err != nil {
47 | return fmt.Errorf("read configuration file %s fail %s", cfg, err.Error())
48 | }
49 |
50 | var c GlobalConfig
51 | err = json.Unmarshal([]byte(configContent), &c)
52 | if err != nil {
53 | return fmt.Errorf("parse configuration file %s fail %s", cfg, err.Error())
54 | }
55 |
56 | configLock.Lock()
57 | defer configLock.Unlock()
58 | config = &c
59 |
60 | log.Println("load configuration file", cfg, "successfully")
61 | return nil
62 | }
63 |
--------------------------------------------------------------------------------
/g/const.go:
--------------------------------------------------------------------------------
1 | package g
2 |
3 | const (
4 | VERSION = "0.0.3"
5 | )
6 |
7 | //0.0.2 优化render, panic日志展示
8 | //0.0.3 http log 增加ip信息
9 |
--------------------------------------------------------------------------------
/handler/home_hander.go:
--------------------------------------------------------------------------------
1 | package handler
2 |
3 | import (
4 | "net/http"
5 |
6 | "github.com/710leo/Toruk/http/render"
7 | )
8 |
9 | func HomeIndex(w http.ResponseWriter, r *http.Request) {
10 | render.HTML(r, w, "home/index")
11 | }
12 |
--------------------------------------------------------------------------------
/http/cookie/cookie.go:
--------------------------------------------------------------------------------
1 | package cookie
2 |
3 | import (
4 | "net/http"
5 |
6 | "github.com/gorilla/securecookie"
7 | )
8 |
9 | var SecureCookie *securecookie.SecureCookie
10 |
11 | func Init() {
12 | var hashKey = []byte(nil)
13 | var blockKey = []byte(nil)
14 | SecureCookie = securecookie.New(hashKey, blockKey)
15 | }
16 |
17 | func ReadUser(r *http.Request) (example string) {
18 | if cookie, err := r.Cookie("u"); err == nil {
19 | value := make(map[string]interface{})
20 | if err = SecureCookie.Decode("u", cookie.Value, &value); err == nil {
21 | example = value["example"].(string)
22 | }
23 | }
24 | return
25 | }
26 |
27 | func WriteUser(w http.ResponseWriter, example string) error {
28 | value := make(map[string]interface{})
29 | value["example"] = example
30 | encoded, err := SecureCookie.Encode("u", value)
31 | if err != nil {
32 | return err
33 | }
34 |
35 | cookie := &http.Cookie{
36 | Name: "u",
37 | Value: encoded,
38 | Path: "/",
39 | MaxAge: 3600 * 24 * 7,
40 | HttpOnly: true,
41 | }
42 | http.SetCookie(w, cookie)
43 |
44 | return nil
45 | }
46 |
47 | func RemoveUser(w http.ResponseWriter) error {
48 | value := make(map[string]interface{})
49 | value["example"] = ""
50 | encoded, err := SecureCookie.Encode("u", value)
51 | if err != nil {
52 | return err
53 | }
54 |
55 | cookie := &http.Cookie{
56 | Name: "u",
57 | Value: encoded,
58 | Path: "/",
59 | MaxAge: -1,
60 | }
61 | http.SetCookie(w, cookie)
62 |
63 | return nil
64 | }
65 |
--------------------------------------------------------------------------------
/http/errors/errors.go:
--------------------------------------------------------------------------------
1 | package errors
2 |
3 | import (
4 | "net/http"
5 | "runtime"
6 | "strings"
7 | "time"
8 | )
9 |
10 | type Error struct {
11 | Code int `json:"code"`
12 | Msg string `json:"msg"`
13 | Time string `json:"time"`
14 | File string `json:"file"`
15 | Line int `json:"line"`
16 | }
17 |
18 | // 401
19 | func NotLoginError(msg ...string) Error {
20 | return _build(http.StatusUnauthorized, "unauthorized", msg...)
21 | }
22 |
23 | // 400
24 | func BadRequestError(msg ...string) Error {
25 | return _build(http.StatusBadRequest, "bad request", msg...)
26 | }
27 |
28 | // 403
29 | func NoPrivError(msg ...string) Error {
30 | return _build(http.StatusForbidden, "forbidden", msg...)
31 | }
32 |
33 | // 500
34 | func InternalServerError(msg ...string) Error {
35 | return _build(http.StatusInternalServerError, "internal server error", msg...)
36 | }
37 |
38 | func _build(code int, defval string, custom ...string) Error {
39 | msg := defval
40 | if len(custom) > 0 {
41 | msg = custom[0]
42 | }
43 | return Error{
44 | Code: code,
45 | Msg: msg,
46 | }
47 | }
48 |
49 | func MaybePanic(err error) {
50 | _, whichFile, line, _ := runtime.Caller(1)
51 | arr := strings.Split(whichFile, "/")
52 | file := arr[len(arr)-1]
53 | t := time.Unix(time.Now().Unix(), 0).Format("2006-01-02 15:04:05")
54 |
55 | if err != nil {
56 | panic(Error{Msg: err.Error(), Time: t, File: file, Line: line})
57 | }
58 | }
59 |
60 | func Panic(msg string) {
61 | _, whichFile, line, _ := runtime.Caller(1)
62 | arr := strings.Split(whichFile, "/")
63 | file := arr[len(arr)-1]
64 | t := time.Unix(time.Now().Unix(), 0).Format("2006-01-02 15:04:05")
65 |
66 | panic(Error{Msg: msg, Time: t, File: file, Line: line})
67 | }
68 |
--------------------------------------------------------------------------------
/http/helper/helper.go:
--------------------------------------------------------------------------------
1 | package helper
2 |
3 | func Example() string {
4 | return "good luck"
5 | }
6 |
--------------------------------------------------------------------------------
/http/http.go:
--------------------------------------------------------------------------------
1 | package http
2 |
3 | import (
4 | "github.com/codegangsta/negroni"
5 | "github.com/gorilla/mux"
6 |
7 | "github.com/710leo/Toruk/g"
8 | "github.com/710leo/Toruk/http/cookie"
9 | "github.com/710leo/Toruk/http/middleware"
10 | "github.com/710leo/Toruk/http/render"
11 | )
12 |
13 | func Start() {
14 | render.Init()
15 | cookie.Init()
16 |
17 | r := mux.NewRouter().StrictSlash(false)
18 | ConfigRouter(r)
19 |
20 | n := negroni.New()
21 |
22 | if g.Config().Debug {
23 | n.Use(middleware.NewLogger())
24 | }
25 |
26 | n.Use(middleware.NewRecovery())
27 | n.UseHandler(r)
28 | n.Run(g.Config().Http.Listen)
29 | }
30 |
--------------------------------------------------------------------------------
/http/middleware/logger.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | "log"
5 | "net/http"
6 | "os"
7 | "time"
8 |
9 | "github.com/codegangsta/negroni"
10 | )
11 |
12 | // Logger is a middleware handler that logs the request as it goes in and the response as it goes out.
13 | type Logger struct {
14 | // Logger inherits from log.Logger used to log messages with the Logger middleware
15 | *log.Logger
16 | }
17 |
18 | // NewLogger returns a new Logger instance
19 | func NewLogger() *Logger {
20 | return &Logger{log.New(os.Stdout, "", 0)}
21 | }
22 |
23 | func (l *Logger) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
24 | start := time.Now()
25 | l.Printf("%v %s %s %s", time.Now().Format("2006/01/02 15:04:05"), r.Method, r.URL.Path, r.RemoteAddr)
26 |
27 | next(rw, r)
28 |
29 | res := rw.(negroni.ResponseWriter)
30 | l.Printf("%v %v %s in %v", time.Now().Format("2006/01/02 15:04:05"), res.Status(), http.StatusText(res.Status()), time.Since(start))
31 | }
32 |
--------------------------------------------------------------------------------
/http/middleware/recovery.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | "fmt"
5 | "log"
6 | "net/http"
7 | "os"
8 | "runtime"
9 |
10 | "github.com/710leo/Toruk/http/errors"
11 | "github.com/710leo/Toruk/http/render"
12 | )
13 |
14 | // Recovery is a Negroni middleware that recovers from any panics and writes a 500 if there was one.
15 | type Recovery struct {
16 | Logger *log.Logger
17 | PrintStack bool
18 | StackAll bool
19 | StackSize int
20 | }
21 |
22 | // NewRecovery returns a new instance of Recovery
23 | func NewRecovery() *Recovery {
24 | return &Recovery{
25 | Logger: log.New(os.Stdout, "[panic] ", 0),
26 | PrintStack: true,
27 | StackAll: false,
28 | StackSize: 1024 * 8,
29 | }
30 | }
31 |
32 | func (rec *Recovery) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
33 | defer func() {
34 | if err := recover(); err != nil {
35 | if customError, ok := err.(errors.Error); ok {
36 | if isAjax(r) {
37 | render.Message(w, customError.Msg)
38 | log.Printf("[%s:%d] %s [Error:]%s", customError.File, customError.Line, customError.Time, customError.Msg)
39 | return
40 | }
41 |
42 | if customError.Code == http.StatusUnauthorized || customError.Code == http.StatusForbidden {
43 | http.Redirect(w, r, "/", 302)
44 | return
45 | }
46 |
47 | render.Put(r, "Error", customError.Msg)
48 | render.HTML(r, w, "inc/error")
49 | return
50 | }
51 |
52 | // Negroni part
53 | w.WriteHeader(http.StatusInternalServerError)
54 | stack := make([]byte, rec.StackSize)
55 | stack = stack[:runtime.Stack(stack, rec.StackAll)]
56 |
57 | f := "PANIC: %s\n%s"
58 | log.Printf(f, err, stack)
59 |
60 | if rec.PrintStack {
61 | fmt.Fprintf(w, f, err, stack)
62 | }
63 | }
64 | }()
65 |
66 | next(w, r)
67 | }
68 |
69 | func isAjax(r *http.Request) bool {
70 | return r.Header.Get("X-Requested-With") == "XMLHttpRequest"
71 | }
72 |
--------------------------------------------------------------------------------
/http/param/param.go:
--------------------------------------------------------------------------------
1 | package param
2 |
3 | import (
4 | "fmt"
5 | "net/http"
6 | "strconv"
7 | "strings"
8 |
9 | "github.com/710leo/Toruk/http/errors"
10 | )
11 |
12 | func String(r *http.Request, key string, defVal string) string {
13 | if val, ok := r.URL.Query()[key]; ok {
14 | if val[0] == "" {
15 | return defVal
16 | }
17 | return strings.TrimSpace(val[0])
18 | }
19 |
20 | if r.Form == nil {
21 | err := r.ParseForm()
22 | if err != nil {
23 | panic(errors.BadRequestError())
24 | }
25 | }
26 |
27 | val := r.Form.Get(key)
28 | if val == "" {
29 | return defVal
30 | }
31 |
32 | return strings.TrimSpace(val)
33 | }
34 |
35 | func MustString(r *http.Request, key string, displayName ...string) string {
36 | val := String(r, key, "")
37 | if val == "" {
38 | name := key
39 | if len(displayName) > 0 {
40 | name = displayName[0]
41 | }
42 | panic(errors.BadRequestError(fmt.Sprintf("%s is necessary", name)))
43 | }
44 | return val
45 | }
46 |
47 | func Int64(r *http.Request, key string, defVal int64) int64 {
48 | raw := String(r, key, "")
49 | if raw == "" {
50 | return defVal
51 | }
52 |
53 | val, err := strconv.ParseInt(raw, 10, 64)
54 | if err != nil {
55 | return defVal
56 | }
57 |
58 | return val
59 | }
60 |
61 | func MustInt64(r *http.Request, key string, displayName ...string) int64 {
62 | raw := String(r, key, "")
63 | if raw == "" {
64 | name := key
65 | if len(displayName) > 0 {
66 | name = displayName[0]
67 | }
68 | panic(errors.BadRequestError(fmt.Sprintf("%s is necessary", name)))
69 | }
70 |
71 | val, err := strconv.ParseInt(raw, 10, 64)
72 | if err != nil {
73 | panic(errors.BadRequestError())
74 | }
75 |
76 | return val
77 | }
78 |
79 | func Int(r *http.Request, key string, defVal int) int {
80 | raw := String(r, key, "")
81 | if raw == "" {
82 | return defVal
83 | }
84 |
85 | val, err := strconv.Atoi(raw)
86 | if err != nil {
87 | return defVal
88 | }
89 |
90 | return val
91 | }
92 |
93 | func MustInt(r *http.Request, key string, displayName ...string) int {
94 | name := key
95 | if len(displayName) > 0 {
96 | name = displayName[0]
97 | }
98 |
99 | raw := String(r, key, "")
100 | if raw == "" {
101 | panic(errors.BadRequestError(fmt.Sprintf("%s is necessary", name)))
102 | }
103 |
104 | val, err := strconv.Atoi(raw)
105 | if err != nil {
106 | panic(errors.BadRequestError(fmt.Sprintf("%s should be integer", name)))
107 | }
108 |
109 | return val
110 | }
111 |
112 | func Float64(r *http.Request, key string, defVal float64) float64 {
113 | raw := String(r, key, "")
114 | if raw == "" {
115 | return defVal
116 | }
117 |
118 | val, err := strconv.ParseFloat(raw, 64)
119 | if err != nil {
120 | return defVal
121 | }
122 |
123 | return val
124 | }
125 |
126 | func MustFloat64(r *http.Request, key string, displayName ...string) float64 {
127 | raw := String(r, key, "")
128 | if raw == "" {
129 | name := key
130 | if len(displayName) > 0 {
131 | name = displayName[0]
132 | }
133 | panic(errors.BadRequestError(fmt.Sprintf("%s is necessary", name)))
134 | }
135 |
136 | val, err := strconv.ParseFloat(raw, 64)
137 | if err != nil {
138 | panic(errors.BadRequestError())
139 | }
140 |
141 | return val
142 | }
143 |
144 | func Bool(r *http.Request, key string, defVal bool) bool {
145 | raw := String(r, key, "")
146 | if raw == "true" || raw == "1" || raw == "on" || raw == "checked" || raw == "yes" {
147 | return true
148 | } else if raw == "false" || raw == "0" || raw == "off" || raw == "" || raw == "no" {
149 | return false
150 | } else {
151 | return defVal
152 | }
153 | }
154 |
155 | func MustBool(r *http.Request, key string) bool {
156 | raw := String(r, key, "")
157 | if raw == "true" || raw == "1" || raw == "on" || raw == "checked" || raw == "yes" {
158 | return true
159 | } else if raw == "false" || raw == "0" || raw == "off" || raw == "" || raw == "no" {
160 | return false
161 | } else {
162 | panic(errors.BadRequestError())
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/http/render/render.go:
--------------------------------------------------------------------------------
1 | package render
2 |
3 | import (
4 | "fmt"
5 | "html/template"
6 | "net/http"
7 |
8 | "github.com/gorilla/context"
9 | "github.com/unrolled/render"
10 |
11 | "github.com/710leo/Toruk/g"
12 | "github.com/710leo/Toruk/http/helper"
13 | )
14 |
15 | var Render *render.Render
16 |
17 | var funcMap = template.FuncMap{
18 | "Example": helper.Example,
19 | }
20 |
21 | func Init() {
22 | Render = render.New(render.Options{
23 | Directory: "views",
24 | Extensions: []string{".html"},
25 | Delims: render.Delims{"{{", "}}"},
26 | Funcs: []template.FuncMap{funcMap},
27 | IndentJSON: false,
28 | IsDevelopment: g.Config().Debug,
29 | })
30 | }
31 |
32 | func Put(r *http.Request, key string, val interface{}) {
33 | m, ok := context.GetOk(r, "_DATA_MAP_")
34 | if ok {
35 | mm := m.(map[string]interface{})
36 | mm[key] = val
37 | context.Set(r, "_DATA_MAP_", mm)
38 | } else {
39 | context.Set(r, "_DATA_MAP_", map[string]interface{}{key: val})
40 | }
41 | }
42 |
43 | func HTML(r *http.Request, w http.ResponseWriter, name string, htmlOpt ...render.HTMLOptions) {
44 | Render.HTML(w, http.StatusOK, name, context.Get(r, "_DATA_MAP_"), htmlOpt...)
45 | }
46 |
47 | func Text(w http.ResponseWriter, v string, codes ...int) {
48 | code := http.StatusOK
49 | if len(codes) > 0 {
50 | code = codes[0]
51 | }
52 | Render.Text(w, code, v)
53 | }
54 |
55 | func Error(w http.ResponseWriter, err error) {
56 | msg := ""
57 | if err != nil {
58 | msg = err.Error()
59 | }
60 |
61 | Render.JSON(w, http.StatusOK, map[string]string{"msg": msg})
62 | }
63 |
64 | func Message(w http.ResponseWriter, format string, args ...interface{}) {
65 | Render.JSON(w, http.StatusOK, map[string]string{"msg": fmt.Sprintf(format, args...)})
66 | }
67 |
68 | func Data(w http.ResponseWriter, v interface{}, msg ...string) {
69 | m := ""
70 | if len(msg) > 0 {
71 | m = msg[0]
72 | }
73 |
74 | Render.JSON(w, http.StatusOK, map[string]interface{}{"msg": m, "data": v})
75 | }
76 |
--------------------------------------------------------------------------------
/http/routes.go:
--------------------------------------------------------------------------------
1 | package http
2 |
3 | import (
4 | "fmt"
5 | "net/http"
6 |
7 | "github.com/gorilla/mux"
8 | "github.com/710leo/Toruk/handler"
9 | )
10 |
11 | func ConfigRouter(r *mux.Router) {
12 | configConfRoutes(r)
13 | }
14 |
15 | func configConfRoutes(r *mux.Router) {
16 | r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
17 | fmt.Fprintf(w, "ok")
18 | }).Methods("GET")
19 |
20 | r.HandleFunc("/home", handler.HomeIndex).Methods("GET")
21 | }
22 |
--------------------------------------------------------------------------------
/init:
--------------------------------------------------------------------------------
1 | echo $1;
2 | sed -i "s@github.com/710leo/Toruk@$1@g" `grep -rl "github.com/710leo" *`;
3 | sed -i "s@toruk@$1@g" control;
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "flag"
5 | "fmt"
6 | "log"
7 | "os"
8 | "runtime"
9 |
10 | "github.com/710leo/Toruk/g"
11 | "github.com/710leo/Toruk/http"
12 | )
13 |
14 | func prepare() {
15 | runtime.GOMAXPROCS(runtime.NumCPU())
16 | }
17 |
18 | func init() {
19 | prepare()
20 |
21 | cfg := flag.String("c", "cfg.json", "configuration file")
22 | version := flag.Bool("v", false, "show version")
23 | help := flag.Bool("h", false, "help")
24 | flag.Parse()
25 |
26 | handleVersion(*version)
27 | handleHelp(*help)
28 | handleConfig(*cfg)
29 | }
30 |
31 | func main() {
32 | http.Start()
33 | }
34 |
35 | func handleVersion(displayVersion bool) {
36 | if displayVersion {
37 | fmt.Println(g.VERSION)
38 | os.Exit(0)
39 | }
40 | }
41 |
42 | func handleHelp(displayHelp bool) {
43 | if displayHelp {
44 | flag.Usage()
45 | os.Exit(0)
46 | }
47 | }
48 |
49 | func handleConfig(configFile string) {
50 | err := g.Parse(configFile)
51 | if err != nil {
52 | log.Fatalln(err)
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/model/example.go:
--------------------------------------------------------------------------------
1 | package model
2 |
--------------------------------------------------------------------------------
/store/mysql.go:
--------------------------------------------------------------------------------
1 | package store
2 |
--------------------------------------------------------------------------------
/views/common/error.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |