Welcome, or No Trespassing
(C) E.G. Klimov 1964A router written in Go (or as it is sometimes called a router), which turned out to be fast enough so that it would not be a shame to compare it with the leaders of go-routing: Bone, Httprouter, Gorilla, Zeus. The name of the router was given by the simple Russian word “Login”, typed in English letters in the Volapuk coding
en.wikipedia.org/wiki/Volapuk_encodingNever happened to me like this: no entry! Wherever you stick - everywhere are solid windows.
(C) Arkady and Boris Strugatsky. Lame fate')
Bxog (English letters), reads Biksouji. In the comments I propose to call a router to choose from: Login, Bxog, Biksouji, Bixog. For the module in the application that first meets the user's request, the name, from my point of view, is quite appropriate. By analogy with Windows, I would like to call my Door router, but I'm afraid to be misunderstood;)
Links to sources:
github.com/claygod/Bxoggithub.com/claygod/BxogTestWhat for
And what for me these feathers?
(C) From a jokeI will say right away, the crisis is to blame for everything: salaries are not enough, with Adsens on old sites, nothing is already dripping, but we must live. We need additional income, but on what to do it? I was tired of puffing, but I don’t know how to do anything else, well, I don’t really want to go to the web designers ... Frontend, this is somehow not mine.
Initially, I looked at C / C ++, moreover I tended to lean toward C (here each has his own). But taking into account pointers, pointers to pointers, pointers to functions and pointers to functions that function pointers take as input, my fragile brain demanded a return from nonalcoholic to classical beer, which the body somehow opposed (unity and struggle of opposites).
After a pleasant and
interesting Lua , I got a new hand (for me) Golang: simple, quickly mastered, similar to C. Put LiteIDE, and you can work. An important plus is that you can put everything on a work computer under Windows even with user rights (well, strict corporate rules at my work, this is a fact).
It remains to determine what to write in the process of learning a language (I believe that it is normal not to study a different language). Framework, this is somehow a bit too much ... And if you study even just one language per year, how many frameworks do you have to rivet? I am afraid that the planet will not endure this, I'm not alone on it :) I decided to write a router, and on this, perhaps, I will finish the lyrical digression.
Development
Since I didn’t yet know the Go language at the time of the beginning of development, the structure of the router, and the principles of its storage and route search changed several times (dramatically, four times). The first iteration was completely introductory. Looking at it (with tears, but how), I understood the basics of Golang and made the second version, in which even looking at the code was not too scary. However, even simple ab testing showed me that my work was pretty slow.
Having changed the algorithms and made some more edits, I decided to get acquainted with other Go-routers. From the list I liked
Bone , I would not be surprised if it is largely due to the name and the funny picture. Looking at this router, I thought that, oh, I would be able to be able to ... The number of stars under a thousand of this router was also somehow inspiring.
Bone has a bench, which pushed me to the third iteration of the development of his creation. Having written myself a similar bench, I again changed the storage structure and the search algorithm. Now, lo and behold, my Bixojie was able to overtake Gorilla Pat (Gorilla Mux is slower, and it’s not difficult to deal with it). At the same time, I realized that Bone's favorite is not at all sharpened by large dynamic URLs, although it copes well with the short static ones, and its bench just written for this.
The king is dead, long live the king! Now I will fight with
HttpRouter . In the course of the play, I realized that the maps in Go, to put it mildly, do not shine with speed compared to arrays. The next round of development began to bring the router to the finish line, where the leader's bench became close, we can say the neighbor. Looking away at my code, I decided that it was too verbose, and in addition, it required fine tuning.
Having polished the router for as long as I had enough patience and brains, I proceeded to write tests (I confess, I just tested it manually and occasionally). Tests have shown that I have not so much patience and brains, but at the same time revealed a couple of major and implicit errors that had to be fixed.
Since
strings. Split was also not fast, with the hesitating light of a candle, I had to write an analogue that met my requirements. Yes, to be honest, sometimes writing fast code means writing a not very nice and hardcore code. Wood chopping - chips fly. In the end, I was able to achieve superiority over the king in benches. It was a bit flattering to my vanity, and although it was not intended to be a clear goal.
Fast start
In principle, I tried to organize the code so that the router’s operation was simple and clear, that is, I hope the code speaks for itself. Well, below I give a comprehensive example of using a router, demonstrating all of its methods.
comprehensive example of using a routerpackage main import ( "io" "net/http" "github.com/claygod/Bxog" )
After starting the above example, click on the links:
Configuration
You need to configure the router by editing the configuration file
github.com/claygod/bxog/config.go The file contains constants that can be changed.
HTTP_METHOD_DEFAULT
The method used by the default router (GET, POST, etc.). This option allows you to write less code and in fact just sugar.
HTTP_SECTION_COUNT
The maximum number of sections in urla. A section is a set of characters between two slashes. It is not necessary to set this figure against the number of sections in the largest route. If 32 is not enough, then write 64, so as not to bother, well, etc.
HTTP_PATTERN_COUNT
The maximum length of the URL. It is clear without explanation.
READ_TIME_OUT
Maximum wait time while reading
WRITE_TIME_OUT
Maximum recording timeout
FILE_PREF
Local path from the root of the site in URL for files available for download.
FILE_PATH
The full path to the directory from which the files will be available for download.
Benchmark
The router turned out fast enough so that it was not a shame to test it in the benchmark together with such popular routers written on Go as Bone, Httprouter, Gorilla, Zeus. The benchmark code and tests of the router are here -
github.com/claygod/bxogtestThe benchmark result for the specified routers in comparison with Bxog with 150 generated 6-section routs (I do not specify the computer configuration, because here it is not absolute numbers that are most important, but their comparison):
- BenchmarkBxogMux-4 5000000 330 ns / op
- BenchmarkHttpRouterMux-4 3000000 395 ns / op
- BenchmarkZeusMux-4 100000 23772 ns / op
- BenchmarkGorillaMux-4 50000 30223 ns / op
- BenchmarkGorillaPatMux-4 1,000,000 1253 ns / op
- BenchmarkBoneMux2-4 20000 63656 ns / op
Very pleased with Gorilla Pat, which shows good, although not the best performance. If you are satisfied with the program from Gorilla, then to find a quick solution Gorilla Pat is a very good solution.
If we talk about the choice of the router in general, then it is important to see how it suits you from the inside (this is my opinion, someone thinks that apart from the API, you don’t have to look at anything). But the fact that there is a choice is already good. The picture below shows that the top three, depending on the number of routes, do not change much.

