@@ -21,6 +21,10 @@ QQ群:148647580
|
|||||||
|
|
||||||
BBS:[http://golanghome.com/](http://gocn.io/)
|
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
|
## Acknowledgments
|
||||||
|
|
||||||
- [四月份平民](https://plus.google.com/110445767383269817959) (review代码)
|
- [四月份平民](https://plus.google.com/110445767383269817959) (review代码)
|
||||||
|
|||||||
84
de/05.6.md
84
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:
|
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)
|
- [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/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).
|
I forked the last of these packages, fixed some bugs, and used it in my short URL service (2 million PV every day).
|
||||||
|
|
||||||
|
|||||||
57
de/08.3.md
57
de/08.3.md
@@ -68,49 +68,62 @@ 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:
|
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
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/drone/routes"
|
"github.com/julienschmidt/httprouter"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getuser(w http.ResponseWriter, r *http.Request) {
|
func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||||
params := r.URL.Query()
|
fmt.Fprint(w, "Welcome!\n")
|
||||||
uid := params.Get(":uid")
|
}
|
||||||
|
|
||||||
|
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)
|
fmt.Fprintf(w, "you are get user %s", uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func modifyuser(w http.ResponseWriter, r *http.Request) {
|
func modifyuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
params := r.URL.Query()
|
uid := ps.ByName("uid")
|
||||||
uid := params.Get(":uid")
|
|
||||||
fmt.Fprintf(w, "you are modify user %s", uid)
|
fmt.Fprintf(w, "you are modify user %s", uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteuser(w http.ResponseWriter, r *http.Request) {
|
func deleteuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
params := r.URL.Query()
|
uid := ps.ByName("uid")
|
||||||
uid := params.Get(":uid")
|
|
||||||
fmt.Fprintf(w, "you are delete user %s", uid)
|
fmt.Fprintf(w, "you are delete user %s", uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func adduser(w http.ResponseWriter, r *http.Request) {
|
func adduser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
params := r.URL.Query()
|
// uid := r.FormValue("uid")
|
||||||
uid := params.Get(":uid")
|
uid := ps.ByName("uid")
|
||||||
fmt.Fprint(w, "you are add user %s", uid)
|
fmt.Fprintf(w, "you are add user %s", uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
mux := routes.New()
|
router := httprouter.New()
|
||||||
mux.Get("/user/:uid", getuser)
|
router.GET("/", Index)
|
||||||
mux.Post("/user/:uid", modifyuser)
|
router.GET("/hello/:name", Hello)
|
||||||
mux.Del("/user/:uid", deleteuser)
|
|
||||||
mux.Put("/user/", adduser)
|
router.GET("/user/:uid", getuser)
|
||||||
http.Handle("/", mux)
|
router.POST("/adduser/:uid", adduser)
|
||||||
http.ListenAndServe(":8088", nil)
|
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.
|
```
|
||||||
|
|
||||||
|
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
|
## Summary
|
||||||
|
|
||||||
|
|||||||
57
en/08.3.md
57
en/08.3.md
@@ -68,49 +68,62 @@ 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:
|
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
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/drone/routes"
|
"github.com/julienschmidt/httprouter"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getuser(w http.ResponseWriter, r *http.Request) {
|
func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||||
params := r.URL.Query()
|
fmt.Fprint(w, "Welcome!\n")
|
||||||
uid := params.Get(":uid")
|
}
|
||||||
|
|
||||||
|
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)
|
fmt.Fprintf(w, "you are get user %s", uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func modifyuser(w http.ResponseWriter, r *http.Request) {
|
func modifyuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
params := r.URL.Query()
|
uid := ps.ByName("uid")
|
||||||
uid := params.Get(":uid")
|
|
||||||
fmt.Fprintf(w, "you are modify user %s", uid)
|
fmt.Fprintf(w, "you are modify user %s", uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteuser(w http.ResponseWriter, r *http.Request) {
|
func deleteuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
params := r.URL.Query()
|
uid := ps.ByName("uid")
|
||||||
uid := params.Get(":uid")
|
|
||||||
fmt.Fprintf(w, "you are delete user %s", uid)
|
fmt.Fprintf(w, "you are delete user %s", uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func adduser(w http.ResponseWriter, r *http.Request) {
|
func adduser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
params := r.URL.Query()
|
// uid := r.FormValue("uid")
|
||||||
uid := params.Get(":uid")
|
uid := ps.ByName("uid")
|
||||||
fmt.Fprint(w, "you are add user %s", uid)
|
fmt.Fprintf(w, "you are add user %s", uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
mux := routes.New()
|
router := httprouter.New()
|
||||||
mux.Get("/user/:uid", getuser)
|
router.GET("/", Index)
|
||||||
mux.Post("/user/:uid", modifyuser)
|
router.GET("/hello/:name", Hello)
|
||||||
mux.Del("/user/:uid", deleteuser)
|
|
||||||
mux.Put("/user/", adduser)
|
router.GET("/user/:uid", getuser)
|
||||||
http.Handle("/", mux)
|
router.POST("/adduser/:uid", adduser)
|
||||||
http.ListenAndServe(":8088", nil)
|
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.
|
```
|
||||||
|
|
||||||
|
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
|
## Summary
|
||||||
|
|
||||||
|
|||||||
85
es/05.6.md
85
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.
|
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:
|
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)
|
- [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/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).
|
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).
|
||||||
|
|
||||||
|
|||||||
58
es/08.3.md
58
es/08.3.md
@@ -67,50 +67,62 @@ 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.
|
- 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:
|
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
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/drone/routes"
|
"github.com/julienschmidt/httprouter"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getuser(w http.ResponseWriter, r *http.Request) {
|
func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||||
params := r.URL.Query()
|
fmt.Fprint(w, "Welcome!\n")
|
||||||
uid := params.Get(":uid")
|
}
|
||||||
|
|
||||||
|
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)
|
fmt.Fprintf(w, "you are get user %s", uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func modifyuser(w http.ResponseWriter, r *http.Request) {
|
func modifyuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
params := r.URL.Query()
|
uid := ps.ByName("uid")
|
||||||
uid := params.Get(":uid")
|
|
||||||
fmt.Fprintf(w, "you are modify user %s", uid)
|
fmt.Fprintf(w, "you are modify user %s", uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteuser(w http.ResponseWriter, r *http.Request) {
|
func deleteuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
params := r.URL.Query()
|
uid := ps.ByName("uid")
|
||||||
uid := params.Get(":uid")
|
|
||||||
fmt.Fprintf(w, "you are delete user %s", uid)
|
fmt.Fprintf(w, "you are delete user %s", uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func adduser(w http.ResponseWriter, r *http.Request) {
|
func adduser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
params := r.URL.Query()
|
// uid := r.FormValue("uid")
|
||||||
uid := params.Get(":uid")
|
uid := ps.ByName("uid")
|
||||||
fmt.Fprint(w, "you are add user %s", uid)
|
fmt.Fprintf(w, "you are add user %s", uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
mux := routes.New()
|
router := httprouter.New()
|
||||||
mux.Get("/user/:uid", getuser)
|
router.GET("/", Index)
|
||||||
mux.Post("/user/:uid", modifyuser)
|
router.GET("/hello/:name", Hello)
|
||||||
mux.Del("/user/:uid", deleteuser)
|
|
||||||
mux.Put("/user/", adduser)
|
router.GET("/user/:uid", getuser)
|
||||||
http.Handle("/", mux)
|
router.POST("/adduser/:uid", adduser)
|
||||||
http.ListenAndServe(":8088", nil)
|
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.
|
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
|
## Resumen
|
||||||
|
|
||||||
|
|||||||
88
ja/05.6.md
88
ja/05.6.md
@@ -9,10 +9,90 @@ redisはkey-valueを保存するシステムです。Memcachedに似ていて、
|
|||||||
現在redisが最もよく使われているのは新浪のマイクロブログプラットフォームでしょう。その次にFacebookに買収された画像フォーラムであるinstagramがあります。その他有名な[インターネット企業](http://redis.io/topics/whos-using-redis)もそうです。
|
現在redisが最もよく使われているのは新浪のマイクロブログプラットフォームでしょう。その次にFacebookに買収された画像フォーラムであるinstagramがあります。その他有名な[インターネット企業](http://redis.io/topics/whos-using-redis)もそうです。
|
||||||
|
|
||||||
Goは現在redisのドライバで以下をサポートしています
|
Goは現在redisのドライバで以下をサポートしています
|
||||||
- https://github.com/alphazero/Go-Redis
|
- [https://github.com/garyburd/redigo](https://github.com/garyburd/redigo)
|
||||||
- http://code.google.com/p/tideland-rdc/
|
- [https://github.com/go-redis/redis](https://github.com/go-redis/redis)
|
||||||
- https://github.com/simonz05/godis
|
- [https://github.com/hoisie/redis](https://github.com/hoisie/redis)
|
||||||
- https://github.com/hoisie/redis.go
|
- [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数があります。)
|
現在私がforkした最新のドライバではいくつかのbugが修正されています。現在私自身の短縮ドメイン名サービスのプロジェクトの中で使用されています。(毎日200WぐらいのPV数があります。)
|
||||||
|
|
||||||
|
|||||||
57
ja/08.3.md
57
ja/08.3.md
@@ -62,49 +62,62 @@ GoにはRESTに対する直接のサポートはありません。しかし、RE
|
|||||||
|
|
||||||
現在`POST`の中において隠されたフィールドである`_method`を増加するなどの方法で`PUT`、`DELETE`といったメソッドをエミュレートすることができます。しかし、サーバでは変換を行う必要があります。現在私のプロジェクトではこのような方法によってRESTインターフェースを作成しています。当然Go言語では完全にRESTfulに沿った実装を行うのは容易です。下の例を通してどのようにRESTfulなアプリケーションの設計を実現するかご説明しましょう。
|
現在`POST`の中において隠されたフィールドである`_method`を増加するなどの方法で`PUT`、`DELETE`といったメソッドをエミュレートすることができます。しかし、サーバでは変換を行う必要があります。現在私のプロジェクトではこのような方法によってRESTインターフェースを作成しています。当然Go言語では完全にRESTfulに沿った実装を行うのは容易です。下の例を通してどのようにRESTfulなアプリケーションの設計を実現するかご説明しましょう。
|
||||||
|
|
||||||
|
```Go
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/drone/routes"
|
"github.com/julienschmidt/httprouter"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getuser(w http.ResponseWriter, r *http.Request) {
|
func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||||
params := r.URL.Query()
|
fmt.Fprint(w, "Welcome!\n")
|
||||||
uid := params.Get(":uid")
|
}
|
||||||
|
|
||||||
|
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)
|
fmt.Fprintf(w, "you are get user %s", uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func modifyuser(w http.ResponseWriter, r *http.Request) {
|
func modifyuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
params := r.URL.Query()
|
uid := ps.ByName("uid")
|
||||||
uid := params.Get(":uid")
|
|
||||||
fmt.Fprintf(w, "you are modify user %s", uid)
|
fmt.Fprintf(w, "you are modify user %s", uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteuser(w http.ResponseWriter, r *http.Request) {
|
func deleteuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
params := r.URL.Query()
|
uid := ps.ByName("uid")
|
||||||
uid := params.Get(":uid")
|
|
||||||
fmt.Fprintf(w, "you are delete user %s", uid)
|
fmt.Fprintf(w, "you are delete user %s", uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func adduser(w http.ResponseWriter, r *http.Request) {
|
func adduser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
params := r.URL.Query()
|
// uid := r.FormValue("uid")
|
||||||
uid := params.Get(":uid")
|
uid := ps.ByName("uid")
|
||||||
fmt.Fprint(w, "you are add user %s", uid)
|
fmt.Fprintf(w, "you are add user %s", uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
mux := routes.New()
|
router := httprouter.New()
|
||||||
mux.Get("/user/:uid", getuser)
|
router.GET("/", Index)
|
||||||
mux.Post("/user/:uid", modifyuser)
|
router.GET("/hello/:name", Hello)
|
||||||
mux.Del("/user/:uid", deleteuser)
|
|
||||||
mux.Put("/user/", adduser)
|
router.GET("/user/:uid", getuser)
|
||||||
http.Handle("/", mux)
|
router.POST("/adduser/:uid", adduser)
|
||||||
http.ListenAndServe(":8088", nil)
|
router.DELETE("/deluser/:uid", deleteuser)
|
||||||
|
router.PUT("/moduser/:uid", modifyuser)
|
||||||
|
|
||||||
|
log.Fatal(http.ListenAndServe(":8080", router))
|
||||||
}
|
}
|
||||||
|
|
||||||
上のコードではどのように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のフレームワークは実現されています。
|
RESTはフレームワークスタイルの一種です。WWWの成功経験を汲み取っています:ステートレス、リソースを中心とし、HTTPプロトコルとURIプロトコルを十分利用しています。統一したインターフェース定義を提供し、Webサービスを設計する方法の一つとして流行しました。ある意味でURIとHTTPといった黎明期のInternet標準を強調することで、RESTは大型のアプリケーションプログラムサーバ時代の前のWeb方式に回帰しています。今のところGoのRESTに対するサポートはまだシンプルです。自分で定義したルーティングを通して、異なるmethodに異なるhandleを実装することができます。このようにRESTのフレームワークは実現されています。
|
||||||
|
|||||||
@@ -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.
|
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:
|
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)
|
- [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/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).
|
I forked the last of these packages, fixed some bugs, and used it in my short URL service (2 million PV every day).
|
||||||
|
|
||||||
|
|||||||
@@ -68,49 +68,62 @@ 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:
|
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
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/drone/routes"
|
"github.com/julienschmidt/httprouter"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getuser(w http.ResponseWriter, r *http.Request) {
|
func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||||
params := r.URL.Query()
|
fmt.Fprint(w, "Welcome!\n")
|
||||||
uid := params.Get(":uid")
|
}
|
||||||
|
|
||||||
|
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)
|
fmt.Fprintf(w, "you are get user %s", uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func modifyuser(w http.ResponseWriter, r *http.Request) {
|
func modifyuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
params := r.URL.Query()
|
uid := ps.ByName("uid")
|
||||||
uid := params.Get(":uid")
|
|
||||||
fmt.Fprintf(w, "you are modify user %s", uid)
|
fmt.Fprintf(w, "you are modify user %s", uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteuser(w http.ResponseWriter, r *http.Request) {
|
func deleteuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
params := r.URL.Query()
|
uid := ps.ByName("uid")
|
||||||
uid := params.Get(":uid")
|
|
||||||
fmt.Fprintf(w, "you are delete user %s", uid)
|
fmt.Fprintf(w, "you are delete user %s", uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func adduser(w http.ResponseWriter, r *http.Request) {
|
func adduser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
params := r.URL.Query()
|
// uid := r.FormValue("uid")
|
||||||
uid := params.Get(":uid")
|
uid := ps.ByName("uid")
|
||||||
fmt.Fprint(w, "you are add user %s", uid)
|
fmt.Fprintf(w, "you are add user %s", uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
mux := routes.New()
|
router := httprouter.New()
|
||||||
mux.Get("/user/:uid", getuser)
|
router.GET("/", Index)
|
||||||
mux.Post("/user/:uid", modifyuser)
|
router.GET("/hello/:name", Hello)
|
||||||
mux.Del("/user/:uid", deleteuser)
|
|
||||||
mux.Put("/user/", adduser)
|
router.GET("/user/:uid", getuser)
|
||||||
http.Handle("/", mux)
|
router.POST("/adduser/:uid", adduser)
|
||||||
http.ListenAndServe(":8088", nil)
|
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.
|
```
|
||||||
|
|
||||||
|
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
|
## Summary
|
||||||
|
|
||||||
|
|||||||
50
zh/08.3.md
50
zh/08.3.md
@@ -68,45 +68,55 @@ Go没有为REST提供直接支持,但是因为RESTful是基于HTTP协议实现
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/drone/routes"
|
"github.com/julienschmidt/httprouter"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getuser(w http.ResponseWriter, r *http.Request) {
|
func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||||
params := r.URL.Query()
|
fmt.Fprint(w, "Welcome!\n")
|
||||||
uid := params.Get(":uid")
|
}
|
||||||
|
|
||||||
|
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)
|
fmt.Fprintf(w, "you are get user %s", uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func modifyuser(w http.ResponseWriter, r *http.Request) {
|
func modifyuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
params := r.URL.Query()
|
uid := ps.ByName("uid")
|
||||||
uid := params.Get(":uid")
|
|
||||||
fmt.Fprintf(w, "you are modify user %s", uid)
|
fmt.Fprintf(w, "you are modify user %s", uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteuser(w http.ResponseWriter, r *http.Request) {
|
func deleteuser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
params := r.URL.Query()
|
uid := ps.ByName("uid")
|
||||||
uid := params.Get(":uid")
|
|
||||||
fmt.Fprintf(w, "you are delete user %s", uid)
|
fmt.Fprintf(w, "you are delete user %s", uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func adduser(w http.ResponseWriter, r *http.Request) {
|
func adduser(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
uid := r.FormValue("uid")
|
// uid := r.FormValue("uid")
|
||||||
|
uid := ps.ByName("uid")
|
||||||
fmt.Fprintf(w, "you are add user %s", uid)
|
fmt.Fprintf(w, "you are add user %s", uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
mux := routes.New()
|
router := httprouter.New()
|
||||||
mux.Get("/user/:uid", getuser)
|
router.GET("/", Index)
|
||||||
mux.Post("/user/", adduser)
|
router.GET("/hello/:name", Hello)
|
||||||
mux.Del("/user/:uid", deleteuser)
|
|
||||||
mux.Put("/user/:uid", modifyuser)
|
router.GET("/user/:uid", getuser)
|
||||||
http.Handle("/", mux)
|
router.POST("/adduser/:uid", adduser)
|
||||||
http.ListenAndServe(":8088", nil)
|
router.DELETE("/deluser/:uid", deleteuser)
|
||||||
|
router.PUT("/moduser/:uid", modifyuser)
|
||||||
|
|
||||||
|
log.Fatal(http.ListenAndServe(":8080", router))
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
上面的代码演示了如何编写一个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的架构。
|
REST是一种架构风格,汲取了WWW的成功经验:无状态,以资源为中心,充分利用HTTP协议和URI协议,提供统一的接口定义,使得它作为一种设计Web服务的方法而变得流行。在某种意义上,通过强调URI和HTTP等早期Internet标准,REST是对大型应用程序服务器时代之前的Web方式的回归。目前Go对于REST的支持还是很简单的,通过实现自定义的路由规则,我们就可以为不同的method实现不同的handle,这样就实现了REST的架构。
|
||||||
|
|||||||
Reference in New Issue
Block a user