📖

PostgresとGolangのデータ型対応表

に公開

PostgreSQLとGoのデータ型対応表

PostgreSQLデータ型 Goのデータ型 (database/sql での推奨) 備考
SMALLINT int16
INTEGER int32 または int int はシステムに依存するため、明示的なint32が良い場合も。
BIGINT int64
SERIAL int32 または int 自動インクリメント。Goではintで受け取る。
BIGSERIAL int64 自動インクリメント。Goではint64で受け取る。
REAL float32 精度に注意。float64にスキャンすると精度問題が発生する可能性あり。
DOUBLE PRECISION float64
NUMERIC, DECIMAL float64 または string または *pgtype.Numeric (pgxの場合) 厳密な精度が必要な場合はstringで受け取り、独自で計算するか、専用の型(pgtype.Numericなど)を使用するのが推奨されます。float64では丸め誤差が生じる可能性があります。
BOOLEAN bool
TEXT, VARCHAR, CHAR string
BYTEA []byte バイナリデータ。
DATE time.Time 日付のみ。
TIME time.Time 時刻のみ。
TIMESTAMP, TIMESTAMPTZ time.Time タイムゾーン情報を持つかどうかで、扱いが少し異なる場合がありますが、Goではtime.Timeで対応できます。
JSON, JSONB []byte または 構造体 (encoding/jsonでMarshal/Unmarshal) []byteでJSON文字列として取得し、json.UnmarshalでGoの構造体に変換するのが一般的です。json.RawMessageも利用可能です。
UUID string または [16]byte (pgxの場合) 文字列で扱うのが一般的ですが、pgxなどの一部ドライバでは専用の型も提供しています。
INET, CIDR net.IP または netip.Addr (Go 1.18以降) IPアドレス。
ARRAY (例: INTEGER[]) []int32 または pq.Int64Array (pqの場合), []stringなど (要素の型による) database/sql標準では配列型を直接スキャンするのが難しい場合があります。ドライバ(pqpq.Int64Arrayなど)が提供するカスタム型を使用するか、JSONとして扱う方法が考えられます。pgxでは配列型を直接サポートしています。
XML string または []byte XML文字列として取得。
NULLABLEな型 sql.NullString, sql.NullInt64, sql.NullBool, sql.NullTime など または ポインタ型 (*string, *int など) NULLの可能性があるカラムは、database/sqlが提供するsql.Null系の型を使用するか、ポインタ型で受け取ることでNULLを表現できます。

補足事項

  • database/sqlパッケージのNull許容型:
    PostgreSQLでNULLが許容されるカラムをGoで扱う場合、database/sqlパッケージのsql.NullString, sql.NullInt64, sql.NullBool, sql.NullFloat64, sql.NullTime などの型を使用することが推奨されます。これらの型は、値とそれがNULLであるかどうかの情報(Validフィールド)を保持します。
    例: sql.NullString

    type User struct {
        ID   int
        Name sql.NullString // NULLを許容するTEXT型カラム
    }
    

    あるいは、Goのポインタ型を使用することもできます。

    type User struct {
        ID   int
        Name *string // NULLを許容するTEXT型カラム
    }
    
  • pgxドライバの使用:github.com/jackc/pgxは、database/sqlインターフェースを実装していますが、よりPostgreSQLに特化した豊富な型マッピングを提供しています。例えば、pgtypeパッケージを使用することで、より正確な型変換が可能になります。
    特にNUMERICDECIMALのような厳密な精度が求められる数値型、UUID、配列型などで、pgxの提供する型を使用すると便利です。

  • JSON/JSONBの扱い:JSONJSONBは、Goの構造体と簡単にマッピングできます。

    import (
        "encoding/json"
        // ...
    )
    
    type MyData struct {
        Key1 string `json:"key1"`
        Key2 int    `json:"key2"`
    }
    
    type MyTable struct {
        ID   int
        Data json.RawMessage // または []byte
    }
    
    // 取得時
    var t MyTable
    // ... db.QueryRow(...).Scan(&t.ID, &t.Data)
    var d MyData
    err := json.Unmarshal(t.Data, &d)
    
    // 保存時
    myData := MyData{Key1: "value", Key2: 123}
    jsonBytes, err := json.Marshal(myData)
    // ... db.Exec("INSERT INTO my_table (data) VALUES ($1)", jsonBytes)
    
  • カスタム型:
    上記にないPostgreSQLの特殊なデータ型(例えば、幾何学データ型など)や、より複雑な変換が必要な場合は、Goのsql.Scannerおよびdriver.Valuerインターフェースを実装することで、独自のGo型を定義し、データベースの型とマッピングすることができます。

Discussion