[go] 聊天室服务器端五--数据库

源码地址: https://github.com/JianBiHua/go_line_chat

说了有数据库的,开始喽

这节重新发下代码,改了点东西。
我发现了一个小技巧:
Get(cmd string, f func(…interface{}), dest …interface{}) error 中有个传递可变参数的地方,应该传成dest…,否则将被当成一个参数处理。

Sqlit3Impl.go

package sql

import (
	"GoWorkspace/go_line_chat/src/server/chatlog"
	"database/sql"
	"errors"
	"fmt"

	_ "github.com/mattn/go-sqlite3"
)

// Sqlite3Impl is sqlite3 impl
type Sqlite3Impl struct {
	db *sql.DB
}

var instance *Sqlite3Impl

// GetInstance is 模拟单例实现功能
func GetInstance() *Sqlite3Impl {
	if instance == nil {
		instance = new(Sqlite3Impl)
	}

	return instance
}

// NewSqlite3Impl is static create sqlite3 impl
func NewSqlite3Impl() *Sqlite3Impl {
	var s = new(Sqlite3Impl)
	return s
}

// log is show log when Chat mode is SqlMode
func (s *Sqlite3Impl) log(msg string) {
	chatlog.Append(chatlog.LOGSQL, msg)
}

// Open 打开数据库,并创建表
//
// out:
// error: 打开数据库时的错误。
func (s *Sqlite3Impl) Open(path string) error {
	// 打开数据库
	var err error
	s.db, err = sql.Open("sqlite3", path)
	fmt.Printf("open sql: " + path)
	if err == nil {
		s.log("Sqlite3 Is Open")
	} else {
		s.log(fmt.Sprintf("Open sqlite3 error: %v", err))
	}

	return err
}

// Close 关闭数据库
func (s *Sqlite3Impl) Close() {
	s.log("Sqlite3 Is Closed")

	s.db.Close()
}

// CreateTable is 创建数据表
// func (s *Sqlite3Impl) createTable() {
// 	var err error
// 	err = createTable(SQLCommandUser)
// 	s.log(fmt.Sprintf("error: %v, %s", err, SQLTableUser))
// 	err = createTable(SQLCommandUserChatGroup)
// 	s.log(fmt.Sprintf("error: %v, %s", err, SQLTableChatGroup))
// 	err = createTable(SQLCommandUserChatGroupMember)
// 	s.log(fmt.Sprintf("error: %v, %s", err, SQLTableChatGroupMember))
// 	err = createTable(SQLCommandUserChatMsg)
// 	s.log(fmt.Sprintf("error: %v, %s", err, SQLTableChatMsg))
// 	err = createTable(SQLCommandFriends)
// 	s.log(fmt.Sprintf("error: %v, %s", err, SQLTableFriends))
// }
func (s *Sqlite3Impl) CreateTable(cmd string) error {
	_, err := s.db.Exec(cmd)
	return err
}

// UpdateOrDelete is run sql command
//
// Example:
//
// 	delete:
//	err := UpdateOrDelete(fmt.Spintf("DELETE FROM UserTable1 WHERE id=1"))
//
//	update:
//	err := UpdateOrDelete(fmt.Spintf("UPDATE UserTable1 SET userName=\"user2\",password=\"password2\" WHERE id=1")
//
func (s *Sqlite3Impl) UpdateOrDelete(prepare string) (int64, error) {
	//插入数据
	// stmt, err := s.db.Prepare(prepare)
	// if err != nil {
	// 	return -1, err
	// }
	// defer stmt.Close()

	res, err := s.db.Exec(prepare)
	if err != nil {
		return -1, err
	}

	id, err := res.RowsAffected()
	if err != nil {
		return -1, err
	}

	return id, err
}

// Insert is insert sql object to table
//
// Example:
//
// Insert(fmt.Sprintf("INSERT INTO %s(userName, password) values(%s,%s)",
//		sql.SQLTableUser, "user", "password"))
func (s *Sqlite3Impl) Insert(prepare string) (int64, error) {
	//插入数据
	// stmt, err := s.db.Prepare(prepare)
	// if err != nil {
	// 	return -1, err
	// }
	// defer stmt.Close()

	res, err := s.db.Exec(prepare)
	if err != nil {
		return -1, err
	}

	id, err := res.LastInsertId()
	if err != nil {
		return -1, err
	}

	return id, err
}

// Get is get data base
//
// Example:
// var cmd = fmt.Sprintf("SELECT id,userName,password FROM UserTable1 WHERE id=%d", user.id)
// err := Get(cmd, func(p ...interface{}){
// 	for key, value := range param {
// 		fmt.Print("", key, value)
// 	}
//}, &userName, &password)
//
func (s *Sqlite3Impl) Get(cmd string, f func(...interface{}), dest ...interface{}) error {
	rows, err := s.db.Query(cmd)
	if err != nil {
		s.log(fmt.Sprintf("Get error : %v", err))
		return err
	}

	defer rows.Close()

	var success = false

	for rows.Next() {
		// 这里有个小技巧:
		// dest... : 就是告诉Scan,我传的是一个可变参数,而不是一个参数。
		err := rows.Scan(dest...)
		if err != nil {
			s.log(fmt.Sprintf("Get error : %v", err))
			fmt.Printf(fmt.Sprintf("Get error : %v", err))
			return err
		}

		// 返回可变参数
		f(dest...)
		success = true
	}

	if success {
		return nil
	}

	return errors.New("not found")
}

这个代码基本都是百度的,拿来封装了下.
这个不是我们的核心,因为这个真没什么东西,就是一个简单的sqlite3的操作

