ginでチャットのような機能を作成する【Go言語】

前提

今回紹介する実装は、前に投稿した下記の記事をもとに作成しています。

ginを使って簡単なログイン画面を作ってみる【Go言語】
使用環境 フレームワーク ・Gin(Webフレームワーク) ・Gorm(DB関連のフレームワーク) DB ・Postgresql テーブル定義 CREATE TABLE public.users ( id integer NOT NULL ...

まずは、テーブルの作成から

テーブル構成は下記のようにしています。 ・チャットテーブル 投稿されたチャットの情報を保持するテーブルです。

-- Table: public.chats

-- DROP TABLE public.chats;

CREATE TABLE public.chats
(
  id integer NOT NULL DEFAULT nextval('chats_id_seq'::regclass),
  created_at timestamp with time zone,
  updated_at timestamp with time zone,
  deleted_at timestamp with time zone,
  chat_text text,
  contributer text,
  bote_date timestamp with time zone,
  room_id text,
  CONSTRAINT chats_pkey PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE public.chats
  OWNER TO "USER";

-- Index: public.idx_chats_deleted_at

-- DROP INDEX public.idx_chats_deleted_at;

CREATE INDEX idx_chats_deleted_at
  ON public.chats
  USING btree
  (deleted_at);

・ユーザテーブル 投稿するユーザの情報を保持するテーブルです。

-- Table: public.users

-- DROP TABLE public.users;

CREATE TABLE public.users
(
  id integer NOT NULL DEFAULT nextval('users_id_seq'::regclass),
  created_at timestamp with time zone,
  updated_at timestamp with time zone,
  deleted_at timestamp with time zone,
  user_id text NOT NULL,
  password text,
  regist_date text,
  last_login text,
  user_name text,
  CONSTRAINT users_pkey PRIMARY KEY (id, user_id)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE public.users
  OWNER TO "USER";

-- Index: public.idx_users_deleted_at

-- DROP INDEX public.idx_users_deleted_at;

CREATE INDEX idx_users_deleted_at
  ON public.users
  USING btree
  (deleted_at);

goで扱うデータ

・ChatList.go

package data

import (
	"time"
)

//Chat Chatsテーブル情報
type ChatList struct {
	ChatText    string    //投稿文
	UserId      string    //ユーザID
	Contributer string    //投稿者
	BoteDate    time.Time //投稿日
	RoomId      string    //部屋ID
}

・Chat.go

package data

import (
	"github.com/jinzhu/gorm"
	"time"
)

//Chat Chatsテーブル情報
type Chat struct {
	gorm.Model
	ChatText    string
	Contributer string    //投稿者
	BoteDate    time.Time //投稿日
	RoomId      string    //部屋ID
}

画面の実装

{{}}で囲まれた箇所は実際にGo側から渡される値を表示しています。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="/css/style.css" />
    <title>Gin Application</title>
</head>
<body>
    <form method="post" action="/chatPost">
        <div class="main-content">
            <h1>ChatList</h1>
            <div class="chatList">
                {{$i := .userId}}
                {{range .chatList}}
                    {{if eq  $i .UserId}}
                        <!-- 自分が投稿したチャットの内容-->
                        <div class="minePost post">
                            <!--投稿者-->
                            <div class="contributer">{{.Contributer}}</div>
                            <!--投稿文-->
                            <div class="text">{{.ChatText}}</div>
                        </div><br>
                    {{else}}
                       <!-- 自分以外が投稿したチャットの内容-->
                        <div class="otherPost post">
                            <!--投稿者-->
                            <div class="contributer">{{.Contributer}}</div>
                            <!--投稿文-->
                            <div class="text">{{.ChatText}}</div><br>
                        </div>
                    {{end}}
                {{end}}
            </div>
            <input type="text" name="chatText" placeholder="入力してください" style="width: 90%;">
            <input type="submit" name="botButton" value="投稿" style="width: 8%;">
        </div>
    </form>
</body>
</html>

 

チャット情報の取得を行う。

・chatListModel.go 実際にDBからデータを取得します。

package model

import (
	"github/GoSumple/gin_sumple/go/data"
	"github/GoSumple/gin_sumple/go/db"
)

//GetChatList userId,passwordをもとにusers情報を取得します。
func GetChatList(roomId string) []data.ChatList {
	d := db.GormConnect()

	//チャット情報の取得
	selData := []data.ChatList{}
	d.Raw("select "+
		"t1.chat_text,t2.user_id,t2.user_name as contributer,t1.bote_date,"+
		"t1.room_id from chats t1 "+
		"inner join users t2 on t1.contributer = t2.user_id "+
		"where t1.room_id = ? ", roomId).Scan(&selData)
	defer d.Close()
	return selData
}

取得情報を画面へ渡す

・chatList.go

/*
 */
package web

import (
	"github.com/gin-contrib/sessions"
	"github.com/gin-gonic/gin"
	"github/GoSumple/gin_sumple/go/data"
	"github/GoSumple/gin_sumple/go/db"
	"github/GoSumple/gin_sumple/go/model"
	"net/http"
	"time"
)

//ChatList chatList.htmlのGET処理を実装します
func ChatList(ctx *gin.Context) {

	session := sessions.Default(ctx)
	userid := session.Get("UserId").(string)
	chatList := model.GetChatList(userid)

	ctx.HTML(http.StatusOK, "chatList.html", gin.H{
		"chatList": chatList,
		"userId":   userid,
	})
}

//ChatPost chatList.htmlのPOST処理(/chatPost)を実装します
func ChatPost(ctx *gin.Context) {
	chattext, _ := ctx.GetPostForm("chatText")
	session := sessions.Default(ctx)
	userid := session.Get("UserId").(string)
	chat := data.Chat{}
	chat.ChatText = chattext
	chat.Contributer = userid
	chat.BoteDate = time.Now()
	chat.RoomId = "111"
	db.ChatInsert(chat)

	ctx.Redirect(http.StatusSeeOther, "/chatList")
}

今回紹介している処理はすべてGitHubに挙げているのでそちらも参考にしてください

https://github.com/tkwest3143/GoSumple/tree/master/gin_sumple