Skip to content

go 基础使用

1. 链接数据库

go
package excample

// 链接pgsql

import (
	"context"
	"fmt"
	"os"

	"github.com/jackc/pgx/v5"
)

// TestPgsqlConnet 演示如何使用 pgx 库连接到 PostgreSQL 数据库,
// 执行查询以从 pg_stat_activity 视图中检索信息,并处理结果。
//
// 此函数执行以下步骤:
//  1. 使用连接 URL 建立到 PostgreSQL 数据库的连接。
//  2. 执行查询以从 pg_stat_activity 视图中检索活动查询的进程 ID (pid)、查询文本和状态,
//     排除空闲查询。
//  3. 遍历结果集并打印检索到的信息。
//
// 注意:
// - 确保在项目中正确导入并配置 pgx 库。
// - 根据您的环境替换连接 URL 中的凭据和数据库详细信息。
// - 安全地处理数据库凭据等敏感信息。
// - 如果任何步骤失败,函数将打印错误信息并退出程序。
func TestPgsqlConnet() {
	urlExample := "postgres://postgres:postgres@10.31.2.54:5432/postgres"
	conn, err := pgx.Connect(context.Background(), urlExample)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Unable to connect to database: %v\n", err)
		os.Exit(1)
	}
	defer conn.Close(context.Background()) // 关闭连接

	var pid int64
	var query string
	var state string
	querySql := "SELECT pid, query, $1 state FROM pg_stat_activity WHERE query <> '<IDLE>' ;"
	rows, err := conn.Query(context.Background(), querySql, "idle")
	if err != nil {
		fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", err)
		os.Exit(1)
	}
	defer rows.Close()

	for rows.Next() {
		err = rows.Scan(&pid, &query, &state)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Scan failed: %v\n", err)
			os.Exit(1)
		}
		fmt.Printf("pid: %d, query: %s, state: %s\n", pid, query, state)
	}
}

其他常用的函数:

  • 执行增删改 Exec
  • 单行查询 QueryRow

事务处理:

go
func InsertUsersInTransaction(conn *pgx.Conn, users []User) error {
    tx, err := conn.Begin(context.Background())
    if err != nil {
        return err
    }

    for _, user := range users {
        _, err := tx.Exec(context.Background(), "INSERT INTO users (id, name) VALUES (1,2)", user.ID, user.Name)
        if err != nil {
            tx.Rollback(context.Background())
            return err
        }
    }

    err = tx.Commit(context.Background())
    if err != nil {
        return err
    }

    return nil
}

其他提问

1. go 模块,函数如何让其他包调用

​首字母大写​​的函数或变量才能被其他包访问(称为"导出")。 使用import关键字导入目标包,路径需与go.mod中的模块名匹配。

2. 在Go语言中,​​package(包)​​和​​module(模块)​​是两个核心概念,主要区别如下:

  • Package(包)

    • 是代码组织和复用的基本单位,由同一目录下的.go文件组成,共享相同的包名。
    • 通过首字母大小写控制标识符(变量、函数等)的可见性(如Add可导出,add仅包内可用)。
    • 示例:package utils定义了一个工具包,其他包可通过import "your-module/utils"调用其导出函数。
  • Module(模块)

    • 是依赖管理和版本控制的单元,包含一个或多个相关包,由go.mod文件定义。
    • 记录项目依赖及其版本(如require github.com/gin-gonic/gin v1.7.0),确保构建一致性。
    • 示例:module github.com/user/project声明模块路径,其下可包含多个子包。

3. go 多行字符串

使用反引号(`)定义原生多行字符串(推荐)

go
str := `第一行
第二行
第三行`

特点: • 保留所有换行和空格(原样输出) • 不支持转义字符(如\n会直接显示为字符) • 适合嵌入SQL、HTML模板等场景

方法保留格式支持转义适用场景
反引号✔️静态文本(SQL/HTML等)
双引号+\n✔️需要转义字符的场景
strings.Join✔️动态生成多行内容

4. defer 的作用

defer 是Go语言的关键字,用于延迟执行一个函数调用,直到包含它的函数返回(无论正常返回还是异常退出)。

  • ​资源管理​​:常用于文件、数据库连接、锁等资源的释放,避免泄漏。
  • ​执行顺序​​:多个defer按后进先出(LIFO)顺序执行。