go+iris+jwt+mysql+xorm+viper, ein einfacher Chatroom für das Iris-Projekt, einschließlich Anmeldung, Registrierung, privatem Chat und Gruppenchat.
Werfen Sie zunächst einen Blick auf die Front-End-Einführung unter diesem Dokument, um zu erfahren, wie man es bedient (aufgrund der begrenzten Energie ist die Benutzeroberfläche nicht besonders benutzerfreundlich).
Greifen Sie auf die Demo-Adresse zu. Wenn der Status des kleinen Symbols oben normal ist, können Sie darauf zugreifen. Es kann in den Ruhezustand wechseln und Sie müssen einige Sekunden warten.
Das Projekt schreibt derzeit nur MySQL-bezogene Anpassungen, aber mit xorm ist es nicht schwierig, andere Datenbanken zu unterstützen. Dies ist möglich, aber nicht erforderlich. Wenn Sie zu faul sind, es selbst auszuführen, werfen Sie einen Blick darauf unter der Demo-URL. Wenn Sie interessiert sind, hat derzeit niemand MySQL.
Ursprünglich wollte ich SQLite unterstützen, damit keine Datenbankparameter konfiguriert werden müssen. Wenn man jedoch bedenkt, dass zum Kompilieren von SQLite unter Windows die Konfiguration der GCC-Umgebung erforderlich ist, ist dies problematischer, es gibt jedoch keinen schnellen Starteffekt und es ist einfach nicht vollständig Daher werden andere Datenbanken vorerst nicht unterstützt (fügen Sie eines Tages weitere hinzu, wenn Sie Zeit haben).
Das Projekt muss also nur die folgenden Parameter konfigurieren
git clone https://github.com/JabinGP/demo-chatroom.git
cd demo-chatroom
// 复制config.toml.example 为 config.toml 并填写数据库信息,或者可选修改端口号
go run main.go
Der Standardport ist 8888. Greifen Sie nach dem Start auf http://localhost:8888
zu
Ich habe React verwendet, aber viele kleine Details sind nicht auf die Größe des Mobiltelefons abgestimmt. Wenn Sie den Computer öffnen, sieht es komfortabler aus. Begnügen wir uns damit. Der Fokus liegt auf Letzterem.
Das Chat-Feld stellt das Fenster so ein, dass es automatisch nach unten scrollt, aber die API wird von React bereitgestellt und ist mit vielen Browsern nicht kompatibel. Dieses Problem kann durch die Verwendung des Chrome-Browsers gelöst werden.
Gehen Sie nach der Registrierung manuell zurück und wählen Sie „Anmelden“. Der rote Name steht für die öffentliche Rede und der graue Name für den privaten Chat. Wenn nicht angegeben, lautet der Standard Öffentliche Rede. Nach der Angabe können nur die entsprechenden Benutzer die Informationen sehen.
Ihr Benutzername wird im blauen Feld angezeigt. Klicken Sie hier, um sich direkt abzumelden.
Das API-Format basiert auf einem erholsamen Design und die Anmeldefunktion wird mit JWT ausgeführt. Bei der Anforderung muss JWT angegeben werden. Weitere Informationen finden Sie in der JWT-Praxis von Golang Iris Praktisch zum Testen. Die Gültigkeitsdauer der JWT-Ausstellung ist nur auf 20 Minuten festgelegt. Sie muss erneut angemeldet werden.
Das API-Anforderungsformat ist das gleiche wie die allgemeine Schnittstelle. Get verwendet Parameter, und Post, Put, Delete usw. verwenden Json im Body, um Parameter zu übergeben.
Das Rückgabeformat ist ziemlich umstritten. Einige Leute befürworten die Verwendung des vollständigen 200-HTTP-Statuscodes und das Hinzufügen eines Codes zum Rückgabeinhalt, wie zum Beispiel diesen:
// 注册错误时
// http status 200
{
"code" : 40001 ,
"msg" : "注册用户名非法"
}
// 注册成功时
// http status 200
{
"code" : 200 ,
"msg" : "成功" ,
"data" : {
"username" : " JabinGP " ,
"id" : 3
}
}
Andere befürworten die Verwendung vollständiger http-Statuscodes zur Anzeige von Fehlern:
// 注册错误时
// http status 400
{
"msg" : "注册用户名非法"
}
// 注册成功时
// http status 200
{
"username" : " JabinGP " ,
"id" : 3
}
Tatsächlich haben beide oben genannten Ansätze ihre eigenen Vor- und Nachteile:
Basierend auf der obigen Situation werde ich die beiden kombinieren:
Bei Erfolg wird der HTTP-Statuscode 200 zurückgegeben
// 注册成功时
// http status 200
{
"username" : " JabinGP " ,
"id" : 3
}
Wenn ein Fehler auftritt, wählen Sie mehrere häufig verwendete Statuscodes aus, um den Fehler auszudrücken: 400 (Anforderungsfehler), 500 (interner Serverfehler), 404 (nicht gefunden), 401 (Authentifizierungsfehler), klassifizieren Sie den Fehler grob und geben Sie dann Anpassen a zurück Code, Nachricht und Details in den Daten, um die detaillierte Fehlerursache darzustellen:
// 注册失败
// http status 400
{
"code" : 6 ,
"msg" : "数据检验失败" ,
"detail" : "用户名已存在"
}
// 登录失效
// http status 401
{
"code" : 8 ,
"msg" : "未认证登录" ,
"detail" : " Token is expired "
}
Nach dieser Kombination ist der erfolgreiche Rückruf erfolgreich und es besteht keine Notwendigkeit, res.data.data wiederholt zu schreiben. Der Fehlerrückruf behandelt nur Fehler, die anhand des HTTP-Statuscodes beurteilt und weiter codiert werden können detailliert beschrieben, um mit Fehlern umzugehen.
Die API-Liste lautet wie folgt. Ersetzen Sie localhost durch mike.jabingp.cn, oder Sie können direkt eine Anfrage an das Demo-Backend stellen:
Funktion | Anfragemethode | Adresse |
---|---|---|
Holen Sie sich das Login-Token | POST | http://localhost:8888/v1/login |
Benutzer finden | ERHALTEN | http://localhost:8888/v1/user |
registrieren | POST | http://localhost:8888/v1/user |
Benutzer ändern Informationen selbst | SETZEN | http://localhost:8888/v1/user |
Benutzer sendet Nachricht | POST | http://localhost:8888/v1/message |
Benutzer erhält Informationen | ERHALTEN | http://localhost:8888/v1/message |
Der Benutzer erhält Token-Informationen | ERHALTEN | http://localhost:8888/v1/token/info |
Detaillierte Anfrageparameter können in der Postman-API-Dokumentation des Demo-Chatrooms eingesehen werden.
Oder sehen Sie sich den Quellcode an. Die Anforderungsparameter können in model/reqo
und die Antwortparameter in model/reso
AJAX ist nicht die beste Wahl für die Chat-Funktion, WebSocket ist besser, aber ich wurde gebeten, AJAX zu verwenden, also habe ich mich nicht für Letzteres entschieden.
Das Frontend des Projekts ist relativ einfach, da es nur als Demo verwendet wird.
Mein Englisch ist nicht sehr gut und die Codekommentare sind nur auf Englisch, weil ich zu faul bin, die Eingabemethode zu ändern.
Dies ist das erste Mal, dass ich Go zum Entwickeln eines Webprojekts verwende, und es ist auch das erste Mal, dass ich React zum Schreiben des Frontends verwende. Da das Frontend der Projektstruktur (xjbx) nicht viel Aufmerksamkeit schenkt, werde ich es nicht tun Ich kompiliere das Projekt und lege es zur besseren Lesbarkeit in den Assets-Ordner. Es ist jedoch nicht erforderlich, das Frontend separat zu starten Wirkung. Wenn ich noch Zeit habe, werde ich darüber nachdenken, eine minimalistische Version in nativer Sprache als Referenz für alle zu schreiben.
Als ich zum ersten Mal ein ORM zum Betreiben einer Datenbank verwendete, fand ich es sehr schwierig, SQL von Hand zu schreiben. Es gab viele gewünschte Effekte und ich konnte nach langem Durchsehen der Dokumente keine Lösung finden . Vielleicht erwäge ich später die Verwendung von SQLX für die Rekonstruktion.
In letzter Zeit interessiere ich mich mehr für Go und erhielt die Aufgabe, einen einfachen Chatroom zu schreiben. Ich stellte fest, dass es derzeit nur wenige Projektpraktiken in Iris gibt, nur einige Beispiele auf HelloWorld-Ebene, also habe ich mich dafür entschieden, Go zu verwenden , und stellen Sie es dann als Open Source zur gegenseitigen Bezugnahme zur Verfügung. Natürlich basiert die Gestaltung der Projektstruktur vollständig auf meiner begrenzten Entwicklungserfahrung. Bitte geben Sie Ihre wertvolle Meinung zu allen unangemessenen Aspekten ab.
Für dieses Projekt gelten die folgenden Anforderungen
Die Anmeldefunktion wird dieses Mal mit JWT
implementiert. Auf die Vor- und Nachteile von JWT
und Session
wird nicht näher eingegangen.
AJAX-basiert ist ein Muss für alle Front-End- und Back-End-Trennungsprojekte, daher wird diese Funktion nicht zu ausführlich besprochen. Der Fokus liegt hier nicht auf der Aktualisierung. Was ist die Schwierigkeit?
Die Betriebslogik des Benutzers besteht darin, Daten im Chatraum zu senden und diese dann auszusenden. Die Chat-Schnittstelle sollte die von ihm selbst gesendeten Daten anzeigen und die von anderen gesendeten Daten in Echtzeit aktualisieren.
Das Front-End und das Back-End kommunizieren über AJAX. Die Front-End-Sendedaten und die Back-End-Sendedaten können ausgedrückt werden als
Was ist hier das Problem? Das Problem besteht darin, dass das Frontend nur aktiv Anfragen initiieren kann und das Backend nur Anfragen annehmen kann. Dies bedeutet, dass die neuesten Nachrichten niemals in Echtzeit aktiv vom Backend an das Frontend gesendet werden können. Die neuesten Nachrichten können nur zuerst im Backend gespeichert und dann darauf gewartet werden, dass das Frontend eine Anfrage initiiert, bevor das Backend Daten zurückgeben kann.
Da das Backend nicht in der Lage ist, Nachrichten aktiv an das Frontend zu senden, besteht die Lösung für Benutzer, um die neuesten Daten zu erhalten, darin, dass das Frontend einen Timer einstellt每隔一段比较短的时间就请求一次后台接口(轮询)
Die Daten können laufend aktualisiert werden.
Das Frontend hat sich entschieden, AJAX zu verwenden, um die Hintergrundschnittstelle regelmäßig abzufragen, um die neuesten Daten zu erhalten. Aus Gründen der Echtzeitdaten beträgt das Abfrageintervall小于1s
Dies bringt ein weiteres Problem mit sich: Das Backend muss nicht jedes Mal alle Daten übertragen, die durch die Datengröße verursacht werden Die Beurteilung neuer Daten durch das Front-End bedeutet, dass das Back-End jedes Mal Daten zurückgeben muss, die das Front-End nicht empfangen hat. Das Problem ist: Woher weiß das Back-End, welche Informationen das Front-End erhalten hat?
Dies erfordert die Verwendung自增主键
der Nachricht. Das Front-End muss bei jeder Anfrage nur最后的消息的主键
übertragen. Durch Wiederholen und automatisches Erhöhen können wir das Verhältnis leicht ermitteln. Die Daten mit einem großen Primärschlüssel sind die Daten, die das Frontend noch nicht empfangen hat.
Sprache
rahmen
Datenspeicherung
Technologie
Aufgrund der Verwendung des Xorm-Datenbank-ORM-Frameworks werden die folgenden Tabellen automatisch generiert und enthalten das Feld
xxxxxx_at
Basierend auf den oben genannten Anforderungen wurden zwei Tabellen, users
und messages
entworfen.
Schlüsselfelder
Struktur der Datenbanktabelle
Feld | Typ | Null | Schlüssel | Standard | Extra |
---|---|---|---|---|---|
AUSWEIS | bigint(20) | NEIN | PRI | NULL | auto_increment |
Benutzername | varchar(255) | JA | NULL | ||
Passwort | varchar(255) | JA | NULL | ||
Geschlecht | bigint(20) | JA | NULL | ||
Alter | bigint(20) | JA | NULL | ||
Interesse | varchar(255) | JA | NULL | ||
erstellt_at | Datum/Uhrzeit | JA | NULL | ||
aktualisiert_at | Datum/Uhrzeit | JA | NULL | ||
gelöscht_at | Datum/Uhrzeit | JA | NULL |
Schlüsselfelder
Struktur der Datenbanktabelle
Feld | Typ | Null | Schlüssel | Standard | Extra |
---|---|---|---|---|---|
AUSWEIS | bigint(20) | NEIN | PRI | NULL | auto_increment |
Absender_ID | bigint(20) | JA | NULL | ||
Empfänger-ID | bigint(20) | JA | NULL | ||
Inhalt | varchar(255) | JA | NULL | ||
send_time | bigint(20) | JA | NULL | ||
erstellt_at | Datum/Uhrzeit | JA | NULL | ||
aktualisiert_at | Datum/Uhrzeit | JA | NULL | ||
gelöscht_at | Datum/Uhrzeit | JA | NULL |
Die folgende Struktur basiert auf persönlichen Erfahrungen. Wenn etwas unangemessen ist, geben Sie uns bitte Ihr wertvolles Feedback.
pojo
Es ist leicht zu verstehen, dass es sich um eine Entität handelt, die der Datenbank entspricht, aber keine Eins-zu-eins-Korrespondenz mit den Datenbankfeldern erforderlich ist.
reqo (Anfrageobjekt), reso (Antwortobjekt)
Wenn Anfragen über verschiedene Schnittstellen gestellt werden, unterscheiden sich auch die Parameter, die übertragen werden können, und die Antwortdaten, sodass für jede Schnittstelle eine entsprechende Anforderungsentität und Antwortentität entworfen werden.
Das Folgende ist mein persönliches Verständnis
Regler
Die Hauptaufgabe besteht darin, die Anforderungsparameter der Anforderung zu akzeptieren, sie in reqo umzuwandeln, eine einfache Überprüfung der Anforderungsparameter durchzuführen (meine persönliche Definition ist eine Überprüfung, die nichts mit der Datenbank zu tun hat, z. B. ungleich Null, ungleich Null) und aufzurufen Die Funktion der Serviceschicht zum Erhalten des Pojo-Ergebnisses und die Konvertierung des Pojo-Ergebnisses werden gekapselt und in reso zurückgegeben.
Service
Die Hauptaufgabe besteht darin, die Schnittstelle der Dao-Schicht weiter zu kapseln und eine gemeinsame Schnittstelle für den Controller bereitzustellen. Die zurückgegebenen Daten können im Dienst überprüft werden, z. B. (Hinzufügen neuer Benutzer, Überprüfen, ob). der Benutzername wird wiederholt).
Dao
Grundsätzlich entspricht eine Methode hier direkt einer SQL-Anweisung ohne jegliche Überprüfung. Die empfangenen Daten gelten als zuverlässig (sie wurden durch die Parameter der Controller- und Service-Schichten überprüft) und die zurückgegebenen Daten können POJO sein.