为啥要用sqlite3呢?

  1. 因为这个库简单呀,系统自带,不用安装。
  2. 不用配置
  3. 同样可以学习数据库的知识(sql语句)

核心来了sqlCommon.go

这个才是重点;

  1. 定义了五个数据库。
  2. 定义了功能;注册/创建聊天组/添加删除组员/添加好友/
  3. 修改了部分数据项。
package sql

// sql names define
const (

	// 数据库名称
	SQLDataBaseName = "LineChat.db"

	// 用户表
	//
	// 用来保存用户的信息,用户名密码等.
	SQLTableUser = "ChatUser"

	// 聊天组表
	//
	// 用来保存用户聊天组的信息。
	SQLTableChatGroup = "ChatGroup"

	// 聊天组表
	//
	// 用来保存用户聊天组组员的信息。
	SQLTableChatGroupMember = "ChatGroupMember"

	// 聊天内容信息表
	//
	// 用来保存各组的聊天信息的表.
	SQLTableChatMsg = "ChatMsg"

	// 好友信息表
	//
	// 用来保存好友信息的表.
	SQLTableFriends = "ChatFriends"
)

// create database and tables sql command
const (
	// create User Table's sql command
	//
	// table member item info:
	// id :
	// user : 用户名
	// password : 密码
	// sex : 性别
	// name : 显示的名称
	// age : 年龄
	// icon : 头像路径
	// signature : 个性签名
	// joinDate : 创建日期时间
	// lastDate : 最后一次登陆日期时间
	// status : 当前状态, 0: 离线 1: 在线  2: 隐身 3: 免打扰 等等..
	SQLCommandUser = "CREATE TABLE IF NOT EXISTS " + SQLTableUser +
		`(
			"id" INTEGER PRIMARY KEY AUTOINCREMENT,
			"userName" varchar(30) unique,
			"password" varchar(30),
			"sex" int(2) default 0,
			"name" varchar(20) default "",
			"age" TIMESTAMP default (datetime('now', 'localtime')) ,
			"icon" varchar (200) default "",
			"signature" varchar (500) default "",
			"joinDate" TIMESTAMP default (datetime('now', 'localtime')),
			"lastDate" TIMESTAMP default (datetime('now', 'localtime')),
			"status" int(5) default 0
		); 
		` +
		"CREATE INDEX IF NOT EXISTS User ON " + SQLTableUser + "(userName);"

	// create User Chat Group Table's sql command
	//
	// table member item info:
	// id :
	// name : 组名称。
	// signature: 组介绍,个性签名
	// max: 最大个数
	// icon: 图标路径
	// createDate: 创建时间
	// type: 组类型,
	SQLCommandUserChatGroup = "CREATE TABLE IF NOT EXISTS " + SQLTableChatGroup +
		`(
			"id" INTEGER PRIMARY KEY AUTOINCREMENT,
			"name" varchar(20) default NULL,
			"signature" varchar(500) default NULL,
			"max" int(8) default 100,
			"type" int(8) default 0,
			"icon" varchar(200) default "",
			"createDate" TIMESTAMP default (datetime('now', 'localtime'))
		);
	`

	// create User Chat Group member Table's sql command
	//
	// table member item info:
	// id :
	// user : 用户名。
	// joinDate: 进入组时间。
	SQLCommandUserChatGroupMember = "CREATE TABLE IF NOT EXISTS " + SQLTableChatGroupMember +
		`(
			"id" INTEGER PRIMARY KEY AUTOINCREMENT,
			"groupId"  INTEGER,
			"userName" varchar(30) not null,
			"joinDate" TIMESTAMP default (datetime('now', 'localtime'))
		);
	` +
		"CREATE INDEX IF NOT EXISTS MemberUser ON " + SQLTableChatGroupMember + "(userName);" +
		"CREATE INDEX IF NOT EXISTS MemberGroupId ON " + SQLTableChatGroupMember + "(groupId);"

	// create User Chat old msg Table's sql command
	//
	// table member item info:
	// id :
	// user : 发送消息的用户。
	// user2 : 对端用户。
	// sendDate: 发送的时间。
	// comment: 发送的内容, 可能是文件,或者图片路径或者网页路径等。
	// type: 消息类型: 0: text 1: picture 2: audio 3: video 4: web page,5: 添加好友
	SQLCommandUserChatMsg = "CREATE TABLE IF NOT EXISTS " + SQLTableChatMsg +
		`(
			"id" INTEGER PRIMARY KEY AUTOINCREMENT,
			"userName" varchar(30) not null,
			"userName2" varchar(30) not null,
			"groupId" int default 0,
			"sendDate" TIMESTAMP default (datetime('now', 'localtime')),
			"comment" TEXT default null,
			"type" int default 0
		);` +
		"CREATE INDEX IF NOT EXISTS MsgUser ON " + SQLTableChatMsg + "(userName);"

	// create User Friends Table's sql command
	//
	// table friends info:
	// id :
	// user1: user 1
	// user2: user 2
	// joniDate: 成为好友的时间。
	SQLCommandFriends = "CREATE TABLE IF NOT EXISTS " + SQLTableFriends +
		`(
			"id" INTEGER PRIMARY KEY AUTOINCREMENT,
			"userName" varchar(30) not null,
			"userName2" varchar(30) not null,
			"joniDate" TIMESTAMP default (datetime('now', 'localtime'))
		);
	` +
		"CREATE INDEX IF NOT EXISTS FriendsUser ON " + SQLTableFriends + "(userName, userName2);"
)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值