图片待插入
引言
在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操作的介绍了,暂时先写这么多,后面也会进行完善。
你知道的越多,你不知道的越多,人才们的 【三连】 就是我创作的最大动力,我们下期见!
注:如果本篇博客有任何错误和建议,欢迎人才们留言,你快说句话啊!