GDL (Go-Duck Language)
The standard DSL for generating your massive suite of code from a simple text file.
GDL Syntax & Structure
GDL allows you to define your core business entities and the relationships between them. It looks and acts slightly similarly to JHipster's JDL.
@Audited
entity Article {
title String required unique
content Text required
status ArticleStatus required
publishedDate LocalDate
views Integer
metadata JSONB
}
enum ArticleStatus {
DRAFT, PUBLISHED, ARCHIVED
}
entity Author {
name String required
biography Text
settings JSON
}
relationship OneToMany {
Author{article} to Article{author} required
}
Supported Data Types
| GDL Type | Go Struct Type | Postgres / SQL Type | GraphQL / Proto |
|---|---|---|---|
| String | string | VARCHAR(255) | String / string |
| String(N) | string | VARCHAR(N) | String / string |
| Text | string | TEXT | String / string |
| JSON | datatypes.JSON | JSON | String / string |
| JSONB | datatypes.JSON | JSONB | String / string |
| Integer | int | INT | Int / int32 |
| Long | int64 | BIGINT | ID / int64 |
| Float | float64 | DECIMAL | Float / float32 |
| BigDecimal | float64 | DECIMAL | Float / double |
| Boolean | bool | BOOLEAN | Boolean / bool |
| LocalDate | time.Time | DATE | String / string |
| Instant | time.Time | TIMESTAMP | String / string |
| Enum | CustomType | VARCHAR(50) | String / string |
Enumerations
GDL supports custom Enum types for fields that have a predefined set of allowed values. Enums are generated as Go types with constants and mapped to safe string columns in the database.
enum Language {
ENGLISH, FRENCH, GERMAN
}
entity Person {
name String required
nativeLanguage Language
}
Modifiers & Annotations
required
Forces the field to be NOT NULL in the database, missing fields are blocked by the Gin validator natively.
unique
Adds a standard UNIQUE constraint indexing configuration at the database level.
@Audited
An entity annotation that completely re-wires the structural behavior of the model. Standard created_at triggers are bypassed and 5 highly-detailed audit columns are injected: created_by, created_date, last_modified_by, last_modified_date, last_modified_user_id. All changes are captured implicitly by the JWT middleware.
Incremental Migration Engine
Running go-duck import-gdl app.gdl compares your GDL file against the physical .go-duck/ snapshot state securely stored in the repo.
It detects exactly what changed (such as removing a field, changing field types, adding new nested JSON) and generates precise atomic standard Liquibase XML migrations/liquibase/changelogs/ scripts to evolve the live database safely without destroying data.
Golden Rule
Avoid editing Liquibase XML manually unless correcting an anomaly. Let the GDL manage your migrations.
Managing Relationships
Relationships in GDL define how entities connect at the database level (foreign keys) and how they are represented in Go structs and GraphQL schemas. Just like JHipster, we support four primary types.
One-to-Many Most Common
Example: An Author has many Articles.
relationship OneToMany {
Author{article} to Article{author}
}
This generates a author_id foreign key in the article table and a slice of Articles in the Author struct.
Many-to-One
Essentially the inverse of One-to-Many, used to specify the owner side explicitly.
relationship ManyToOne {
Article{author} to Author
}
One-to-One
Example: A User has exactly one Profile.
relationship OneToOne {
User{profile} to Profile{user}
}
Many-to-Many
Example: Students enrolled in many Courses.
relationship ManyToMany {
Student{course} to Course{student}
}
This triggers the automatic generation of a join table (e.g., student_course) in Liquibase.