内容简介:I wanted a simple, fast router that has no unnecessary overhead using the standard library only, following good practices and well tested code.Detail see
gorouter
xujiajun/gorouter is a simple and fast HTTP router for Go. It is easy to build RESTful APIs and your web framework.
Motivation
I wanted a simple, fast router that has no unnecessary overhead using the standard library only, following good practices and well tested code.
Features
- Custom NotFoundHandler
- Middleware Chain Support
- Pattern Rule Familiar
- HTTP Method Get、Post、Delete、Put、Patch Support
- No external dependencies (just Go stdlib)
Requirements
- golang 1.8+
Installation
go get github.com/xujiajun/gorouter
Usage
Static routes
package main
import (
"log"
"net/http"
"github.com/xujiajun/gorouter"
)
func main() {
mux := gorouter.New()
mux.GET("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hello world"))
})
log.Fatal(http.ListenAndServe(":8181", mux))
}
URL Parameters
package main
import (
"github.com/xujiajun/gorouter"
"log"
"net/http"
)
func main() {
mux := gorouter.New()
//url parameters match
mux.GET("/user/:id", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("match user/:id !"))
})
log.Fatal(http.ListenAndServe(":8181", mux))
}
Regex Parameters
package main
import (
"github.com/xujiajun/gorouter"
"log"
"net/http"
)
func main() {
mux := gorouter.New()
//url regex match
mux.GET("/user/{id:[0-9]+}", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("match user/{id:[0-9]+} !"))
})
log.Fatal(http.ListenAndServe(":8181", mux))
}
Routes Groups
package main
import (
"fmt"
"github.com/xujiajun/gorouter"
"log"
"net/http"
)
func usersHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "/api/users")
}
func main() {
mux := gorouter.New()
mux.Group("/api").GET("/users", usersHandler)
log.Fatal(http.ListenAndServe(":8181", mux))
}
Custom NotFoundHandler
package main
import (
"fmt"
"github.com/xujiajun/gorouter"
"log"
"net/http"
)
func notFoundFunc(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
fmt.Fprint(w, "404 page !!!")
}
func main() {
mux := gorouter.New()
mux.NotFoundFunc(notFoundFunc)
mux.GET("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hello world"))
})
log.Fatal(http.ListenAndServe(":8181", mux))
}
Custom PanicHandler
package main
import (
"fmt"
"github.com/xujiajun/gorouter"
"log"
"net/http"
)
func main() {
mux := gorouter.New()
mux.PanicHandler = func(w http.ResponseWriter, req *http.Request, err interface{}) {
w.WriteHeader(http.StatusInternalServerError)
fmt.Println("err from recover is :", err)
fmt.Fprint(w, "received a panic")
}
mux.GET("/panic", func(w http.ResponseWriter, r *http.Request) {
panic("panic")
})
log.Fatal(http.ListenAndServe(":8181", mux))
}
Middlewares Chain
package main
import (
"fmt"
"github.com/xujiajun/gorouter"
"log"
"net/http"
)
type statusRecorder struct {
http.ResponseWriter
status int
}
func (rec *statusRecorder) WriteHeader(code int) {
rec.status = code
rec.ResponseWriter.WriteHeader(code)
}
//https://upgear.io/blog/golang-tip-wrapping-http-response-writer-for-middleware/
func withStatusRecord(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
rec := statusRecorder{w, http.StatusOK}
next.ServeHTTP(&rec, r)
log.Printf("response status: %v\n", rec.status)
}
}
func notFoundFunc(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
fmt.Fprint(w, "Not found page !")
}
func withLogging(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
log.Printf("Logged connection from %s", r.RemoteAddr)
next.ServeHTTP(w, r)
}
}
func withTracing(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
log.Printf("Tracing request for %s", r.RequestURI)
next.ServeHTTP(w, r)
}
}
func main() {
mux := gorouter.New()
mux.NotFoundFunc(notFoundFunc)
mux.Use(withLogging, withTracing, withStatusRecord)
mux.GET("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hello world"))
})
log.Fatal(http.ListenAndServe(":8181", mux))
}
Serve static files
package main
import (
"github.com/xujiajun/gorouter"
"log"
"net/http"
"os"
)
//ServeFiles serve static resources
func ServeFiles(w http.ResponseWriter, r *http.Request) {
wd, err := os.Getwd()
if err != nil {
log.Fatal(err)
}
dir := wd + "/examples/serveStaticFiles/files"
http.StripPrefix("/files/", http.FileServer(http.Dir(dir))).ServeHTTP(w, r)
}
func main() {
mux := gorouter.New()
mux.GET("/hi", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hi"))
})
//defined prefix
mux2 := mux.Group("/files")
//http://127.0.0.1:8181/files/demo.txt
//will match
mux2.GET("/{filename:[0-9a-zA-Z_.]+}", func(w http.ResponseWriter, r *http.Request) {
ServeFiles(w, r)
})
//http://127.0.0.1:8181/files/a/demo2.txt
//http://127.0.0.1:8181/files/a/demo.txt
//will match
mux2.GET("/{fileDir:[0-9a-zA-Z_.]+}/{filename:[0-9a-zA-Z_.]+}", func(w http.ResponseWriter, r *http.Request) {
ServeFiles(w, r)
})
log.Fatal(http.ListenAndServe(":8181", mux))
}
Detail see serveStaticFiles example
Pattern Rule
The syntax here is modeled after julienschmidt/httprouter and gorilla/mux
| Syntax | Description | Example |
|---|---|---|
:name |
named parameter | /user/:name |
{name:regexp} |
named with regexp parameter | /user/{name:[0-9a-zA-Z]+} |
:id |
named with regexp parameter | /user/:id |
And :id is short for {id:[0-9]+} , :name are short for {name:[0-9a-zA-Z_]+}
Benchmarks
go test -bench=.
Benchmark System:
- Go version 1.9.2
- OS: Mac OS X 10.13.3
- Architecture: x86_64
- 16 GB 2133 MHz LPDDR3
Tested routers:
Result:
➜ gorouter git:(master) ✗ go test -bench=. GithubAPI Routes: 203 GithubAPI2 Routes: 203 HttpRouter: 37464 Bytes GoRouter: 83616 Bytes trie-mux: 135096 Bytes MuxRouter: 1324192 Bytes goos: darwin goarch: amd64 pkg: github.com/xujiajun/gorouter BenchmarkTrieMuxRouter-8 10000 692179 ns/op 1086465 B/op 2975 allocs/op BenchmarkHttpRouter-8 10000 627134 ns/op 1034366 B/op 2604 allocs/op BenchmarkGoRouter-8 10000 630895 ns/op 1034415 B/op 2843 allocs/op BenchmarkMuxRouter-8 10000 6396340 ns/op 1272876 B/op 4691 allocs/op PASS ok github.com/xujiajun/gorouter 83.503s
Conclusions:
-
Performance (xujiajun/gorouter ≈ julienschmidt/httprouter > teambition/trie-mux > gorilla/mux)
-
Memory Consumption (xujiajun/gorouter ≈ julienschmidt/httprouter < teambition/trie-mux < gorilla/mux)
-
Features (xujiajun/gorouter, gorilla/mux and teambition/trie-mux support regexp, But julienschmidt/httprouter not support)
if you want a performance router which support regexp, maybe xujiajun/gorouter is good choice.
Contributing
If you'd like to help out with the project. You can put up a Pull Request.
Author
License
The gorouter is open-sourced software licensed under the MIT Licensed
Acknowledgements
This package is inspired by the following:
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 【架构入门 - 高性能篇】集群高性能
- 【架构入门 - 高性能篇】数据库高性能
- 高性能计算Lustre性能优化方案
- 深度 | 从Go高性能日志库zap看如何实现高性能Go组件
- 高性能计算
- 高性能架构模式
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
HTML5与CSS3基础教程(第7版)
[美] Elizabeth Castro、[美] Bruce Hyslop / 望以文 / 人民邮电出版社 / 2013-1 / 59.00元
代表下一代网页编写技术的HTML5,为网页提供布局和格式的CSS3,这两者构成了Web开发的基石,也是Web程序员和设计师必须熟练掌握的最基本技能。 本书是风靡全球的HTML和CSS最佳入门教程的最新版,上一版单单英文版的销量就超过100万册,被翻译为十多种语言,并长期雄踞亚马逊书店计算机图书排行榜榜首。 最新的第7版秉承前一版直观、透彻、全面、循序渐进的讲授特色,仍然采用独特的双栏图......一起来看看 《HTML5与CSS3基础教程(第7版)》 这本书的介绍吧!