图片待插入
引言
在C++中,通过使用关键字public、protected和private实现对类的封装和继承。其中public和private实现了类的封装,protected实现了类的继承。在Java中,类的修饰添加了两个个关键字default和friendly。其中default同一包中的类可以访问,声明时没有加修饰符,认为是friendly。比较内容见表1。
| C++ | Java | C# | Go | |
|---|---|---|---|---|
| public | 可以被该类中的函数、子类的函数、友元函数访问,也可以由该类的对象访问 | 具有最大的访问权限,可以访问任何一个在classpath下的类、接口、异常等。它往往用于对外的情况,也就是对象或类对外的一种接口的形式。 | 公有访问,不受任何限制。 | Go的关键字中没有public |
| private | 可以被该类中的函数、子类的函数、友元函数访问,但不可以由该类的对象访问 | 访问权限仅限于类的内部,是一种封装的体现,例如,大多数成员变量都是修饰符为private的,它们不希望被其他任何外部的类访问。 | 私有访问,只限于本类成员访问,子类、实例都不能访问。 | Go的关键字中没有private |
| protected | 可以被该类中的函数、友元函数访问,但不可以由子类的函数、该类的对象、访问 | 主要的作用就是用来保护子类的。它的含义在于子类可以用它修饰的成员,其他的不可以,它相当于传递给子类的一种继承的东西 | 保护访问,只限于本类和子类访问,实例不能访问。 | Go的关键字中没有protected |
| internal | C++的关键字中没有interface | 用于声明仅包含抽象方法的特殊类型的类 | 内部访问,只限于本项目内访问,其他不能访问。 | Go的关键字中没有internal |
| default | 通过default关键字恢复构造函数 | 有时候也称为friendly,它是针对本包访问而设计的,任何处于本包下的类、接口、异常等,都可以相互访问,即使是父类没有用protected修饰的成员也可以。 | C#的关键字中没有default,这里不讨论switch语句。 | Go的关键字中没有default |
为什么要进行封装
提到封装的好处,我们想从函数说起。在我们学习计算机编程语言时,是不是习惯将一系列操作全部写在main函数中。在学到函数章节时,才会开始尝试并习惯将不同的操作写在不同的函数中。函数的使用,可以提高编码效率,较少定位错误的时间。在面对对象编程中,一个对象涉及多个变量和方法,在对象内部函数不受限制。对对象进行封装,使用者就不必关注方法是如何实现的。封装的好处如下:
提高了数据的安全性:调用者不能够通过变量名、属性名的方式来修改某个私有的成员属性
操作简单:封装后,调用者在使用的时候,只需调用方法即可,调用者不需要再进行判断
隐藏了实现:实现过程对调用者是不可见的,调用者只需调用方法即可,不知道具体实现过程
代码实现
数据库表结构如表2所示。
| 名字 | 类型 | 排序规则 | 属性 | 空 | 默认 | 额外 |
| userID | int(10) | UNSIGNED | 否 | 无 | AUTO_INCREMENT | |
| userNum (主键) | varchar(20) | uft8mb4_general_ci | 否 | 无 | ||
| userPhone | varchar(11) | uft8mb4_general_ci | 是 | NULL | ||
| userMail | varchar(50) | uft8mb4_general_ci | 是 | NULL | ||
| userPwd | varchar(32) | uft8mb4_general_ci | 否 | 无 | ||
| userRole | varchar(7) | uft8mb4_general_ci | 是 | NULL | ||
| userLockTime | time | 是 | NULL | |||
| created | timestamp | 否 | CURRENT_TIMESTAMP | |||
| updated | timestamp | 否 | CURRENT_TIMESTAMP | ON UPDATE CURRENT_TIMESTAMP |
sqlhelper的代码如下:
package toolkit
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"log"
"time"
)
const (
USERNAME = ""
PASSWORD = ""
NETWORK = "tcp"
SERVER = "127.0.0.1"
PORT = 3306
DATABASE = ""
)
type Search interface {
UserLogin(account string, password string, actype int) bool
UserRegister(account string, password string, actype int) bool
UserUpdate(account string, password string, actype int) bool
UserCancel(account string, password string, actype int) bool
}
type User struct {
}
func (user User) UserInfo() {
}
func (user User) UserLogin(account string, password string, actype int) bool {
db := open()
defer db.Close()
var sql string
switch actype {
case 0:
sql = fmt.Sprintf("select userNum,userPwd from user_login_info where userNum ='%s' and userPwd = '%s';", account, password)
case 1:
sql = fmt.Sprintf("select userNum,userPwd from user_login_info where userPhone ='%s' and userPwd = '%s';", account, password)
case 2:
sql = fmt.Sprintf("select userNum,userPwd from user_login_info where userMail ='%s' and userPwd = '%s';", account, password)
}
rows, err := db.Query(sql)
if err != nil {
fmt.Println("query failed:", err)
return false
}
for rows.Next() {
var userNum, userPasswd string
err = rows.Scan(&userNum, &userPasswd)
//err = rows.Scan(&infos.fileID, &infos.fileName, &infos.fileSize, &infos.fileSource, &infos.filePayment, &infos.fileDownloads, &infos.userID, &infos.created, &infos.updated)
if err != nil {
fmt.Println("scan failed:", err)
}
if userNum == account && userPasswd == password {
return true
}
}
return false
}
func (user User) UserRegister(account string, password string, actype int) bool {
db := open()
defer db.Close()
var sql string
switch actype {
case 0:
sql = fmt.Sprintf("select 1 from user_login_info where userNum ='%s' limit 1;", account)
case 1:
sql = fmt.Sprintf("select 1 from user_login_info where userPhone ='%s' limit 1;", account)
case 2:
sql = fmt.Sprintf("select 1 from user_login_info where userMail ='%s' limit 1;", account)
}
rows, err := db.Query(sql)
if err != nil {
fmt.Println("query failed:", err)
return false
}
num := 0
for rows.Next() {
err = rows.Scan(&num)
if err != nil {
fmt.Println("scan failed:", err)
}
fmt.Println(num)
}
var operation Operation
if num == 1 {
operation = new(Record)
operation.Writer(fmt.Sprintf("user %s register fault at %s, because it exist", account, time.Now().Format("20060102")))
return false
} else {
sql := fmt.Sprintf("insert into user_login_info (userNum,userPwd) values ('%s','%s')", account, password)
_, err := db.Exec(sql)
if err != nil {
operation = new(SQL_ERROE_SAVEPATH)
operation.Writer(err.Error() + "," + time.Now().Format("20060102"))
return false
}
operation = new(Record)
operation.Writer(fmt.Sprintf("user %s register successful at %s", account, time.Now().Format("20060102")))
return true
}
return false
}
func (user User) UserUpdate(account string, password string, actype int) bool {
db := open()
defer db.Close()
if user.UserLogin(account, password, actype) == true {
return false
}
var sql string
switch actype {
case 0:
sql = fmt.Sprintf("update user_login_info set userPwd ='%s' where userNum ='%s';", password, account)
case 1:
sql = fmt.Sprintf("update user_login_info set userPwd ='%s' where userPhone ='%s';", password, account)
case 2:
sql = fmt.Sprintf("update user_login_info set userPwd ='%s' where userMail ='%s';", password, account)
}
result, err := db.Exec(sql)
if err != nil {
fmt.Println("update fault:", err)
return false
}
idAff, err := result.RowsAffected()
if err != nil {
log.Println("RowsAffected failed:", err)
return false
}
if idAff == 0 {
return false
}
return true
}
func (user User) UserCancel(account string, password string, actype int) bool {
db := open()
defer db.Close()
if user.UserLogin(account, password, actype) == false {
return false
}
var sql string
switch actype {
case 0:
sql = fmt.Sprintf("delete from user_login_info where userNum ='%s';", account)
case 1:
sql = fmt.Sprintf("delete from user_login_info where userPhone ='%s';", account)
case 2:
sql = fmt.Sprintf("delete from user_login_info where userMail ='%s';", account)
}
result, err := db.Exec(sql)
if err != nil {
fmt.Println("delete fault:", err)
return false
}
idAff, err := result.RowsAffected()
if err != nil {
log.Println("RowsAffected failed:", err)
return false
}
if idAff == 0 {
return false
}
return true
}
func open() *sql.DB {
conn := fmt.Sprintf("%s:%s@%s(%s:%d)/%s", USERNAME, PASSWORD, NETWORK, SERVER, PORT, DATABASE)
//fmt.Println("conn:", conn)
db, err := sql.Open("mysql", conn)
if err != nil {
fmt.Println("connection to mysql fault:", err)
return db
}
db.SetConnMaxLifetime(100 * time.Second)
db.SetMaxOpenConns(100)
return db
}以登陆为例,代码如下:
account := "account" password := "password" actype := "actype" var search Search search = new(User) loginsuc := search.UserLogin(account, password, actypeInt) fmt.Println(loginsuc)
写在最后的话
以上就是接口封装SQL操作的介绍了,暂时先写这么多,后面也会进行完善。
你知道的越多,你不知道的越多,人才们的 【三连】 就是我创作的最大动力,我们下期见!
注:如果本篇博客有任何错误和建议,欢迎人才们留言,你快说句话啊!

