2015-03-23 18 views
10

Esiste un modo nativo per i parametri url inplace in nativo Go?Mappatura parametri URL url

Ad esempio, se ho un URL: http://localhost:8080/blob/123/test Desidero utilizzare questo URL come /blob/{id}/test.

Non voglio usare alcuna libreria esterna e voglio farlo nativo Go.

+3

Go è molto supponente. A "I (do not) want" -l'atteggiamento farà male. – Volker

+1

Non capisco il voto negativo. La domanda è molto chiara. – Jacob

risposta

6

Non c'è costruito in modo semplice per fare questo, però, non è difficile da fare.

Ecco come lo faccio, senza aggiungere una libreria particolare. Viene inserito in una funzione in modo da poter richiamare una semplice funzione getCode() all'interno del gestore richieste.

Fondamentalmente è sufficiente dividere lo r.URL.Path in parti e quindi analizzare le parti.

// 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, "" 
     } 
} 
+0

: Questo funzionerà. Ho già fatto un'implementazione quasi simile. Grazie mille per la tua risposta. :) – Somesh

6

bene, senza le librerie esterne non è possibile, ma posso raccomandare due quelli eccellenti:

  1. httprouter - https://github.com/julienschmidt/httprouter - è estremamente veloce e molto leggero. È più veloce del router della libreria standard e crea 0 allocazioni per chiamata, il che è ottimo in un linguaggio GCed.

  2. Gorilla Mux - http://www.gorillatoolkit.org/pkg/mux - Interfaccia molto popolare, bella, bella comunità.

utilizzo Esempio di 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)) 
} 
+6

Se non è possibile senza librerie esterne, come vengono implementate queste librerie? – rightfold

+2

@ райтфолд sono implementati al livello più basso, bypassando il router http predefinito.Ho capito la domanda di OP come "c'è un modo per farlo usando la libreria HTTP predefinita". Bene: solo per implementare il tuo router. E non c'è davvero bisogno di questo. –

-1

Nessun modo senza libreria standard. Perché non vuoi provare qualche libreria? Penso che non sia così difficile da usare, basta andare a prendere bla bla bla

Io uso Beego. Il suo stile MVC.

-1

Se avete bisogno di un framework e pensate che sarà lento perché è "più grande" di un router o di una rete/http, allora vi sbagliate.

Iris è il più veloce go web framework che troverete mai, finora secondo tutti i parametri.

Installare da

go get gopkg.in/kataras/iris.v6 

modelli di Django va facile con 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"}) 
} 
-1

ne dite di scrivere il proprio generatore url (estendono net/url un po ') come di seguito.

// --- 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() 
}