2015-03-23 3 views
10

Есть ли собственный способ для параметров url inplace в native Go?Отобразить параметры URL-адреса

Например, если у меня есть URL: http://localhost:8080/blob/123/test Я хочу использовать этот URL как /blob/{id}/test.

Я не хочу использовать внешнюю библиотеку и хочу сделать ее родной Go.

+3

Go очень отзывчивый. «Я (не хочу) хочу», - будет больно. – Volker

+1

Я не понимаю ни слова. Вопрос очень ясен. – Jacob

ответ

6

Там отсутствует встроенный в простой способ сделать это, однако, это не так трудно сделать.

Вот как я это делаю, не добавляя определенную библиотеку. Он помещается в функцию, так что вы можете вызвать простую функцию getCode() внутри вашего обработчика запросов.

В основном вы просто разделите r.URL.Path на части, а затем проанализируйте их.

// 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

: Это сработает. Я уже сделал почти аналогичную реализацию. Большое спасибо за ваш ответ. :) – Somesh

6

Ну, без внешних библиотек вы не можете, но, возможно, я рекомендую две отличные из них:

  1. httprouter - https://github.com/julienschmidt/httprouter - очень быстро и очень легкий. Это быстрее, чем стандартный маршрутизатор библиотеки, и он создает 0 распределений за вызов, что отлично подходит для языка GCed.

  2. Gorilla Mux - http://www.gorillatoolkit.org/pkg/mux - Очень популярный, приятный интерфейс, приятное общение. не

Пример использования 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

Если вы не можете без внешних библиотек, как эти библиотеки реализованы? – rightfold

+2

@ райтфолд они реализованы на самом низком уровне, минуя стандартный http-маршрутизатор.Я понял вопрос OP как «есть ли способ сделать это, используя стандартную библиотеку http». Ну, просто для реализации собственного маршрутизатора. И в этом нет необходимости. –

-1

Ни в коем случае без стандартной библиотеки. Почему вы не хотите попробовать библиотеку? Я думаю, что его не так сложно использовать, просто перейдите к bla bla bla

Я использую Beego. Его стиль MVC.

-1

Если вам нужна структура, и вы думаете, что она будет медленной, потому что она «больше», чем маршрутизатор или сеть/http, тогда вы ошибаетесь.

Iris является самым быстрым go web framework, который вы когда-либо найдете, по всем показателям.

Установка по

go get gopkg.in/kataras/iris.v6 

шаблонов Django идет легко с радужки:

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

Как о написании собственного генератора URL (продлить net/url немного), как показано ниже.

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