前言
这篇文章主要是学习怎么用 Go 语言(Gin)开发Web程序,前端太弱了,得好好补补课,完了再来更新。
1、环境准备
新建项目,生成 go.mod 文件:
出现报错:go: modules disabled by GO111MODULE=off; see 'go help modules',说明需要开启:
临时设置环境变量:
set GO111MODULE=on # windows export GO111MODULE=on # linux
永久设置环境变量:
再次生成 go.mod 文件:
执行完毕,发现项目下生成 go.mod 文件:
这里的模块名称是我们自定义的,不是说非得和哪个目录或者项目名对应上!
2、用户注册
2.1、需求
- 用户向地址 /register 发送POST请求(表单携带着 username、password、phone)
- 后端处理请求(检查手机号位数、手机号是否已经被注册、用户名是否为空)
2.2、需求实现
2.2.1、判断手机号是否存在
func isPhoneExist(db gorm.DB, phone string) bool { user := User{} db.Where("phone = ?", phone).First(user) if user.ID != 0 { return true } return false }
2.2.2、生成随机10位的用户名
func RandomString(length int) string { var letters = []byte("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM") result := make([]byte, length) rand.Seed(time.Now().Unix()) for i := range result { result[i] = letters[rand.Intn(len(letters))] } return string(result) }
2.2.3、设置用户表结构体
这个结构体的字段会对应用户表中的每个字段,我们会在初始化数据库的时候,使用 gorm.DB 的 AutoMigrate 方法自动帮我进行创建这个结构体对应的表。
type User struct { gorm.Model Name string `gorm:"type:varchar(20);not null"` Phone string `gorm:"type:varchar(110);not null,unique"` Password string `gorm:"size:255;not null"` }
其中 gorm.Model 的源码如下:
我们通过嵌套 gorm.Model 来给我们的表增加四个字段。
2.2.4、获得数据库连接(gorm)
func InitDB() *gorm.DB { driverName := "mysql" host := "127.0.0.1" port := 3306 database := "go_web" username := "root" password := "xxxxx" charset := "utf8mb4" args := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=true", username, password, host, port, database, charset) db, err := gorm.Open(driverName, args) if err != nil { panic("failed to connect database, err : " + err.Error()) } db.AutoMigrate(&User{}) // 如果表不存在则自动创建 return db }
2.3、完整代码
package main import ( "fmt" "github.com/gin-gonic/gin" _ "github.com/go-sql-driver/mysql" "github.com/jinzhu/gorm" "math/rand" "net/http" "time" ) type User struct { gorm.Model Name string `gorm:"type:varchar(20);not null"` Phone string `gorm:"type:varchar(110);not null,unique"` Password string `gorm:"size:255;not null"` } func main() { db := InitDB() defer db.Close() engine := gin.Default() engine.POST("/register", func(ctx *gin.Context) { // 获取参数 name := ctx.PostForm("username") phone := ctx.PostForm("phone") password := ctx.PostForm("password") // 数据验证 if len(phone) != 11 { ctx.JSON(http.StatusUnprocessableEntity, gin.H{ "code": 422, "msg": "手机号必须为11位!", }) return } if len(password) < 6 { // gin.H 等同于 map[string]any ctx.JSON(http.StatusUnprocessableEntity, map[string]interface{}{ "code": 422, "msg": "密码不能少于6位!", }) return } if len(name) == 0 { name = RandomString(10) } fmt.Println(name, phone, password) // 判断手机号是否存在 if isPhoneExist(*db, phone) { ctx.JSON(http.StatusUnprocessableEntity, gin.H{ "msg": "用户已存在,不允许重复注册", }) return } // 创建用户 newUser := User{ Name: name, Phone: phone, Password: password, } db.Create(&newUser) // 返回结果 ctx.JSON(200, gin.H{ "msg": "注册成功", }) }) panic(engine.Run()) // 默认端口 8080 } func isPhoneExist(db gorm.DB, phone string) bool { user := User{} db.Where("phone = ?", phone).First(user) if user.ID != 0 { return true } return false } func RandomString(length int) string { var letters = []byte("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM") result := make([]byte, length) rand.Seed(time.Now().Unix()) for i := range result { result[i] = letters[rand.Intn(len(letters))] } return string(result) } func InitDB() *gorm.DB { driverName := "mysql" host := "127.0.0.1" port := 3306 database := "go_web" username := "root" password := "xxxxx" charset := "utf8mb4" args := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=true", username, password, host, port, database, charset) db, err := gorm.Open(driverName, args) if err != nil { panic("failed to connect database, err : " + err.Error()) } db.AutoMigrate(&User{}) // 如果表不存在则自动创建 return db }
2.4、测试
使用规范的用户信息再次注册:
Go Web 开发 Demo【用户登录、注册、验证】(2)https://developer.aliyun.com/article/1534273