You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用go-pg从PostgreSQL获取虚拟列的技术疑问

解决go-pg虚拟列查询的问题

Absolutely, using a nested CustomBook struct is a totally valid approach—you just need to tweak a few details to make it play nice with go-pg. Let's walk through fixes for both of your issues, plus a couple of other options to consider:

1. Fixing the "can't find column=info" error & type safety

The first problem happens because go-pg relies on exported (uppercase) struct fields to map database columns, and your original Book struct has unexported fields (lowercase id/name). Additionally, your CustomBook needs to explicitly map the virtual column to its Info field.

Here's the corrected struct setup:

// Make sure Book's fields are exported so go-pg can reflect them
type Book struct {
    ID   int
    Name string
}

// Nested struct with the virtual column field, tagged to match the SQL alias
type CustomBook struct {
    Book          // Embeds all Book fields
    Info string `pg:"info"` // Maps to the "info" alias from your SQL
}

2. Ensuring you get all fields (not just the virtual column)

Your second issue occurs because calling ColumnExpr() replaces go-pg's default SELECT list (which would normally fetch all struct fields). To include both the original Book fields and your virtual column, explicitly select the embedded Book fields plus your custom expression:

var customBooks []CustomBook
err := db.Model(&customBooks).
    ColumnExpr("book.*"). // Fetch all fields from the embedded Book struct
    ColumnExpr("concat('info:', 'id:', id, '...') AS info"). // Add your virtual column
    Select()

if err != nil {
    // Handle error
}

Alternative Options

If creating a nested struct feels overkill, here are two other ways to solve this:

Option A: Add the virtual column field directly to Book

You can add an Info field to your original Book struct, marking it as non-persistent (so go-pg doesn't try to write it to the database) and then explicitly select the columns you need:

type Book struct {
    ID   int
    Name string
    Info string `pg:"-"` // The "-" tag tells go-pg to ignore this for writes
}

var books []Book
err := db.Model(&books).
    Column("id", "name"). // Select original fields
    ColumnExpr("concat('info:', 'id:', id, '...') AS info"). // Add virtual column
    Select()

Option B: Use a map for unstructured results

If you don't need type safety, you can fetch results into a map[string]interface{} which will automatically include all columns (including your virtual one):

var books []map[string]interface{}
err := db.Model(&books).
    Column("id", "name").
    ColumnExpr("concat('info:', 'id:', id, '...') AS info").
    Select()

Key Takeaways

  • Always use exported (uppercase) fields in your go-pg models—this is a common gotcha!
  • Use ColumnExpr("table.*") to include all fields from an embedded struct or table, then append your custom expressions.
  • The nested CustomBook approach is great for keeping your code organized and type-safe, which is why it's my top recommendation.

内容的提问来源于stack exchange,提问作者Fred Hors

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 18:57:50