SQL to Go Struct

Turn CREATE TABLE statements into Go structs with db tags and correct null handling.

CREATE TABLE

Go

Go structs appear here.

About this SQL to Go struct converter

Paste a CREATE TABLE statement — PostgreSQL or MySQL — and get Go structs with db tags ready for sqlx, pgx or plain database/sql. Everything runs in your browser, so pasting a production schema sends nothing anywhere.

Nullable columns are the part that matters

A column without NOT NULL can be NULL, and scanning NULL into a plain string fails at runtime with converting NULL to string is unsupported. So nullable columns become pointers (*string) by default, which database/sql sets to nil. Switch to sql.NullString if you prefer the explicit .Valid check. A PRIMARY KEY is implicitly NOT NULL in both databases even when the constraint is not spelled out, and the parser accounts for that.

numeric and decimal become string, not float64

This surprises people, so it is worth stating plainly: float64 cannot represent an exact decimal. Scanning a numeric(12,2) balance into one silently introduces rounding error, which is exactly the wrong outcome for money. The default here is string, which preserves the value exactly; from there you can move to a decimal package. Most converters map these to float64 and say nothing.

Dialect differences that actually change the type

  • MySQL TINYINT(1) is how MySQL stores a boolean — BOOLEAN is an alias for it — so it maps to bool, while a plain TINYINT maps to int8.
  • MySQL TIME maps to string, not time.Time. The column holds values from -838:59:59 to 838:59:59 — it is a duration, not an instant, and does not fit.
  • UNSIGNED columns map to the unsigned Go types, so a BIGINT UNSIGNED primary key becomes uint64 rather than overflowing an int64.
  • Postgres arrays like text[] become []string. Note that database/sql cannot scan those directly — wrap them in pq.Array, or use pgx, which handles arrays natively.
  • json and jsonb become json.RawMessage, so you can defer decoding to the point where you know the shape.

Exact-width integers or Go's int?

By default an integer column becomes int32 and a bigint becomes int64, matching what the column can actually hold. If you would rather have Go's native int everywhere, switch Integers to Go int. Note that int is 64-bit on every platform Go currently targets, so it is a safe home for a bigint, but it hides the column's real range.

What it does with the rest of the DDL

Table-level constraints — PRIMARY KEY (…), FOREIGN KEY, UNIQUE, CHECK, MySQL KEY/INDEX — are parsed and skipped rather than mistaken for columns. Comments, quoted identifiers, schema-qualified names, IF NOT EXISTS, table options like ENGINE=InnoDB and defaults containing commas or function calls are all handled. Types it does not recognise map to string, which is right for enums and domains, and it tells you which ones it guessed at.

Is the output gofmt-clean?

Yes. Fields are aligned into columns exactly the way gofmt would, so running gofmt on the result changes nothing.