Jika anda pernah bekerja dengan rangka kerja web seperti Express.js, anda tahu betapa mudah dan mudahnya untuk digunakan. Sekarang, bayangkan kemudahan ini dalam Go, dengan prestasi dan keteguhannya. Nah, itu mendorong saya untuk mencipta express-go, rangka kerja mikro yang diilhamkan oleh Express.js, dan yang terbaik: Saya membinanya dalam masa 19 jam! Perjalanan itu sengit, tetapi bernilai setiap saat. Biar saya ceritakan bagaimana semuanya berlaku. Pautan repositori rasmi
Semuanya bermula apabila saya berfikir: "Memang bagus untuk mempunyai sesuatu yang ringkas seperti Express.js, tetapi dengan prestasi Go!". Go sudah dikenali sebagai minimalis dan berprestasi, tetapi apabila ia datang untuk menulis pelayan web, saya merasakan sesuatu yang lebih mudah untuk digunakan seperti Express.js masih tiada.
Jadi daripada merungut, saya memutuskan untuk mengotorkan tangan saya dan membuat sesuatu berlaku. Saya berazam untuk mencipta rangka kerja mikro yang membolehkan saya mengkonfigurasi laluan, mengendalikan permintaan dan respons HTTP dengan cepat dan mudah.
Saya bermula dengan struktur asas: aplikasi Go yang boleh mendengar permintaan HTTP dan, bergantung pada laluan, melaksanakan fungsi yang berbeza.
Perkara pertama yang perlu saya lakukan ialah menyediakan penghalaan. Saya harap anda boleh mentakrifkan laluan dengan cara yang serupa dengan Express.js, di mana anda menentukan URL dan fungsi untuk mengendalikan laluan itu.
Inilah keajaiban laluan:
type App struct { routes map[string]func(req *req.Request, res *req.Response) } func NewApp() *App { return &App{ routes: make(map[string]func(req *req.Request, res *req.Response)), } } func (a *App) Route(path string, handler func(req *req.Request, res *req.Response)) { a.routes[path] = handler } func (a *App) ServeHTTP(w http.ResponseWriter, r *http.Request) { if handler, exists := a.routes[r.URL.Path]; exists { request := req.NewRequest(r) response := req.NewResponse(w) handler(request, response) } else { http.NotFound(w, r) } } func (a *App) Listen(addr string) error { return http.ListenAndServe(addr, a) }
Idea di sini adalah mudah: Saya mahukan peta laluan (map[string]func) dengan kuncinya ialah URL dan nilainya ialah fungsi yang akan mengendalikan permintaan.
Salah satu perkara yang paling saya sukai tentang Express.js ialah cara mudah untuk menggunakan pengendali laluan. Jadi, saya menerima pakai idea bahawa setiap laluan hanya akan menjadi fungsi yang akan menerima dua parameter: permintaan dan tindak balas. Dalam Go, ini adalah lebih banyak kerja, kerana perpustakaan standard memerlukan banyak kerja manual, jadi saya menulis beberapa abstraksi untuk memudahkannya.
Mengendalikan Permintaan
Permintaan HTTP dalam Go melibatkan banyak struktur dan kaedah, jadi saya merangkum semua ini dalam struct yang dipanggil Request, dengan beberapa kaedah mudah untuk mendapatkan parameter pertanyaan, pengepala dan badan permintaan.
type Request struct { Req *http.Request Body string } func NewRequest(req *http.Request) *Request { bodyBytes, _ := io.ReadAll(req.Body) bodyString := string(bodyBytes) return &Request{ Req: req, Body: bodyString, } } func (r *Request) QueryParam(key string) string { params := r.Req.URL.Query() return params.Get(key) } func (r *Request) Header(key string) string { return r.Req.Header.Get(key) } func (r *Request) BodyAsString() string { return r.Body }
Sekarang, daripada berurusan dengan http.Request secara langsung, saya boleh melakukan sesuatu seperti:
app.Route("/greet", func(r *req.Request, w *req.Response) { name := r.QueryParam("name") if name == "" { name = "Guest" } w.Send("Hello, " + name + "!") })
Ini menjadikan perkara lebih bersih dan lebih mudah dibaca!
Selepas permintaan, sudah tiba masanya untuk memudahkan penghantaran balasan. Respons juga memerlukan sentuhan kesederhanaan supaya saya boleh menghantar teks atau JSON dengan cepat.
type App struct { routes map[string]func(req *req.Request, res *req.Response) } func NewApp() *App { return &App{ routes: make(map[string]func(req *req.Request, res *req.Response)), } } func (a *App) Route(path string, handler func(req *req.Request, res *req.Response)) { a.routes[path] = handler } func (a *App) ServeHTTP(w http.ResponseWriter, r *http.Request) { if handler, exists := a.routes[r.URL.Path]; exists { request := req.NewRequest(r) response := req.NewResponse(w) handler(request, response) } else { http.NotFound(w, r) } } func (a *App) Listen(addr string) error { return http.ListenAndServe(addr, a) }
Pada penghujung 19 jam kerja ini, saya berjaya mencipta express-go: rangka kerja mikro yang pantas dan mudah digunakan, di mana mengkonfigurasi laluan dan menghantar respons adalah semudah Express.js, tetapi dengan semua kuasa dan prestasi Go.
Berikut ialah contoh lengkap tentang cara semuanya sesuai:
type Request struct { Req *http.Request Body string } func NewRequest(req *http.Request) *Request { bodyBytes, _ := io.ReadAll(req.Body) bodyString := string(bodyBytes) return &Request{ Req: req, Body: bodyString, } } func (r *Request) QueryParam(key string) string { params := r.Req.URL.Query() return params.Get(key) } func (r *Request) Header(key string) string { return r.Req.Header.Get(key) } func (r *Request) BodyAsString() string { return r.Body }
Mudah, bersih dan tepat sasaran. Saya berbangga untuk mengatakan bahawa saya dapat membina ini dalam masa kurang dari sehari, dan perkara yang menarik ialah ia menawarkan fleksibiliti yang cukup untuk projek kecil, tanpa semua kerumitan rangka kerja yang lebih besar.
Mencipta express-go dalam masa 19 jam merupakan perjalanan yang menyeronokkan dan mencabar. Saya menumpukan pada menyelesaikan masalah sebenar yang saya hadapi dengan pelayan Go dan cuba menjadikan semuanya seintuitif yang mungkin. Sudah tentu, banyak lagi kerja yang perlu dilakukan, tetapi banyak lagi yang perlu dilakukan!
Jika anda ingin tahu, lihat kod dan jangan ragu untuk menyumbang. Lagipun, alat binaan seperti ini lebih hebat apabila kita boleh berkongsi prosesnya!
Sekarang, kalau awak maafkan saya, saya akan minum kopi... selepas 19 jam, saya layak, bukan?
Atas ialah kandungan terperinci Bagaimana Saya Menulis Express-Go dalam Jam. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!