Tests
Perhaps the tests are not enough, or at some point they are not covered enough, I will be glad to receive tips in the comments. In general, DISCLAIMER, in the jambs that probably exist, do not blame me, I just passed by here.
API
The API of the router is as simple as an orange. As a small sweetness (if the orange is sour), the ability to not only access the parameters from the URL in the handler, but also generate a new URL is added. This may be convenient when developing a Go site (or a framework for such tasks).
Methods:
- New - create multiplexer
- Add - add a route. By default, the GET method and the route ID as a string are its rules, respectively, these are not required options. Example with method and ID: m.Add ("/ abc /: param", YourHandler) .Method ("POST"). Id ("abc")
- Start - start the server with the port that you want to listen
- Params - get parameters from URL
- Create - create a URL from the parameters of the route
- Test - analogue Start (only for testing)
A simple example:
m := bxog.New() m.Add("/", IndexHandler) m.Start(":80")
Sections
As mentioned above, URL slashes are divided into sections. A section can be static (immutable) and dynamic (argument). The dynamic section begins with a colon (this is a common practice of routers). The last section should not end with a slash.
Static files
With the help of the
FILE_PREF and
FILE_PATH constants, it is necessary to indicate to the router which way static files will be accessible in the browser and which path to these files on the hard disk.
Golang
Disputes about Go do not subside. Some criticize him, others praise him. And the one and the other, perhaps justified. I liked the forced formatting of the code: reading other people's sources no longer causes any problems, everything is homogeneous and readable. Sometimes reminders of created and unused variables interfere, but in the end, you simply change your programming style so that the compilation is immediately successful. Will I continue to use this language? Yes. Would I recommend it to others? Yes. Is it necessary to make it the main and only language in your work? No, and not because it is bad, you just need to expand your horizons.
Summing up
That's all write "emergency exit." And at least one contagion wrote "emergency entrance".
(C) Dmitry Emets. Methodius Buslaev. Revenge of the ValkyriesStarting to write my Bixoge, I did not set out to wipe the nose of the go-router router * Httprouter * in the speed of processing the request. The fact that my code was fast is rather a nice bonus. In my opinion, for an application using a router, this same router is unlikely to be a narrow neck. But if you set a goal to write a really fast application, then ... another thing. Most likely it will be a small application, service or something else like that. For large and complex applications, speed ceases to be the only and most important criterion.
And what about the work?
I did not find a job, because I have not yet searched. I would very much like to read in the comments about the real situations of the market of Go-programmers, otherwise I have some doubts disassembled, I can immediately buy a new textbook on the XXX language :)
github.com/claygod/Bxoggithub.com/claygod/BxogTestUPD: 01/17/2017
Made a clone of the router under the
Fast HTTP server :
github.com/claygod/doorUPD: 02/28/2017
Recently drew attention to the fact that the speed of the main rival HttpRouter was slightly increased by its author. Also, to my regret, the commits that made working with command line parameters through the native Context slowed down my favorite router significantly. Accordingly, I had to spend a couple of evenings and increase the performance of my brainchild. Today, the benchmark for the hundreds of six-section routes looks like this:
- BenchmarkBxogMux-4 5000000 277 ns / op
- BenchmarkHttpRouterMux-4 3000000 307 ns / op
- BenchmarkZeusMux-4 100000 18631 ns / op
- BenchmarkGorillaMux-4 50000 25302 ns / op
- BenchmarkGorillaPatMux-4 1,000,000 1253 ns / op
- BenchmarkBoneMux2-4 20000 63656 ns / op
For GorillaPat and Bone, the situation has not changed, so I left the old numbers. I would also note that the situation is even better for routs with a smaller number of sections, but since I decided to measure in six-sections, then so be it.