متن خبر

چگونه یک برنامه چت بلادرنگ با Go، Fiber و HTMX بسازیم

چگونه یک برنامه چت بلادرنگ با Go، Fiber و HTMX بسازیم

شناسهٔ خبر: 520312 -




در این آموزش، یک برنامه چت بلادرنگ ساده با استفاده از Go، Fiber و HTMX خواهید ساخت.

شما یاد خواهید گرفت که چگونه با استفاده از WebSocket از تطبیق پذیری فیبر استفاده کنید. همچنین یاد می گیرید که چگونه بدون استفاده از جاوا اسکریپت یک frontend واکنشی ایجاد کنید.

پیش نیازها

درک خوبی از سرورهای Go و HTTP.

Go باید نصب شود (نسخه Go 1.22 در این پروژه استفاده خواهد شد).

فهرست مطالب

شروع شدن

نحوه نصب Dependencies

فایل main.go

فایل های استاتیک

نحوه پیکربندی فایل های استاتیک

نحوه ایجاد هندلر

فایل messages.go

فایل websocket.go

چگونه یک WebSocket به مسیرها و HTMX اضافه کنیم

نتیجه

شروع شدن

ابتدا یک پوشه جدید به نام go-chat ایجاد کنید. همانطور که در زیر مشاهده می کنید، Go را در پروژه خود با اجرای go mod init pakacage_name آغاز کنید:

 go mod init github.com/steelthedev/go-chat

نحوه نصب Dependencies

شما باید چند کتابخانه را نصب کنید که بسیار حیاتی هستند. این را می توان در ترمینال با اجرای دستورات زیر انجام داد:

 go get -u github.com/gofiber/fiber/v2 go get -u github.com/gofiber/websocket/v2 go get -u github.com/gofiber/template/html/v2

اینها فیبر و اجزای دیگر مانند WebSocket و کتابخانه قالب HTML را نصب خواهند کرد.

فایل main.go

