当前位置: 首页 > web >正文

GO学习记录三

初始化数据库表结构代码。
这次遇到个新手坑,之前直接用代码是成功的,封装后发现不报错也不能成功创建表了。
排查问题后,发现是因为在封装的时候,把defer db.Close()释放连接的方法写在了封装方法initDB()中。
defer 这个关键字的特点是延迟执行,会在函数结束时,应该时return之前执行,所以写在封装方法initDB中,就会导致initDB()运行结束后,直接就释放了数据库连接,致使之后创建表的函数都是处于未创建数据库连接的环境下运行的,导致最后没有创建成功。

package main//引用的包
import ("database/sql""fmt""log""strings"_ "github.com/lib/pq" //pgsql数据库组件
)// 定义数据库相关配置
const (host     = "localhost"        //数据库ipport     = 5432               //数据库端口user     = "postgres"         //数据库用户名password = "postgres"         //数据库密码dbname   = "postgresLearning" //数据库名
)// 启动函数
func main() {//初始化数据库连接db := initDB()defer db.Close() //defer db.Close() 是 Go 语言中一种确保资源被正确释放的惯用写法,它的作用是://在函数返回前,自动调用 db.Close() 来关闭数据库连接,无论函数是正常返回还是发生 paniccreateUserTable(db)  //创建users表createTest1Table(db) //创建test1表createTest2Table(db) //创建test2表
}// 创建users表
func createUserTable(db *sql.DB) {createTable := Table{Name: "users",Columns: []Column{{Name: "id", Type: SERIAL, Primary: true},{Name: "username", Type: VARCHAR, Length: 50, Unique: true, NotNull: true},{Name: "password", Type: VARCHAR, Length: 100, NotNull: true},{Name: "email", Type: VARCHAR, Length: 100, Unique: true, NotNull: true},{Name: "created_at", Type: TIMESTAMP, Default: "CURRENT_TIMESTAMP"},{Name: "updated_at", Type: TIMESTAMP, Default: "CURRENT_TIMESTAMP"},},}success, createTableSQL := CreateTable(createTable)if success {db.Exec(createTableSQL)fmt.Println("创建Users数据表完成")}
}// 创建test1表
func createTest1Table(db *sql.DB) {createTable := Table{Name: "test1",Columns: []Column{{Name: "id", Type: SERIAL, Primary: true},{Name: "name", Type: VARCHAR, Length: 50, Unique: true, NotNull: true},{Name: "age", Type: INT, NotNull: true},{Name: "created_at", Type: TIMESTAMP, Default: "CURRENT_TIMESTAMP"},{Name: "updated_at", Type: TIMESTAMP, Default: "CURRENT_TIMESTAMP"},},}success, createTableSQL := CreateTable(createTable)if success {db.Exec(createTableSQL)fmt.Println("创建Test1数据表完成")}
}// 创建test2表
func createTest2Table(db *sql.DB) {createTable := Table{Name: "test2",Columns: []Column{{Name: "id", Type: SERIAL, Primary: true},{Name: "name", Type: VARCHAR, Length: 50, Unique: true, NotNull: true},{Name: "age", Type: INT, NotNull: true},{Name: "created_at", Type: TIMESTAMP, Default: "CURRENT_TIMESTAMP"},{Name: "updated_at", Type: TIMESTAMP, Default: "CURRENT_TIMESTAMP"},},}success, createTableSQL := CreateTable(createTable)if success {db.Exec(createTableSQL)fmt.Println("创建Test1数据表完成")}
}// 初始化数据库连接
func initDB() *sql.DB {// 构建连接字符串psqlInfo := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",host, port, user, password, dbname)// 连接数据库db, err := sql.Open("postgres", psqlInfo)if err != nil {log.Fatal(err)}//defer db.Close()  这里有一个注意点,这块代码回直接关闭数据库连接// 检查连接err = db.Ping()if err != nil {log.Fatal(err)}fmt.Println("Successfully connected to PostgreSQL database!")return db
}// ColumnItemType 定义列类型的自定义类型
type ColumnItemType string// 支持的列类型常量
const (VARCHAR   ColumnItemType = "VARCHAR"TIMESTAMP ColumnItemType = "TIMESTAMP"SERIAL    ColumnItemType = "SERIAL"TEXT      ColumnItemType = "TEXT"DECIMAL   ColumnItemType = "DECIMAL"INT       ColumnItemType = "INT"
)// Column 定义字段结构
type Column struct {Name    stringType    ColumnItemTypeLength  int // 长度,仅对 VARCHAR、DECIMAL 等有效NotNull boolUnique  boolPrimary boolDefault string
}// Table 定义表结构
type Table struct {Name    stringColumns []Column
}// CreateTable 生成 CREATE TABLE SQL 语句
func CreateTable(table Table) (bool, string) {if table.Name == "" {fmt.Printf("表名不能为空")return false, ""}if len(table.Columns) == 0 {fmt.Printf("字段列表不能为空")return false, ""}var fieldDefs []stringfor _, col := range table.Columns {if col.Name == "" {fmt.Printf("字段名不能为空")return false, ""}def := col.Name + " " + string(col.Type) // 注意:col.Type 是 ColumnItemType,需转为 string// 处理长度(仅对支持长度的类型)if col.Length > 0 {// 可以根据 Type 判断是否支持 Length,例如只对 VARCHAR 和 DECIMAL 生效def += fmt.Sprintf("(%d)", col.Length)}// 添加约束if col.NotNull {def += " NOT NULL"}if col.Unique {def += " UNIQUE"}if col.Primary {def += " PRIMARY KEY"}if col.Default != "" {def += " DEFAULT " + col.Default}fieldDefs = append(fieldDefs, def)}// 拼接完整 SQLsql := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s (%s);",table.Name,strings.Join(fieldDefs, ", "),)return true, sql
}
http://www.xdnf.cn/news/17658.html

相关文章:

  • 基于MongoDB/HBase的知识共享平台的设计与实现
  • 【Dv3Admin】菜单转换选项卡平铺到页面
  • Excel 连接阿里云 RDS MySQL
  • 5G 非地面网络(NTN)最专业的方案
  • 高并发场景下分布式ID生成方案对比与实践指南
  • 在 .NET Core 5.0 中启用 Gzip 压缩
  • 从ELF到进程间通信:剖析Linux程序的加载与交互机制
  • 玩转Docker | 使用Docker部署Trilium Notes知识库工具
  • 5G NTN 卫星测试产品
  • word格式设置-论文写作,样式,字号等
  • WPF之绑定!
  • LeetCode——241.为运算表达式设计优先级
  • 在 RHEL9 上搭建企业级 Web 服务(Tomcat)
  • Android Audio实战——获取活跃音频类型(十五)
  • 深度学习与遥感入门(五)|GAT 构图消融 + 分块全图预测:更稳更快的高光谱图分类(PyTorch Geometric 实战)
  • 【数据可视化-86】中国育儿成本深度可视化分析(基于《中国统计年鉴2023》数据):用Python和pyecharts打造炫酷可视化大屏
  • 论文阅读 arxiv 2024 MemGPT: Towards LLMs as Operating Systems
  • Apache IoTDB 全场景部署:基于 Apache IoTDB 的跨「端-边-云」的时序数据库 DB+AI
  • Java 之抽象类和接口
  • SSH远程连接TRAE时显示权限被拒绝检查方案
  • 可视化程序设计(4) - 第一个图形窗口程序
  • Java进阶之单列集合Set接口下的通用方法
  • Linux下的软件编程——标准IO
  • ECharts Y轴5等分终极解决方案 - 动态适配缩放场景
  • 后量子密码学的迁移与安全保障:迎接量子时代的挑战
  • NLP---IF-IDF案例分析
  • FreeRTOS学习:优化系统
  • LeetCode_哈希表
  • 论文阅读:Aircraft Trajectory Prediction Based on Residual Recurrent Neural Networks
  • OpenAI正式发布GPT-5:迈向AGI的关键一步