From c63b43836dd963c74fb839a161dd2491700bda0e Mon Sep 17 00:00:00 2001 From: vCaesar Date: Tue, 10 Jan 2017 20:40:17 +0800 Subject: [PATCH 1/9] Update RESTful --- zh/08.3.md | 48 +++++++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/zh/08.3.md b/zh/08.3.md index 25da1d15..a77fca44 100644 --- a/zh/08.3.md +++ b/zh/08.3.md @@ -68,41 +68,51 @@ Go没有为REST提供直接支持,但是因为RESTful是基于HTTP协议实现 import ( "fmt" - "github.com/drone/routes" + "github.com/julienschmidt/httprouter" + "log" "net/http" ) - func getuser(w http.ResponseWriter, r *http.Request) { - params := r.URL.Query() - uid := params.Get(":uid") + func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + fmt.Fprint(w, "Welcome!\n") + } + + func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name")) + } + + func getuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + uid := ps.ByName("uid") fmt.Fprintf(w, "you are get user %s", uid) } - func modifyuser(w http.ResponseWriter, r *http.Request) { - params := r.URL.Query() - uid := params.Get(":uid") + func modifyuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + uid := ps.ByName("uid") fmt.Fprintf(w, "you are modify user %s", uid) } - func deleteuser(w http.ResponseWriter, r *http.Request) { - params := r.URL.Query() - uid := params.Get(":uid") + func deleteuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + uid := ps.ByName("uid") fmt.Fprintf(w, "you are delete user %s", uid) } - func adduser(w http.ResponseWriter, r *http.Request) { - uid := r.FormValue("uid") + func adduser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + // uid := r.FormValue("uid") + uid := ps.ByName("uid") fmt.Fprintf(w, "you are add user %s", uid) } func main() { - mux := routes.New() - mux.Get("/user/:uid", getuser) - mux.Post("/user/", adduser) - mux.Del("/user/:uid", deleteuser) - mux.Put("/user/:uid", modifyuser) - http.Handle("/", mux) - http.ListenAndServe(":8088", nil) + router := httprouter.New() + router.GET("/", Index) + router.GET("/hello/:name", Hello) + + router.GET("/user/:uid", getuser) + router.POST("/adduser/:uid", adduser) + router.DELETE("/deluser/:uid", deleteuser) + router.PUT("/moduser/:uid", modifyuser) + + log.Fatal(http.ListenAndServe(":8080", router)) } ``` From 260a9552e3c203842ead0d29b54ae3eceaaed4cb Mon Sep 17 00:00:00 2001 From: vCaesar Date: Tue, 10 Jan 2017 20:41:33 +0800 Subject: [PATCH 2/9] Update en RESTful --- en/08.3.md | 55 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/en/08.3.md b/en/08.3.md index 3a337dfc..a2895036 100644 --- a/en/08.3.md +++ b/en/08.3.md @@ -68,48 +68,61 @@ The picture above shows three levels that are currently implemented in REST. You We can simulate `PUT` and `DELETE` requests by adding a hidden `_method` field in our POST requests, however these requests must be converted on the server side before they are processed. My personal applications use this workflow to implement REST interfaces. Standard RESTful interfaces are easily implemented in Go, as the following example demonstrates: +```Go + package main import ( "fmt" - "github.com/drone/routes" + "github.com/julienschmidt/httprouter" + "log" "net/http" ) - func getuser(w http.ResponseWriter, r *http.Request) { - params := r.URL.Query() - uid := params.Get(":uid") + func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + fmt.Fprint(w, "Welcome!\n") + } + + func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name")) + } + + func getuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + uid := ps.ByName("uid") fmt.Fprintf(w, "you are get user %s", uid) } - func modifyuser(w http.ResponseWriter, r *http.Request) { - params := r.URL.Query() - uid := params.Get(":uid") + func modifyuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + uid := ps.ByName("uid") fmt.Fprintf(w, "you are modify user %s", uid) } - func deleteuser(w http.ResponseWriter, r *http.Request) { - params := r.URL.Query() - uid := params.Get(":uid") + func deleteuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + uid := ps.ByName("uid") fmt.Fprintf(w, "you are delete user %s", uid) } - func adduser(w http.ResponseWriter, r *http.Request) { - params := r.URL.Query() - uid := params.Get(":uid") - fmt.Fprint(w, "you are add user %s", uid) + func adduser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + // uid := r.FormValue("uid") + uid := ps.ByName("uid") + fmt.Fprintf(w, "you are add user %s", uid) } func main() { - mux := routes.New() - mux.Get("/user/:uid", getuser) - mux.Post("/user/:uid", modifyuser) - mux.Del("/user/:uid", deleteuser) - mux.Put("/user/", adduser) - http.Handle("/", mux) - http.ListenAndServe(":8088", nil) + router := httprouter.New() + router.GET("/", Index) + router.GET("/hello/:name", Hello) + + router.GET("/user/:uid", getuser) + router.POST("/adduser/:uid", adduser) + router.DELETE("/deluser/:uid", deleteuser) + router.PUT("/moduser/:uid", modifyuser) + + log.Fatal(http.ListenAndServe(":8080", router)) } +``` + This sample code shows you how to write a very basic REST application. Our resources are users, and we use different functions for different methods. Here, we imported a third-party package called `github.com/drone/routes`. We've already covered how to implement a custom router in previous chapters -the `drone/routes` package implements some very convenient router mapping rules that make it very convenient for implementing RESTful architecture. As you can see, REST requires you to implement different logic for different HTTP methods of the same resource. ## Summary From 25d13e77701d9db75058b759a1d2994648ddcebd Mon Sep 17 00:00:00 2001 From: vCaesar Date: Tue, 10 Jan 2017 20:42:33 +0800 Subject: [PATCH 3/9] Update de RESTful --- de/08.3.md | 55 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/de/08.3.md b/de/08.3.md index 3323135f..4f63a603 100644 --- a/de/08.3.md +++ b/de/08.3.md @@ -68,48 +68,61 @@ The picture above shows three levels that are currently implemented in REST. You We can simulate `PUT` and `DELETE` requests by adding a hidden `_method` field in our POST requests, however these requests must be converted on the server side before they are processed. My personal applications use this workflow to implement REST interfaces. Standard RESTful interfaces are easily implemented in Go, as the following example demonstrates: +```Go + package main import ( "fmt" - "github.com/drone/routes" + "github.com/julienschmidt/httprouter" + "log" "net/http" ) - func getuser(w http.ResponseWriter, r *http.Request) { - params := r.URL.Query() - uid := params.Get(":uid") + func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + fmt.Fprint(w, "Welcome!\n") + } + + func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name")) + } + + func getuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + uid := ps.ByName("uid") fmt.Fprintf(w, "you are get user %s", uid) } - func modifyuser(w http.ResponseWriter, r *http.Request) { - params := r.URL.Query() - uid := params.Get(":uid") + func modifyuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + uid := ps.ByName("uid") fmt.Fprintf(w, "you are modify user %s", uid) } - func deleteuser(w http.ResponseWriter, r *http.Request) { - params := r.URL.Query() - uid := params.Get(":uid") + func deleteuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + uid := ps.ByName("uid") fmt.Fprintf(w, "you are delete user %s", uid) } - func adduser(w http.ResponseWriter, r *http.Request) { - params := r.URL.Query() - uid := params.Get(":uid") - fmt.Fprint(w, "you are add user %s", uid) + func adduser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + // uid := r.FormValue("uid") + uid := ps.ByName("uid") + fmt.Fprintf(w, "you are add user %s", uid) } func main() { - mux := routes.New() - mux.Get("/user/:uid", getuser) - mux.Post("/user/:uid", modifyuser) - mux.Del("/user/:uid", deleteuser) - mux.Put("/user/", adduser) - http.Handle("/", mux) - http.ListenAndServe(":8088", nil) + router := httprouter.New() + router.GET("/", Index) + router.GET("/hello/:name", Hello) + + router.GET("/user/:uid", getuser) + router.POST("/adduser/:uid", adduser) + router.DELETE("/deluser/:uid", deleteuser) + router.PUT("/moduser/:uid", modifyuser) + + log.Fatal(http.ListenAndServe(":8080", router)) } +``` + This sample code shows you how to write a very basic REST application. Our resources are users, and we use different functions for different methods. Here, we imported a third-party package called `github.com/drone/routes`. We've already covered how to implement a custom router in previous chapters -the `drone/routes` package implements some very convenient router mapping rules that make it very convenient for implementing RESTful architecture. As you can see, REST requires you to implement different logic for different HTTP methods of the same resource. ## Summary From 885b1be16be308a39ed6da615533d636a5d26f99 Mon Sep 17 00:00:00 2001 From: vCaesar Date: Tue, 10 Jan 2017 20:46:55 +0800 Subject: [PATCH 4/9] Update other RESTful --- es/08.3.md | 56 +++++++++++++++++++++++++++++++-------------------- ja/08.3.md | 55 +++++++++++++++++++++++++++++++------------------- pt-br/08.3.md | 55 +++++++++++++++++++++++++++++++------------------- 3 files changed, 102 insertions(+), 64 deletions(-) diff --git a/es/08.3.md b/es/08.3.md index 7c6336f9..39bdf2cd 100644 --- a/es/08.3.md +++ b/es/08.3.md @@ -67,48 +67,60 @@ La figura de arriba nos muestra tres niveles actualmente implementados en REST. - Algunos firewalls interceptan peticiones `PUT` y `DELETE` y los clientes tienen `POST` para implementarlos. Los servicios completamente RESTful usan los métodos originales HTTP y los reestablecen. Podemos simular las peticiones `PUT` y `DELETE` agregando un campo oculto llamado `_method` en nuestras peticiones `POST`, sin embargo estas peticiones tienen que ser convertidas en el servidor antes de que puedan ser procesadas. En mis aplicaciones personales, uso este flujo de trabajo para implmentar iterfaces REST. Las interfaces RESTful son fáciles de implementar en Go, como se puede ver en el siguiente ejemplo: -``` + +```Go + package main import ( "fmt" - "github.com/drone/routes" + "github.com/julienschmidt/httprouter" + "log" "net/http" ) - func getuser(w http.ResponseWriter, r *http.Request) { - params := r.URL.Query() - uid := params.Get(":uid") + func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + fmt.Fprint(w, "Welcome!\n") + } + + func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name")) + } + + func getuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + uid := ps.ByName("uid") fmt.Fprintf(w, "you are get user %s", uid) } - func modifyuser(w http.ResponseWriter, r *http.Request) { - params := r.URL.Query() - uid := params.Get(":uid") + func modifyuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + uid := ps.ByName("uid") fmt.Fprintf(w, "you are modify user %s", uid) } - func deleteuser(w http.ResponseWriter, r *http.Request) { - params := r.URL.Query() - uid := params.Get(":uid") + func deleteuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + uid := ps.ByName("uid") fmt.Fprintf(w, "you are delete user %s", uid) } - func adduser(w http.ResponseWriter, r *http.Request) { - params := r.URL.Query() - uid := params.Get(":uid") - fmt.Fprint(w, "you are add user %s", uid) + func adduser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + // uid := r.FormValue("uid") + uid := ps.ByName("uid") + fmt.Fprintf(w, "you are add user %s", uid) } func main() { - mux := routes.New() - mux.Get("/user/:uid", getuser) - mux.Post("/user/:uid", modifyuser) - mux.Del("/user/:uid", deleteuser) - mux.Put("/user/", adduser) - http.Handle("/", mux) - http.ListenAndServe(":8088", nil) + router := httprouter.New() + router.GET("/", Index) + router.GET("/hello/:name", Hello) + + router.GET("/user/:uid", getuser) + router.POST("/adduser/:uid", adduser) + router.DELETE("/deluser/:uid", deleteuser) + router.PUT("/moduser/:uid", modifyuser) + + log.Fatal(http.ListenAndServe(":8080", router)) } + ``` Este ejemplo muestra como puedes escribir aplicaciones REST muy básicas. Nuestros recursos son usuarios y usamos diferentes funciones para diferentes métods. Aquí, importamos un paquete de terceros llamado `github.com/drone/routes`. Ya hemos cubierto como implementar un manejador de rutas personalizado en capítulos anteriores. El paquete `drone/routes` implementa un mapeo de rutas muy conveniente de seguir y muy fácil para implementar arquitecturas REST. Como puedes ver, REST requiere que implementes diferente lógica para cada método HTTP de el mismo recurso. diff --git a/ja/08.3.md b/ja/08.3.md index 9483de75..48ab8cae 100644 --- a/ja/08.3.md +++ b/ja/08.3.md @@ -62,48 +62,61 @@ GoにはRESTに対する直接のサポートはありません。しかし、RE 現在`POST`の中において隠されたフィールドである`_method`を増加するなどの方法で`PUT`、`DELETE`といったメソッドをエミュレートすることができます。しかし、サーバでは変換を行う必要があります。現在私のプロジェクトではこのような方法によってRESTインターフェースを作成しています。当然Go言語では完全にRESTfulに沿った実装を行うのは容易です。下の例を通してどのようにRESTfulなアプリケーションの設計を実現するかご説明しましょう。 +```Go + package main import ( "fmt" - "github.com/drone/routes" + "github.com/julienschmidt/httprouter" + "log" "net/http" ) - func getuser(w http.ResponseWriter, r *http.Request) { - params := r.URL.Query() - uid := params.Get(":uid") + func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + fmt.Fprint(w, "Welcome!\n") + } + + func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name")) + } + + func getuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + uid := ps.ByName("uid") fmt.Fprintf(w, "you are get user %s", uid) } - func modifyuser(w http.ResponseWriter, r *http.Request) { - params := r.URL.Query() - uid := params.Get(":uid") + func modifyuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + uid := ps.ByName("uid") fmt.Fprintf(w, "you are modify user %s", uid) } - func deleteuser(w http.ResponseWriter, r *http.Request) { - params := r.URL.Query() - uid := params.Get(":uid") + func deleteuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + uid := ps.ByName("uid") fmt.Fprintf(w, "you are delete user %s", uid) } - func adduser(w http.ResponseWriter, r *http.Request) { - params := r.URL.Query() - uid := params.Get(":uid") - fmt.Fprint(w, "you are add user %s", uid) + func adduser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + // uid := r.FormValue("uid") + uid := ps.ByName("uid") + fmt.Fprintf(w, "you are add user %s", uid) } func main() { - mux := routes.New() - mux.Get("/user/:uid", getuser) - mux.Post("/user/:uid", modifyuser) - mux.Del("/user/:uid", deleteuser) - mux.Put("/user/", adduser) - http.Handle("/", mux) - http.ListenAndServe(":8088", nil) + router := httprouter.New() + router.GET("/", Index) + router.GET("/hello/:name", Hello) + + router.GET("/user/:uid", getuser) + router.POST("/adduser/:uid", adduser) + router.DELETE("/deluser/:uid", deleteuser) + router.PUT("/moduser/:uid", modifyuser) + + log.Fatal(http.ListenAndServe(":8080", router)) } +``` + 上のコードではどのようにRESTなアプリケーションを書くかご覧いただきました。我々がアクセスするリソースはユーザです。異なるmethodによって異なる関数にアクセスしました。ここではサードパーティライブラリ`github.com/drone/routes`を使用しています。前の章でどのように自分で定義したルータを実現するかご紹介しました。このライブラリは自分で定義したルートと便利なルートのルールを反映させます。これを使って簡単にRESTのフレームワークを実装することができます。 ## まとめ diff --git a/pt-br/08.3.md b/pt-br/08.3.md index 3323135f..4f63a603 100644 --- a/pt-br/08.3.md +++ b/pt-br/08.3.md @@ -68,48 +68,61 @@ The picture above shows three levels that are currently implemented in REST. You We can simulate `PUT` and `DELETE` requests by adding a hidden `_method` field in our POST requests, however these requests must be converted on the server side before they are processed. My personal applications use this workflow to implement REST interfaces. Standard RESTful interfaces are easily implemented in Go, as the following example demonstrates: +```Go + package main import ( "fmt" - "github.com/drone/routes" + "github.com/julienschmidt/httprouter" + "log" "net/http" ) - func getuser(w http.ResponseWriter, r *http.Request) { - params := r.URL.Query() - uid := params.Get(":uid") + func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + fmt.Fprint(w, "Welcome!\n") + } + + func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name")) + } + + func getuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + uid := ps.ByName("uid") fmt.Fprintf(w, "you are get user %s", uid) } - func modifyuser(w http.ResponseWriter, r *http.Request) { - params := r.URL.Query() - uid := params.Get(":uid") + func modifyuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + uid := ps.ByName("uid") fmt.Fprintf(w, "you are modify user %s", uid) } - func deleteuser(w http.ResponseWriter, r *http.Request) { - params := r.URL.Query() - uid := params.Get(":uid") + func deleteuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + uid := ps.ByName("uid") fmt.Fprintf(w, "you are delete user %s", uid) } - func adduser(w http.ResponseWriter, r *http.Request) { - params := r.URL.Query() - uid := params.Get(":uid") - fmt.Fprint(w, "you are add user %s", uid) + func adduser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + // uid := r.FormValue("uid") + uid := ps.ByName("uid") + fmt.Fprintf(w, "you are add user %s", uid) } func main() { - mux := routes.New() - mux.Get("/user/:uid", getuser) - mux.Post("/user/:uid", modifyuser) - mux.Del("/user/:uid", deleteuser) - mux.Put("/user/", adduser) - http.Handle("/", mux) - http.ListenAndServe(":8088", nil) + router := httprouter.New() + router.GET("/", Index) + router.GET("/hello/:name", Hello) + + router.GET("/user/:uid", getuser) + router.POST("/adduser/:uid", adduser) + router.DELETE("/deluser/:uid", deleteuser) + router.PUT("/moduser/:uid", modifyuser) + + log.Fatal(http.ListenAndServe(":8080", router)) } +``` + This sample code shows you how to write a very basic REST application. Our resources are users, and we use different functions for different methods. Here, we imported a third-party package called `github.com/drone/routes`. We've already covered how to implement a custom router in previous chapters -the `drone/routes` package implements some very convenient router mapping rules that make it very convenient for implementing RESTful architecture. As you can see, REST requires you to implement different logic for different HTTP methods of the same resource. ## Summary From 2ba3a76eb1c31af1c2d3fdfcfa918229ccf2b227 Mon Sep 17 00:00:00 2001 From: vCaesar Date: Tue, 10 Jan 2017 20:59:58 +0800 Subject: [PATCH 5/9] Add de redigo demo and update link --- de/05.6.md | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/de/05.6.md b/de/05.6.md index 930dd1e8..64bcc32b 100644 --- a/de/05.6.md +++ b/de/05.6.md @@ -10,10 +10,90 @@ redis is a key-value storage system like Memcached, that supports the string, li There are some Go database drivers for redis: +- [https://github.com/garyburd/redigo](https://github.com/garyburd/redigo) +- [https://github.com/go-redis/redis](https://github.com/go-redis/redis) +- [https://github.com/hoisie/redis](https://github.com/hoisie/redis) - [https://github.com/alphazero/Go-Redis](https://github.com/alphazero/Go-Redis) -- [http://code.google.com/p/tideland-rdc/](http://code.google.com/p/tideland-rdc/) - [https://github.com/simonz05/godis](https://github.com/simonz05/godis) -- [https://github.com/hoisie/redis.go](https://github.com/hoisie/redis.go) + +Let's see how to use the driver that redigo to operate on a database: + +```Go + + package main + + import ( + "fmt" + "github.com/garyburd/redigo/redis" + "os" + "os/signal" + "syscall" + "time" + ) + + var ( + Pool *redis.Pool + ) + + func init() { + redisHost := ":6379" + Pool = newPool(redisHost) + close() + } + + func newPool(server string) *redis.Pool { + + return &redis.Pool{ + + MaxIdle: 3, + IdleTimeout: 240 * time.Second, + + Dial: func() (redis.Conn, error) { + c, err := redis.Dial("tcp", server) + if err != nil { + return nil, err + } + return c, err + }, + + TestOnBorrow: func(c redis.Conn, t time.Time) error { + _, err := c.Do("PING") + return err + }, + } + } + + func close() { + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt) + signal.Notify(c, syscall.SIGTERM) + signal.Notify(c, syscall.SIGKILL) + go func() { + <-c + Pool.Close() + os.Exit(0) + }() + } + + func Get(key string) ([]byte, error) { + + conn := Pool.Get() + defer conn.Close() + + var data []byte + data, err := redis.Bytes(conn.Do("GET", key)) + if err != nil { + return data, fmt.Errorf("error get key %s: %v", key, err) + } + return data, err + } + + func main() { + test, err := Get("test") + fmt.Println(test, err) + } + +``` I forked the last of these packages, fixed some bugs, and used it in my short URL service (2 million PV every day). From 030a8f759dd00a78100311d913bd0adc1574c7fd Mon Sep 17 00:00:00 2001 From: vCaesar Date: Tue, 10 Jan 2017 21:03:59 +0800 Subject: [PATCH 6/9] Add other redigo demo --- es/05.6.md | 85 +++++++++++++++++++++++++++++++++++++++++++++++-- ja/05.6.md | 88 ++++++++++++++++++++++++++++++++++++++++++++++++--- pt-br/05.6.md | 85 +++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 248 insertions(+), 10 deletions(-) diff --git a/es/05.6.md b/es/05.6.md index 3a1096ba..fdf6b552 100644 --- a/es/05.6.md +++ b/es/05.6.md @@ -9,11 +9,90 @@ Al ser el lenguaje C del siglo XXI, Go tiene soporte para bases de datos NoSQL, redis es un sistema de almacenamiento llave valor como Memcached, que soporta los tipos de cadenas, listas conjuntos y conjuntos ordenados. Aquí están algunos de los manejadores de bases de datos para redis: - +- [https://github.com/garyburd/redigo](https://github.com/garyburd/redigo) +- [https://github.com/go-redis/redis](https://github.com/go-redis/redis) +- [https://github.com/hoisie/redis](https://github.com/hoisie/redis) - [https://github.com/alphazero/Go-Redis](https://github.com/alphazero/Go-Redis) -- [http://code.google.com/p/tideland-rdc/](http://code.google.com/p/tideland-rdc/) - [https://github.com/simonz05/godis](https://github.com/simonz05/godis) -- [https://github.com/hoisie/redis.go](https://github.com/hoisie/redis.go) + +Let's see how to use the driver that redigo to operate on a database: + +```Go + + package main + + import ( + "fmt" + "github.com/garyburd/redigo/redis" + "os" + "os/signal" + "syscall" + "time" + ) + + var ( + Pool *redis.Pool + ) + + func init() { + redisHost := ":6379" + Pool = newPool(redisHost) + close() + } + + func newPool(server string) *redis.Pool { + + return &redis.Pool{ + + MaxIdle: 3, + IdleTimeout: 240 * time.Second, + + Dial: func() (redis.Conn, error) { + c, err := redis.Dial("tcp", server) + if err != nil { + return nil, err + } + return c, err + }, + + TestOnBorrow: func(c redis.Conn, t time.Time) error { + _, err := c.Do("PING") + return err + }, + } + } + + func close() { + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt) + signal.Notify(c, syscall.SIGTERM) + signal.Notify(c, syscall.SIGKILL) + go func() { + <-c + Pool.Close() + os.Exit(0) + }() + } + + func Get(key string) ([]byte, error) { + + conn := Pool.Get() + defer conn.Close() + + var data []byte + data, err := redis.Bytes(conn.Do("GET", key)) + if err != nil { + return data, fmt.Errorf("error get key %s: %v", key, err) + } + return data, err + } + + func main() { + test, err := Get("test") + fmt.Println(test, err) + } + +``` Realicé una bifurcación de el último de estos paquetes, arreglé algunos servicios y lo usé en mi sistema de acortado de urls (2 millones de peticiones por día). diff --git a/ja/05.6.md b/ja/05.6.md index e59e6f4a..ed2b8895 100644 --- a/ja/05.6.md +++ b/ja/05.6.md @@ -9,10 +9,90 @@ redisはkey-valueを保存するシステムです。Memcachedに似ていて、 現在redisが最もよく使われているのは新浪のマイクロブログプラットフォームでしょう。その次にFacebookに買収された画像フォーラムであるinstagramがあります。その他有名な[インターネット企業](http://redis.io/topics/whos-using-redis)もそうです。 Goは現在redisのドライバで以下をサポートしています -- https://github.com/alphazero/Go-Redis -- http://code.google.com/p/tideland-rdc/ -- https://github.com/simonz05/godis -- https://github.com/hoisie/redis.go +- [https://github.com/garyburd/redigo](https://github.com/garyburd/redigo) +- [https://github.com/go-redis/redis](https://github.com/go-redis/redis) +- [https://github.com/hoisie/redis](https://github.com/hoisie/redis) +- [https://github.com/alphazero/Go-Redis](https://github.com/alphazero/Go-Redis) +- [https://github.com/simonz05/godis](https://github.com/simonz05/godis) + +Let's see how to use the driver that redigo to operate on a database: + +```Go + + package main + + import ( + "fmt" + "github.com/garyburd/redigo/redis" + "os" + "os/signal" + "syscall" + "time" + ) + + var ( + Pool *redis.Pool + ) + + func init() { + redisHost := ":6379" + Pool = newPool(redisHost) + close() + } + + func newPool(server string) *redis.Pool { + + return &redis.Pool{ + + MaxIdle: 3, + IdleTimeout: 240 * time.Second, + + Dial: func() (redis.Conn, error) { + c, err := redis.Dial("tcp", server) + if err != nil { + return nil, err + } + return c, err + }, + + TestOnBorrow: func(c redis.Conn, t time.Time) error { + _, err := c.Do("PING") + return err + }, + } + } + + func close() { + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt) + signal.Notify(c, syscall.SIGTERM) + signal.Notify(c, syscall.SIGKILL) + go func() { + <-c + Pool.Close() + os.Exit(0) + }() + } + + func Get(key string) ([]byte, error) { + + conn := Pool.Get() + defer conn.Close() + + var data []byte + data, err := redis.Bytes(conn.Do("GET", key)) + if err != nil { + return data, fmt.Errorf("error get key %s: %v", key, err) + } + return data, err + } + + func main() { + test, err := Get("test") + fmt.Println(test, err) + } + +``` 現在私がforkした最新のドライバではいくつかのbugが修正されています。現在私自身の短縮ドメイン名サービスのプロジェクトの中で使用されています。(毎日200WぐらいのPV数があります。) diff --git a/pt-br/05.6.md b/pt-br/05.6.md index ab798a70..0cf7e599 100644 --- a/pt-br/05.6.md +++ b/pt-br/05.6.md @@ -9,11 +9,90 @@ As the C language of the 21st century, Go has good support for NoSQL databases, redis is a key-value storage system like Memcached, that supports the string, list, set and zset(ordered set) value types. There are some Go database drivers for redis: - +- [https://github.com/garyburd/redigo](https://github.com/garyburd/redigo) +- [https://github.com/go-redis/redis](https://github.com/go-redis/redis) +- [https://github.com/hoisie/redis](https://github.com/hoisie/redis) - [https://github.com/alphazero/Go-Redis](https://github.com/alphazero/Go-Redis) -- [http://code.google.com/p/tideland-rdc/](http://code.google.com/p/tideland-rdc/) - [https://github.com/simonz05/godis](https://github.com/simonz05/godis) -- [https://github.com/hoisie/redis.go](https://github.com/hoisie/redis.go) + +Let's see how to use the driver that redigo to operate on a database: + +```Go + + package main + + import ( + "fmt" + "github.com/garyburd/redigo/redis" + "os" + "os/signal" + "syscall" + "time" + ) + + var ( + Pool *redis.Pool + ) + + func init() { + redisHost := ":6379" + Pool = newPool(redisHost) + close() + } + + func newPool(server string) *redis.Pool { + + return &redis.Pool{ + + MaxIdle: 3, + IdleTimeout: 240 * time.Second, + + Dial: func() (redis.Conn, error) { + c, err := redis.Dial("tcp", server) + if err != nil { + return nil, err + } + return c, err + }, + + TestOnBorrow: func(c redis.Conn, t time.Time) error { + _, err := c.Do("PING") + return err + }, + } + } + + func close() { + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt) + signal.Notify(c, syscall.SIGTERM) + signal.Notify(c, syscall.SIGKILL) + go func() { + <-c + Pool.Close() + os.Exit(0) + }() + } + + func Get(key string) ([]byte, error) { + + conn := Pool.Get() + defer conn.Close() + + var data []byte + data, err := redis.Bytes(conn.Do("GET", key)) + if err != nil { + return data, fmt.Errorf("error get key %s: %v", key, err) + } + return data, err + } + + func main() { + test, err := Get("test") + fmt.Println(test, err) + } + +``` I forked the last of these packages, fixed some bugs, and used it in my short URL service (2 million PV every day). From 1b079e856ad9cc8278ee3c11382fd506e1616e8c Mon Sep 17 00:00:00 2001 From: vCaesar Date: Tue, 10 Jan 2017 21:38:47 +0800 Subject: [PATCH 7/9] Update introduce --- en/08.3.md | 2 +- zh/08.3.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/en/08.3.md b/en/08.3.md index a2895036..92787090 100644 --- a/en/08.3.md +++ b/en/08.3.md @@ -123,7 +123,7 @@ We can simulate `PUT` and `DELETE` requests by adding a hidden `_method` field i ``` -This sample code shows you how to write a very basic REST application. Our resources are users, and we use different functions for different methods. Here, we imported a third-party package called `github.com/drone/routes`. We've already covered how to implement a custom router in previous chapters -the `drone/routes` package implements some very convenient router mapping rules that make it very convenient for implementing RESTful architecture. As you can see, REST requires you to implement different logic for different HTTP methods of the same resource. +This sample code shows you how to write a very basic REST application. Our resources are users, and we use different functions for different methods. Here, we imported a third-party package called `github.com/julienschmidt/httprouter`. We've already covered how to implement a custom router in previous chapters -the `julienschmidt/httprouter` package implements some very convenient router mapping rules that make it very convenient for implementing RESTful architecture. As you can see, REST requires you to implement different logic for different HTTP methods of the same resource. ## Summary diff --git a/zh/08.3.md b/zh/08.3.md index a77fca44..d08c09a2 100644 --- a/zh/08.3.md +++ b/zh/08.3.md @@ -116,7 +116,7 @@ Go没有为REST提供直接支持,但是因为RESTful是基于HTTP协议实现 } ``` -上面的代码演示了如何编写一个REST的应用,我们访问的资源是用户,我们通过不同的method来访问不同的函数,这里使用了第三方库`github.com/drone/routes`,在前面章节我们介绍过如何实现自定义的路由器,这个库实现了自定义路由和方便的路由规则映射,通过它,我们可以很方便的实现REST的架构。通过上面的代码可知,REST就是根据不同的method访问同一个资源的时候实现不同的逻辑处理。 +上面的代码演示了如何编写一个REST的应用,我们访问的资源是用户,我们通过不同的method来访问不同的函数,这里使用了第三方库`github.com/julienschmidt/httprouter`,在前面章节我们介绍过如何实现自定义的路由器,这个库实现了自定义路由和方便的路由规则映射,通过它,我们可以很方便的实现REST的架构。通过上面的代码可知,REST就是根据不同的method访问同一个资源的时候实现不同的逻辑处理。 ## 总结 REST是一种架构风格,汲取了WWW的成功经验:无状态,以资源为中心,充分利用HTTP协议和URI协议,提供统一的接口定义,使得它作为一种设计Web服务的方法而变得流行。在某种意义上,通过强调URI和HTTP等早期Internet标准,REST是对大型应用程序服务器时代之前的Web方式的回归。目前Go对于REST的支持还是很简单的,通过实现自定义的路由规则,我们就可以为不同的method实现不同的handle,这样就实现了REST的架构。 From 85d0f7f3bf378b05e2cd2f8cd9d427a830a32ba5 Mon Sep 17 00:00:00 2001 From: vCaesar Date: Tue, 10 Jan 2017 21:41:33 +0800 Subject: [PATCH 8/9] Update router introduce --- de/08.3.md | 2 +- es/08.3.md | 2 +- ja/08.3.md | 2 +- pt-br/08.3.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/de/08.3.md b/de/08.3.md index 4f63a603..29c443aa 100644 --- a/de/08.3.md +++ b/de/08.3.md @@ -123,7 +123,7 @@ We can simulate `PUT` and `DELETE` requests by adding a hidden `_method` field i ``` -This sample code shows you how to write a very basic REST application. Our resources are users, and we use different functions for different methods. Here, we imported a third-party package called `github.com/drone/routes`. We've already covered how to implement a custom router in previous chapters -the `drone/routes` package implements some very convenient router mapping rules that make it very convenient for implementing RESTful architecture. As you can see, REST requires you to implement different logic for different HTTP methods of the same resource. +This sample code shows you how to write a very basic REST application. Our resources are users, and we use different functions for different methods. Here, we imported a third-party package called `github.com/julienschmidt/httprouter`. We've already covered how to implement a custom router in previous chapters -the `julienschmidt/httprouter` package implements some very convenient router mapping rules that make it very convenient for implementing RESTful architecture. As you can see, REST requires you to implement different logic for different HTTP methods of the same resource. ## Summary diff --git a/es/08.3.md b/es/08.3.md index 39bdf2cd..ecc9d8e6 100644 --- a/es/08.3.md +++ b/es/08.3.md @@ -122,7 +122,7 @@ Podemos simular las peticiones `PUT` y `DELETE` agregando un campo oculto llamad } ``` -Este ejemplo muestra como puedes escribir aplicaciones REST muy básicas. Nuestros recursos son usuarios y usamos diferentes funciones para diferentes métods. Aquí, importamos un paquete de terceros llamado `github.com/drone/routes`. Ya hemos cubierto como implementar un manejador de rutas personalizado en capítulos anteriores. El paquete `drone/routes` implementa un mapeo de rutas muy conveniente de seguir y muy fácil para implementar arquitecturas REST. Como puedes ver, REST requiere que implementes diferente lógica para cada método HTTP de el mismo recurso. +Este ejemplo muestra como puedes escribir aplicaciones REST muy básicas. Nuestros recursos son usuarios y usamos diferentes funciones para diferentes métods. Aquí, importamos un paquete de terceros llamado `github.com/julienschmidt/httprouter`. Ya hemos cubierto como implementar un manejador de rutas personalizado en capítulos anteriores. El paquete `julienschmidt/httprouter` implementa un mapeo de rutas muy conveniente de seguir y muy fácil para implementar arquitecturas REST. Como puedes ver, REST requiere que implementes diferente lógica para cada método HTTP de el mismo recurso. ## Resumen diff --git a/ja/08.3.md b/ja/08.3.md index 48ab8cae..b3b1b250 100644 --- a/ja/08.3.md +++ b/ja/08.3.md @@ -117,7 +117,7 @@ GoにはRESTに対する直接のサポートはありません。しかし、RE ``` -上のコードではどのようにRESTなアプリケーションを書くかご覧いただきました。我々がアクセスするリソースはユーザです。異なるmethodによって異なる関数にアクセスしました。ここではサードパーティライブラリ`github.com/drone/routes`を使用しています。前の章でどのように自分で定義したルータを実現するかご紹介しました。このライブラリは自分で定義したルートと便利なルートのルールを反映させます。これを使って簡単にRESTのフレームワークを実装することができます。 +上のコードではどのようにRESTなアプリケーションを書くかご覧いただきました。我々がアクセスするリソースはユーザです。異なるmethodによって異なる関数にアクセスしました。ここではサードパーティライブラリ`github.com/julienschmidt/httprouter`を使用しています。前の章でどのように自分で定義したルータを実現するかご紹介しました。このライブラリは自分で定義したルートと便利なルートのルールを反映させます。これを使って簡単にRESTのフレームワークを実装することができます。 ## まとめ RESTはフレームワークスタイルの一種です。WWWの成功経験を汲み取っています:ステートレス、リソースを中心とし、HTTPプロトコルとURIプロトコルを十分利用しています。統一したインターフェース定義を提供し、Webサービスを設計する方法の一つとして流行しました。ある意味でURIとHTTPといった黎明期のInternet標準を強調することで、RESTは大型のアプリケーションプログラムサーバ時代の前のWeb方式に回帰しています。今のところGoのRESTに対するサポートはまだシンプルです。自分で定義したルーティングを通して、異なるmethodに異なるhandleを実装することができます。このようにRESTのフレームワークは実現されています。 diff --git a/pt-br/08.3.md b/pt-br/08.3.md index 4f63a603..29c443aa 100644 --- a/pt-br/08.3.md +++ b/pt-br/08.3.md @@ -123,7 +123,7 @@ We can simulate `PUT` and `DELETE` requests by adding a hidden `_method` field i ``` -This sample code shows you how to write a very basic REST application. Our resources are users, and we use different functions for different methods. Here, we imported a third-party package called `github.com/drone/routes`. We've already covered how to implement a custom router in previous chapters -the `drone/routes` package implements some very convenient router mapping rules that make it very convenient for implementing RESTful architecture. As you can see, REST requires you to implement different logic for different HTTP methods of the same resource. +This sample code shows you how to write a very basic REST application. Our resources are users, and we use different functions for different methods. Here, we imported a third-party package called `github.com/julienschmidt/httprouter`. We've already covered how to implement a custom router in previous chapters -the `julienschmidt/httprouter` package implements some very convenient router mapping rules that make it very convenient for implementing RESTful architecture. As you can see, REST requires you to implement different logic for different HTTP methods of the same resource. ## Summary From b7d9bf8e73f18c95b9f85d60fa635a0fe40c021f Mon Sep 17 00:00:00 2001 From: vCaesar Date: Tue, 10 Jan 2017 22:06:44 +0800 Subject: [PATCH 9/9] Add See Contributors --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index ac82c383..9ed5cd56 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,10 @@ QQ群:148647580 BBS:[http://golanghome.com/](http://gocn.io/) +##Contributors + +- See [contributors page](https://github.com/astaxie/build-web-application-with-golang/graphs/contributors) for full list of contributors. + ## Acknowledgments - [四月份平民](https://plus.google.com/110445767383269817959) (review代码)