go - protocol - Ir a la asignación de parámetros de url
open graph protocol tutorial (5)
¿Hay una forma nativa para los parámetros de URL inplace en Go
nativo?
Por ejemplo, si tengo una URL: http://localhost:8080/blob/123/test
, quiero usar esta URL como /blob/{id}/test
.
Esta no es una pregunta sobre cómo encontrar bibliotecas. Estoy empezando con la pregunta básica: si proporciona una facilidad básica para hacerlo de forma nativa.
¿Qué tal si escribe su propio generador de url (extienda net/url
un poco) como se muestra a continuación?
// --- This is how does it work like --- //
url, _ := rest.NewURLGen("http", "stack.over.flow", "1234").
Pattern(foo/:foo_id/bar/:bar_id).
ParamQuery("foo_id", "abc").
ParamQuery("bar_id", "xyz").
ParamQuery("page", "1").
ParamQuery("offset", "5").
Do()
log.Printf("url: %s", url)
// url: http://stack.over.flow:1234/foo/abc/bar/xyz?page=1&offset=5
// --- Your own url generator would be like below --- //
package rest
import (
"log"
"net/url"
"strings"
"straas.io/base/errors"
"github.com/jinzhu/copier"
)
// URLGen generates request URL
type URLGen struct {
url.URL
pattern string
paramPath map[string]string
paramQuery map[string]string
}
// NewURLGen new a URLGen
func NewURLGen(scheme, host, port string) *URLGen {
h := host
if port != "" {
h += ":" + port
}
ug := URLGen{}
ug.Scheme = scheme
ug.Host = h
ug.paramPath = make(map[string]string)
ug.paramQuery = make(map[string]string)
return &ug
}
// Clone return copied self
func (u *URLGen) Clone() *URLGen {
cloned := &URLGen{}
cloned.paramPath = make(map[string]string)
cloned.paramQuery = make(map[string]string)
err := copier.Copy(cloned, u)
if err != nil {
log.Panic(err)
}
return cloned
}
// Pattern sets path pattern with placeholder (format `:<holder_name>`)
func (u *URLGen) Pattern(pattern string) *URLGen {
u.pattern = pattern
return u
}
// ParamPath builds path part of URL
func (u *URLGen) ParamPath(key, value string) *URLGen {
u.paramPath[key] = value
return u
}
// ParamQuery builds query part of URL
func (u *URLGen) ParamQuery(key, value string) *URLGen {
u.paramQuery[key] = value
return u
}
// Do returns final URL result.
// The result URL string is possible not escaped correctly.
// This is input for `gorequest`, `gorequest` will handle URL escape.
func (u *URLGen) Do() (string, error) {
err := u.buildPath()
if err != nil {
return "", err
}
u.buildQuery()
return u.String(), nil
}
func (u *URLGen) buildPath() error {
r := []string{}
p := strings.Split(u.pattern, "/")
for i := range p {
part := p[i]
if strings.Contains(part, ":") {
key := strings.TrimPrefix(p[i], ":")
if val, ok := u.paramPath[key]; ok {
r = append(r, val)
} else {
if i != len(p)-1 {
// if placeholder at the end of pattern, it could be not provided
return errors.Errorf("placeholder[%s] not provided", key)
}
}
continue
}
r = append(r, part)
}
u.Path = strings.Join(r, "/")
return nil
}
func (u *URLGen) buildQuery() {
q := u.URL.Query()
for k, v := range u.paramQuery {
q.Set(k, v)
}
u.RawQuery = q.Encode()
}
Bueno, sin bibliotecas externas no se puede, pero puedo recomendar dos excelentes:
httprouter - https://github.com/julienschmidt/httprouter - es extremadamente rápido y muy ligero. Es más rápido que el enrutador de la biblioteca estándar, y crea 0 asignaciones por llamada, lo cual es excelente en un lenguaje GCed.
Gorilla Mux - http://www.gorillatoolkit.org/pkg/mux - Muy popular, bonita interfaz, buena comunidad.
Ejemplo de uso de httprouter:
func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
fmt.Fprintf(w, "hello, %s!/n", ps.ByName("name"))
}
func main() {
router := httprouter.New()
router.GET("/hello/:name", Hello)
log.Fatal(http.ListenAndServe(":8080", router))
}
De ninguna manera sin biblioteca estándar. ¿Por qué no quieres probar alguna biblioteca? Creo que no es tan difícil de usar, solo ve por bla bla bla
Yo uso Beego . Su estilo MVC.
No hay una forma simple de hacer esto, sin embargo, no es difícil de hacer.
Así es como lo hago, sin añadir una biblioteca en particular. Se coloca en una función para que pueda invocar una función simple getCode()
dentro de su controlador de solicitudes.
Básicamente, simplemente divide el r.URL.Path
en partes, y luego analiza las partes.
// Extract a code from a URL. Return the default code if code
// is missing or code is not a valid number.
func getCode(r *http.Request, defaultCode int) (int, string) {
p := strings.Split(r.URL.Path, "/")
if len(p) == 1 {
return defaultCode, p[0]
} else if len(p) > 1 {
code, err := strconv.Atoi(p[0])
if err == nil {
return code, p[1]
} else {
return defaultCode, p[1]
}
} else {
return defaultCode, ""
}
}
Si necesita un marco y piensa que será lento porque es ''más grande'' que un enrutador o una red / http, entonces está equivocado.
Iris es el framework web Go más rápido que jamás encontrará, hasta ahora según todos los puntos de referencia.
Instalar por
go get gopkg.in/kataras/iris.v6
Las plantillas Django son fáciles con el iris:
import (
"gopkg.in/kataras/iris.v6"
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
"gopkg.in/kataras/iris.v6/adaptors/view" // <-----
)
func main() {
app := iris.New()
app.Adapt(iris.DevLogger())
app.Adapt(httprouter.New()) // you can choose gorillamux too
app.Adapt(view.Django("./templates", ".html")) // <-----
// RESOURCE: http://127.0.0.1:8080/hi
// METHOD: "GET"
app.Get("/hi", hi)
app.Listen(":8080")
}
func hi(ctx *iris.Context){
ctx.Render("hi.html", iris.Map{"Name": "iris"})
}