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

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.dtcms.com/a/325462.html

相关文章:

  • 5G 非地面网络(NTN)最专业的方案
  • Docker 详解(保姆级安装+配置+使用教程)
  • 【MySQL✨】服务器安装 MySQL 及配置相关操作
  • 零 shot 语义+在线闭环:深度学习让机器人学会“主动”
  • JavaWeb-后端Web实战(IOC + DI)
  • 第八篇:交互入门:鼠标拾取物体
  • TRS(总收益互换)系统架构设计:多市场交易的技术实现分析
  • 网络编程~
  • 套接字技术、视频加载技术、断点续传技术
  • 前端执行上下文(简版)
  • 2025.8.6 图论(1)Solution
  • 大模型提示词工程实践:聊天机器人定制与实践-打造个性化任务助手
  • Oracle 19C 配置TAF
  • 投资光伏怕成本超标?鹧鸪云系统配置最优方案
  • 微算法科技(NASDAQ:MLGO)通过蚁群算法求解资源分配的全局最优解,实现低能耗的区块链资源分配
  • 【深度学习计算性能】03:自动并行
  • Apache Ignite 生产级的线程池关闭工具方法揭秘
  • 【C++】封装哈希表模拟实现unordered_set和unordered_map
  • 【10】微网优联——微网优联 嵌入式技术一面,校招,面试问答记录
  • 【Linux让旧电脑重获新生的奇妙魔法】
  • 【k8s】k8s安装与集群部署脚本
  • Godot ------ 平滑拖动03
  • 量子神经网络:从NISQ困境到逻辑比特革命的破局之路
  • Day 37:早停策略和模型权重的保存
  • C语言指针(四):字符指针、数组指针与函数指针的实战指南
  • Unity大型场景性能优化全攻略:PC与安卓端深度实践 - 场景管理、渲染优化、资源调度 C#
  • 在Mac 上生成GitLab 的SSH 密钥并将其添加到GitLab
  • 在 .NET Core 5.0 中启用 Gzip 压缩
  • AI时代基于云原生的 CI/CD 基础设施 Tekton
  • Redis Sentinel 中 `sentinel resolve-hostnames yes` 的必要性解析