در پوشه اصلی، یک فایل main.go ایجاد کنید. این فایل نقطه ورود به برنامه خواهد بود. در داخل فایل قصد داریم یک وب سرور ساده ایجاد کنیم:

 package main import "github.com/gofiber/fiber/v2" func main() { // Start new fiber instance app := fiber.New() // Create a "ping" handler to test the server app.Get("/ping", func(ctx *fiber.Ctx) error{ return ctx.SendString("Welcome to fiber") }) // Start the http server app.Listen(":3000") }

فایل را ذخیره کرده و go run main.go در ترمینال اجرا کنید تا وب سرور راه اندازی شود.

tuts1-cropped
go run برای راه اندازی وب سرور

اگر به مرورگر بروید و مسیر /ping را آزمایش کنید، باید پاسخی مانند این وجود داشته باشد:

خوش آمدید <a href= به فیبر برش خورده" srcset="https://www.freecodecamp.org/news/content/images/size/w600/2024/06/welcome-to-fiber-cropped.png 600w, https://www.freecodecamp.org/news/content/images/size/w1000/2024/06/welcome-to-fiber-cropped.png 1000w, https://www.freecodecamp.org/news/content/images/size/w1600/2024/06/welcome-to-fiber-cropped.png 1600w, https://www.freecodecamp.org/news/content/images/2024/06/welcome-to-fiber-cropped.png 1912w" sizes="(min-width: 1200px) 1200px" width="1912" height="790" loading="lazy">
مسیر /پینگ در مرورگر

فایل های استاتیک

برای عملکرد برنامه به فایل های ثابت مانند فایل های CSS و HTML نیاز داریم. دو پوشه با نام static و view ایجاد کنید. در داخل پوشه views ، دو فایل html ایجاد کنید: index.html و messages.html .

فایل index.html باید به شکل زیر باشد:

 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Chat Room</title> <script src="https://unpkg.com/htmx.org@1.9.10" integrity="sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC" crossorigin="anonymous"></script> <!-- HTMX Websockets extension https://htmx.org/extensions/web-sockets/ --> <script src="https://unpkg.com/htmx.org/dist/ext/ws.js"></script> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> <link rel="stylesheet" href="/static/style.css"> </head> <body> <div class="container"> <div class="chat-window"> <div class="messages" id="messages" > <!-- Messages will be appended here --> </div> <form id="form"> <div class="input-area"> <input type="text" name="text" min="1" id="messageInput" placeholder="Type a message..."> <button type="submit">Send</button> </div> </form> </div> </div> </body> </html>

در index.html بالا، ما افزونه های لازم مانند style.css خود را که به زودی ایجاد می شود، HTMX و bootstrap 5 پیوند داده ایم.

فایل message.html چگونه باید باشد:

 <div id="messages" hx-swap-oob="beforeend"> <p class="text-small">{{ .Text }}</p> </div>

این پیام پاسخ سرور خواهد بود و با کمک HTMX به طور خودکار در کد index.html ما در مرورگر جابجا می شود.

بیشتر بخوانید

Paytm هند در جریان است


اکنون یک پوشه جدید به نام static ایجاد کنید. در داخل آن، یک فایل style.css جدید ایجاد کنید:

 body { margin: 0; padding: 0; font-family: Arial, sans-serif; background-color: #f2f2f2; } .container { display: flex; justify-content: center; align-items: center; height: 100vh; } .chat-window { width: 400px; background-color: #fff; border-radius: 10px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); } .messages { padding: 10px; overflow-y: scroll; height: 300px; } .message { margin-bottom: 10px; } .message p { background-color: #f0f0f0; border-radius: 5px; padding: 5px 10px; display: inline-block; max-width: 80%; } .input-area { padding: 10px; display: flex; } .input-area input[type="text"] { flex: 1; padding: 8px; border: 1px solid #ccc; border-radius: 5px; margin-right: 5px; } .input-area button { padding: 8px 15px; background-color: #4CAF50; color: white; border: none; border-radius: 5px; cursor: pointer; transition: background-color 0.3s; } .input-area button:hover { background-color: #45a049; } .input-area button:active { background-color: #3e8e41; }

نحوه پیکربندی فایل های استاتیک

در فایل main.g o خود، باید به Fiber بگویید که چگونه فایل‌های استاتیک شما را مدیریت کند، مخصوصاً پوشه‌ای را که باید رندر HTML را تحلیل کند. main.go را به صورت زیر به روز کنید:

 package main import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/template/html/v2" ) func main() { // Create views engine viewsEngine := html.New("./views", ".html") // Start new fiber instance app := fiber.New(fiber.Config{ Views: viewsEngine, }) // Static route and directory app.Static("/static/", "./static") // Create a "ping" handler to test the server app.Get("/ping", func(ctx *fiber.Ctx) error{ return ctx.SendString("Welcome to fiber") }) // Start the http server app.Listen(":3000") }

همانطور که در بالا مشاهده شد، یک پیکربندی به نمونه برنامه اضافه شد و همچنین مسیر استاتیک را به صورت /static/ پیکربندی کرد.

نحوه ایجاد هندلر

یک فایل جدید با نام handlers.go ایجاد کنید:

 package handlers import "github.com/gofiber/fiber/v2" type AppHandler struct{} func NewAppHandler() *AppHandler { return &AppHandler{} } func (a *AppHandler) HandleGetIndex(ctx *fiber.Ctx) error { context := fiber.Map{} return ctx.Render("index", context) }

در کد بالا، یک هندلر ایجاد کردیم که ساختار AppHandler را دریافت کرد. در صورتی که کد بزرگتر شود، این به انتزاعات کمک می کند. تابع HandleGetIndex یک اشاره گر به زمینه فیبر می گیرد و فایل index.html را رندر می کند.

در main.go :

 package main import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/template/html/v2" "github.com/steelthedev/go-chat/handlers" ) func main() { // Start new fiber instance app := fiber.New() // Create a "ping" handler to test the server app.Get("/ping", func(ctx *fiber.Ctx) error{ return ctx.SendString("Welcome to fiber") }) // create new App Handler appHandler := NewAppHandler() // Add appHandler routes app.Get("/, appHandler.HandleGetIndex) // Start the http server app.Listen(":3000") }

در بالا، ما یک کنترلر برنامه جدید ایجاد کردیم و تابع HandleGetIndex را در مسیرها اضافه کردیم. دستور go run main.go اجرا کنید. در localhost:3000 ، باید صفحه‌ای شبیه به این داشته باشید:

چت روم برش خورده
جعبه ورودی، دکمه ارسال و ناحیه نمایش چت در localhost:3000

فایل messages.go

مستقیماً یک فایل جدید در پروژه ایجاد کنید و نام آن را message.go بگذارید. این فایل میزبان ساختار پیام خواهد بود.

 package main type Message struct { Text string `json:"text"` }

فایل websocket.go

یک فایل جدید در فهرست پروژه ایجاد کنید و نام آن را websocket.go بگذارید. این تابع اصلی ایجاد سرور WebSocket، خواندن از طریق آن و نوشتن در تمام کانال ها را در خود جای می دهد:

 package main import ( "bytes" "encoding/json" "html/template" "log" "github.com/gofiber/fiber/v2" "github.com/gofiber/websocket/v2" ) type WebSocketServer struct { clients map[*websocket.Conn]bool broadcast chan *Message } func NewWebSocket() *WebSocketServer { return &WebSocketServer{ clients: make(map[*websocket.Conn]bool), broadcast: make(chan *Message), } } func (s *WebSocketServer) HandleWebSocket(ctx *websocket.Conn) { // Register a new Client s.clients[ctx] = true defer func() { delete(s.clients, ctx) ctx.Close() }() for { _, msg, err := ctx.ReadMessage() if err != nil { log.Println("Read Error:", err) break } // send the message to the broadcast channel var message Message if err := json.Unmarshal(msg, &message); err != nil { log.Fatalf("Error Unmarshalling") } s.broadcast <- &message } } func (s *WebSocketServer) HandleMessages() { for { msg := <-s.broadcast // Send the message to all Clients for client := range s.clients { err := client.WriteMessage(websocket.TextMessage, getMessageTemplate(msg)) if err != nil { log.Printf("Write Error: %v ", err) client.Close() delete(s.clients, client) } } } } func getMessageTemplate(msg *Message) []byte { tmpl, err := template.ParseFiles("views/message.html") if err != nil { log.Fatalf("template parsing: %s", err) } // Render the template with the message as data. var renderedMessage bytes.Buffer err = tmpl.Execute(&renderedMessage, msg) if err != nil { log.Fatalf("template execution: %s", err) } return renderedMessage.Bytes() }

تابع HandleWebSocket کلاینت را اضافه می کند، پیام ها را به JSON پردازش می کند و سپس پیام را به کانالی برای توزیع به همه مشتریان توسط HandleMessage اضافه می کند.

همچنین این ارتباط را زنده نگه می دارد. getMessageTemplate اساساً پیام را به message.html پردازش می کند و سپس آن را به یک بایت تبدیل می کند. سپس این بایت می تواند به عنوان پاسخ برای مشتری ارسال شود.

چگونه یک WebSocket به مسیرها و HTMX اضافه کنیم

ما باید WebSocket را به routes main.go خود اضافه کنیم:

 package main import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/template/html/v2" "github.com/gofiber/websocket/v2" "github.com/steelthedev/go-chat/handlers" ) func main() { // Start new fiber instance app := fiber.New() // Create a "ping" handler to test the server app.Get("/ping", func(ctx *fiber.Ctx) error{ return ctx.SendString("Welcome to fiber") }) // create new App Handler appHandler := NewAppHandler() // Add appHandler routes app.Get("/, appHandler.HandleGetIndex) // create new webscoket server := NewWebSocket() app.Get("/ws", websocket.New(func(ctx *websocket.Conn) { server.HandleWebSocket(ctx) })) go server.HandleMessages() // Start the http server app.Listen(":3000") }

WebSocket و مسیر آن اضافه شده است. مرحله آخر اضافه کردن تگ های HTMX به فایل index.html است:

 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Chat Room</title> <script src="https://unpkg.com/htmx.org@1.9.10" integrity="sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC" crossorigin="anonymous"></script> <!-- HTMX Websockets extension https://htmx.org/extensions/web-sockets/ --> <script src="https://unpkg.com/htmx.org/dist/ext/ws.js"></script> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> <link rel="stylesheet" href="/static/style.css"> </head> <body> <div class="container"> <div class="chat-window" hx-ext="ws" ws-connect="/ws"> <div class="messages" id="messages" hx-swap="beforeend" hx-swap-oob="beforeend"> <!-- Messages will be appended here --> </div> <form id="form" ws-send hx "> <div class="input-area"> <input type="text" name="text" min="1" id="messageInput" placeholder="Type a message..."> <button type="submit">Send</button> </div> </form> </div> </div> </body> </html>

تگ hx-ext و تگ ws-connect به URL WebSocket /ws اشاره می کنند. تگ hx-swap برای انجام دستکاری های DOM استفاده شد که پیام های ما را به بخش #messages اضافه می کند.

پس از ذخیره این، go run main.go اجرا کنید. می توانید دو پنجره مرورگر مختلف را در localhost:3000 باز کنید

اسکرین شات-از-2024-06-02-04-23-06
دو پنجره مرورگر که برای ارسال و دریافت پیام استفاده می شود

اگر WebSocket به خوبی اجرا می شود، باید بتوانید پیام هایی را از دو مرورگر به صورت بلادرنگ همانطور که در تصویر نشان داده شده است ارسال و دریافت کنید.

نتیجه

در این آموزش، نحوه ایجاد یک سرور WebSocket ساده با استفاده از Go، Fiber و HTMX را به نمایش گذاشته ایم.

شما می توانید با گفت ن ویژگی های اضافی مانند ClientID، احراز هویت و مدیریت کاربر، این پروژه را ادامه دهید و بهبود بخشید. می توانید از مخزن پروژه در اینجا دیدن کنید: github.com/steelthedev/go-chat

خبرکاو

ارسال نظر




تبليغات ايهنا تبليغات ايهنا

تمامی حقوق مادی و معنوی این سایت متعلق به خبرکاو است و استفاده از مطالب با ذکر منبع بلامانع است