Technology used
golang
goroutines
websockets
webserver
channels
Frontend
react
backendを作成
①backendディレクトリとmain.jsを作成
# バックエンド用のディレクトリを作成
mkdir backend
touch main.go
cd backend
go mod init chatapplication
go get github.com/gorilla/websocket
go run main.go
②main.goを作成する
package main
import (
customwebsocket "chatapplication/websocket"
"log"
"net/http"
)
func serverWs(pool *customwebsocket.Pool,w http.ResponseWriter, r *http.Request) {
log.Println("This is working")
conn, err := customwebsocket.Upgrade(w,r)
if err != nil {
log.Println(err)
return
}
client := &customwebsocket.Client{
Conn: conn,
Pool: pool,
}
pool.Register <- client
client.Read()
}
func setupRoutes(){
log.Println("This is working")
pool := customwebsocket.NewPool()
go pool.Start()
http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
serverWs(pool, w, r)
})
}
func main() {
setupRoutes()
http.ListenAndServe(":9000", nil)
};
③backendにwebsocketフォルダとwebsocket.goを作成する
mkdir websocket
touch websocket.go
package customwebsocket
import (
"log"
"net/http"
"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}
func Upgrade(w http.ResponseWriter, r *http.Request) (*websocket.Conn, error){
upgrader.CheckOrigin = func(r *http.Request) bool { return true }
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Println("websocket connection error:", err)
return nil, err
}
return conn, nil
}
cd backend
go mod tidy
④backendにwebsocket/client.goを作成する
package customwebsocket
import (
"fmt"
"sync"
"github.com/gorilla/websocket"
)
type Client struct{
Conn * websocket.Conn
Pool *Pool
mu sync.Mutex
}
type Message struct {
Type int `json:"type"`
Body string `json:"body"`
}
func(c *Client) Read(){
defer func () {
c.Pool.Unregister <- c
c.Conn.Close()
}()
for {
msgType, msg, err := c.Conn.ReadMessage()
if err != nil {
fmt.Println(err)
return
}
m := Message{Type: msgType, Body: string(msg)}
c.Pool.Broadcast <- m
fmt.Println("msg recived===>>>\n", m)
}
}
⑤backendにwebsocket/pool.goを作成する
package customwebsocket
import "fmt"
type Pool struct{
Register chan *Client
Unregister chan *Client
Clients map [*Client] bool
Broadcast chan Message
}
func NewPool() *Pool{return &Pool{
Register: make(chan *Client),
Unregister: make(chan *Client),
Clients: make(map [*Client] bool),
Broadcast: make(chan Message),
}}
func(pool *Pool) Start(){
for {
select{
case client := <-pool.Register:
pool.Clients[client] = true
fmt.Println("total connection ppol:- ", len(pool.Clients))
for k, _ := range pool.Clients{
fmt.Println(k)
k.Conn.WriteJSON(Message{Type: 1, Body: "New User Joined"})
}
case client := <-pool.Unregister:
delete(pool.Clients,client)
fmt.Println("total connection ppol:- ", len(pool.Clients))
for k, _ := range pool.Clients{
fmt.Println(k)
k.Conn.WriteJSON(Message{Type: 1, Body: "User Disconnected"})
}
case msg := <-pool.Broadcast:
fmt.Println("broadcasting a message")
for k, _ := range pool.Clients {
if err := k.Conn.WriteJSON(msg); err != nil {
fmt.Println(err)
return
}
}
}
}
}
Frontendを作成する
①frontendディレクトリ
mkdir frontend
cd frontend
npx create-react-app <プロジェクト>
②srcにapiフォルダとindex.jsを作成する
var socket = new WebSocket('ws://localhost:9000/ws');
let connect = (cb) => {
console.log('connecting');
socket.onopen = () => {
console.log('websocket connected successfully');
};
socket.onmessage = (msg) => {
console.log('message from socket', msg);
cb(msg);
};
socket.onclose = (event) => {
console.log('websocket connected closed', event);
};
socket.onerror = (error) => {
console.log('websocket error', error);
};
};
let sendMsg = (msg) => {
console.log('msg send:-', msg);
socket.send(msg);
};
export { connect, sendMsg };
mkdir api
touch index.js
③srcにComponents/Header/Header.jsxを作成する
import React from 'react';
import './Header.scss';
const Header = () => {
return (
<div>
<h2>Go chat application in react</h2>
</div>
);
};
export default Header;
④srcにComponents/Header/Header.scssを作成する
.header {
background-color: gray;
color: #ffeda3;
h2 {
font-size: 5em;
text-align: center;
}
}
⑤srcにComponents/Header/index.jsを作成する
import Header from './Header';
const index = () => {
return <div>index</div>;
};
export default Header;
cd frontend
cd chat
npm i sass --save-dev
⑥srcにComponents/ChatInput/ChatInput.jsxを作成する
import React, { Component } from 'react';
import './ChatInput.scss';
class ChatInput extends Component {
render() {
return (
<div className='ChatInput'>
<input onKeyDown={this.props.send} placeholder='Enter a message...' />
</div>
);
}
}
export default ChatInput;
⑦srcにComponents/ChatInput/ChatInput.scssを作成する
.ChatInput {
width: 90%;
display: block;
margin: auto;
input {
padding: 10px;
margin: 0;
background-color: white;
font-size: 15px;
border: none;
border-radius: 5px;
border: 1px solid black;
width: 98%;
}
}
⑧srcにComponents/ChatInput/index.jsを作成する
import ChatInput from './ChatInput';
const index = () => {
return <div>index</div>;
};
export default ChatInput;
⑨srcにComponents/Message/Message.jsxを作成する
import React, { Component } from 'react';
import './Message.scss';
class Message extends Component {
constructor(props) {
super(props);
let temp = JSON.parse(this.props.message);
this.state = { message: temp };
}
render() {
return <div className='Message'>{this.state.message.body}</div>;
}
}
export default Message;
⑩srcにComponents/Message/Message.scssを作成する
.Message {
display: block;
background-color: lightblue;
margin: 10px auto;
padding: 10px 20px;
border-radius: 5px;
box-shadow: 0 5px 15px -5px black;
clear: both;
&.me {
color: rgb(138, 131, 245);
float: right;
}
}
⑪srcにComponents/Message/index.jsを作成する
import Message from './Message';
export default Message;
⑫srcにComponents/ChatHistory/ChatHistory.jsxを作成する
import React, { Component } from 'react';
import './ChatHistory.scss';
import Message from '../Message';
class ChatHistory extends Component {
render() {
const messages = this.props.ChatHistory.map((msg) => (
<Message key={msg.timeStamp} message={msg.data} />
));
console.log(messages);
return (
<div className='ChatHistory'>
<h2>Chat History</h2>
{messages}
</div>
);
}
}
export default ChatHistory;
⑬srcにComponents/ChatHistory/ChatHistory.scssを作成する
.ChatHistory {
background-color: lightcoral;
margin: 0;
padding: 20px;
h2 {
margin: 0;
padding: 0;
color: white;
}
}
⑭srcにComponents/ChatHistory/index.jsを作成する
import ChatHistory from './ChatHistory';
export default ChatHistory;
⑮src/App.jsを編集する
import Header from './Components/Header';
import ChatInput from './components/ChatInput';
import './App.css';
import React, { Component } from 'react';
import { connect, sendMsg } from './api';
import ChatHistory from './components/ChatHistory';
class App extends Component {
constructor(props) {
super(props);
this.state = {
chatHistory: [],
};
}
componentDidMount() {
connect((msg) => {
console.log();
this.setState((prevState) => ({
chatHistory: [...prevState.chatHistory, msg],
}));
console.log(this.state);
});
}
send(event) {
if (event.keyCode === 30) {
sendMsg(event.target.value);
event.target.value = '';
}
}
render() {
return (
<div className='App'>
<Header />
<ChatHistory chatHistory={this.state.chatHistory} />
<ChatInput send={this.send} />
</div>
);
}
}
export default App;
参考サイト
GO + REACT Fullstack App - Chat Application PART- 1 IN HINDI
GO + REACT Fullstack App - Chat Application PART- 2 IN HINDI
GO + REACT Fullstack App - Chat Application PART- 3 IN HINDI
GO + REACT Fullstack App - Chat Application PART- 4 IN HINDI
GO + REACT Fullstack App - Chat Application PART- 5 IN HINDI
GO + REACT Fullstack App - Chat Application PART- 6 IN HINDI
GO + REACT Fullstack App - Chat Application PART- 7 IN HINDI
GO + REACT Fullstack App - Chat Application PART- 8 IN HINDI
GO + REACT Fullstack App - Chat Application PART- 9 IN HINDI