
Dingo Examples
Preview Dingo ⇄ Go output
package main
import (
"database/sql"
"encoding/json"
"net/http"
"strings"
)
// Sum type for user status - no boilerplate needed!
enum UserStatus {
Active,
Pending,
Suspended
}
// Domain models
type User struct {
ID int
Username string
Email string
Status UserStatus
Profile *UserProfile // Optional profile (Phase 7 - safe navigation)
}
type UserProfile struct {
Bio *string
Website *string
PhoneNumber *string
Country *string
}
type RegisterRequest struct {
Username string
Email string
Password string
Profile *ProfileInput // Optional profile data
}
type ProfileInput struct {
Bio *string
Website *string
Phone *string
Country *string
}
// Validation functions return Result types - explicit success/failure
// These will be called with the ? operator for automatic error propagation
func validateEmail(email string) Result<string, error> {
if !strings.Contains(email, "@") || !strings.Contains(email, ".") {
return Err("invalid email format")
}
return Ok(email)
}
func validatePassword(password string) Result<string, error> {
if len(password) < 8 {
return Err("password must be at least 8 characters")
}
return Ok(password)
}
func validateUsername(username string) Result<string, error> {
if len(username) < 3 {
return Err("username must be at least 3 characters")
}
if len(username) > 20 {
return Err("username too long")
}
return Ok(username)
}
// Database operations using Result types
func checkUserExists(db *sql.DB, email string) Result<bool, error> {
let exists bool
let err = db.QueryRow("SELECT EXISTS(SELECT 1 FROM users WHERE email = ?)").Scan(&exists)
if err != nil {
return Err(err)
}
return Ok(exists)
}
func hashPassword(password string) Result<string, error> {
// Simplified for example - real code would use bcrypt
if password == "" {
return Err("cannot hash empty password")
}
return Ok("hashed_" + password)
}
func saveUser(db *sql.DB, username string, email string, hashedPwd string, status UserStatus, profile *UserProfile) Result<int64, error> {
// Safe navigation for optional profile fields with defaults
let bio = profile?.Bio ?? ""
let website = profile?.Website ?? ""
let phone = profile?.PhoneNumber ?? ""
let country = profile?.Country ?? "US"
let result, err = db.Exec(
"INSERT INTO users (username, email, password, status, bio, website, phone, country) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
username, email, hashedPwd, status, bio, website, phone, country,
)
if err != nil {
return Err(err)
}
let id, err1 = result.LastInsertId()
if err1 != nil {
return Err(err1)
}
return Ok(id)
}
// Main business logic - showcases error propagation and safe navigation
// Demonstrates manual error handling (? operator support coming in future phase)
// NEW (Phase 7): Safe navigation (?.) and null coalescing (??) for optional fields
func registerUser(db *sql.DB, req RegisterRequest) Result<User, error> {
// All validations with manual error checks
let emailResult = validateEmail(req.Email)
if emailResult.IsErr() {
return Err("email validation failed")
}
let email = emailResult.Unwrap()
let passwordResult = validatePassword(req.Password)
if passwordResult.IsErr() {
return Err("password validation failed")
}
let password = passwordResult.Unwrap()
let usernameResult = validateUsername(req.Username)
if usernameResult.IsErr() {
return Err("username validation failed")
}
let username = usernameResult.Unwrap()
// Check if user exists - guard clause
let existsResult = checkUserExists(db, email)
if existsResult.IsErr() {
return Err("failed to check user existence")
}
if existsResult.Unwrap() {
return Err("user already exists")
}
// Build user profile from optional input (Phase 7 - safe navigation)
let userProfile = buildUserProfile(req.Profile)
// Hash password and save user
let hashedPasswordResult = hashPassword(password)
if hashedPasswordResult.IsErr() {
return Err("password hashing failed")
}
let hashedPassword = hashedPasswordResult.Unwrap()
let idResult = saveUser(db, username, email, hashedPassword, UserStatus_Pending, userProfile)
if idResult.IsErr() {
return Err("failed to save user")
}
let id = idResult.Unwrap()
// Return created user with type-safe enum status
return Ok(User{
ID: int(id),
Username: username,
Email: email,
Status: UserStatus_Pending,
Profile: userProfile,
})
}
// NEW (Phase 7): Build user profile with safe defaults using ?. and ??
func buildUserProfile(input *ProfileInput) *UserProfile {
// Safe navigation with null coalescing - extract optional fields with defaults
// These would be verbose null checks in plain Go!
return &UserProfile{
Bio: input?.Bio, // Pass through optional bio
Website: input?.Website, // Pass through optional website
PhoneNumber: input?.Phone, // Map input field to domain field
Country: input?.Country, // Pass through optional country
}
}
// HTTP handler - clean and focused on business logic
func handleRegister(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
let req RegisterRequest
let err = json.NewDecoder(r.Body).Decode(&req)
if err != nil {
http.Error(w, "invalid request body", http.StatusBadRequest)
return
}
// Process registration
let result = registerUser(db, req)
if result.IsOk() {
let user = result.Unwrap()
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(user)
} else {
let err1 = result.UnwrapErr()
http.Error(w, err1.Error(), http.StatusBadRequest)
}
}
}
// NEW (Phase 7): Handler demonstrating safe navigation in response formatting
func handleGetUser(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// Extract user ID from query params
let userID = r.URL.Query().Get("id")
if userID == "" {
http.Error(w, "user ID required", http.StatusBadRequest)
return
}
// Fetch user (may return nil)
let user = getUserByID(db, userID)
// Safe navigation with defaults for JSON response
// Compare this compact syntax to manual nil checks!
let response = map[string]interface{}{
"id": userID,
"username": user?.Username ?? "unknown",
"email": user?.Email ?? "no-email@example.com",
"status": getUserStatusString(user?.Status),
// Nested safe navigation for profile fields
"bio": user?.Profile?.Bio ?? "No bio provided",
"website": user?.Profile?.Website ?? "",
"phone": user?.Profile?.PhoneNumber ?? "",
"country": user?.Profile?.Country ?? "Unknown",
}
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(response)
}
}
// Helper functions for new handler
func getUserByID(db *sql.DB, id string) *User {
// Simplified - would query database in real implementation
return nil
}
func getUserStatusString(status UserStatus) string {
if status == UserStatus_Active {
return "active"
}
if status == UserStatus_Pending {
return "pending"
}
if status == UserStatus_Suspended {
return "suspended"
}
return "unknown"
}

package main
import (
"database/sql"
"encoding/json"
"net/http"
"strings"
)
type ResultTag uint8
const (
ResultTagOk ResultTag = iota
ResultTagErr
)
type Result_string_error struct {
tag ResultTag
ok *string
err *error
}
func Result_string_error_Ok(arg0 string) Result_string_error {
return Result_string_error{tag: ResultTagOk, ok: &arg0}
}
func Result_string_error_Err(arg0 error) Result_string_error {
return Result_string_error{tag: ResultTagErr, err: &arg0}
}
func (r Result_string_error) IsOk() bool {
return r.tag == ResultTagOk
}
func (r Result_string_error) IsErr() bool {
return r.tag == ResultTagErr
}
func (r Result_string_error) Unwrap() string {
if r.tag != ResultTagOk {
panic("called Unwrap on Err")
}
if r.ok == nil {
panic("Result contains nil Ok value")
}
return *r.ok
}
func (r Result_string_error) UnwrapOr(defaultValue string) string {
if r.tag == ResultTagOk {
return *r.ok
}
return defaultValue
}
func (r Result_string_error) UnwrapErr() error {
if r.tag != ResultTagErr {
panic("called UnwrapErr on Ok")
}
if r.err == nil {
panic("Result contains nil Err value")
}
return *r.err
}
func (r Result_string_error) UnwrapOrElse(fn func(error) string) string {
if r.tag == ResultTagOk && r.ok != nil {
return *r.ok
}
if r.err != nil {
return fn(*r.err)
}
panic("Result in invalid state")
}
func (r Result_string_error) Map(fn func(string) interface{}) interface{} {
if r.tag == ResultTagOk && r.ok != nil {
u := fn(*r.ok)
return struct {
tag ResultTag
ok *interface{}
err *error
}{tag: ResultTagOk, ok: &u}
}
return struct {
tag ResultTag
ok *interface{}
err *error
}{tag: r.tag, ok: nil, err: r.err}
}
func (r Result_string_error) MapErr(fn func(error) interface{}) interface{} {
if r.tag == ResultTagErr && r.err != nil {
f := fn(*r.err)
return struct {
tag ResultTag
ok *string
err *interface{}
}{tag: ResultTagErr, ok: nil, err: &f}
}
return struct {
tag ResultTag
ok *string
err *interface{}
}{tag: r.tag, ok: r.ok, err: nil}
}
func (r Result_string_error) Filter(predicate func(string) bool) Result_string_error {
if r.tag == ResultTagOk && predicate(*r.ok) {
return r
}
return r
}
func (r Result_string_error) AndThen(fn func(string) interface{}) interface{} {
if r.tag == ResultTagOk && r.ok != nil {
return fn(*r.ok)
}
return struct {
tag ResultTag
ok *interface{}
err *error
}{tag: r.tag, ok: nil, err: r.err}
}
func (r Result_string_error) OrElse(fn func(error) interface{}) interface{} {
if r.tag == ResultTagErr && r.err != nil {
return fn(*r.err)
}
return struct {
tag ResultTag
ok *string
err *interface{}
}{tag: r.tag, ok: r.ok, err: nil}
}
func (r Result_string_error) And(other interface{}) interface{} {
if r.tag == ResultTagOk {
return other
}
return r
}
func (r Result_string_error) Or(other Result_string_error) Result_string_error {
if r.tag == ResultTagOk {
return r
}
return other
}
type Result_interface_string struct {
tag ResultTag
ok *interface{}
err *string
}
func Result_interface_string_Ok(arg0 interface{}) Result_interface_string {
return Result_interface_string{tag: ResultTagOk, ok: &arg0}
}
func Result_interface_string_Err(arg0 string) Result_interface_string {
return Result_interface_string{tag: ResultTagErr, err: &arg0}
}
func (r Result_interface_string) IsOk() bool {
return r.tag == ResultTagOk
}
func (r Result_interface_string) IsErr() bool {
return r.tag == ResultTagErr
}
func (r Result_interface_string) Unwrap() interface{} {
if r.tag != ResultTagOk {
panic("called Unwrap on Err")
}
if r.ok == nil {
panic("Result contains nil Ok value")
}
return *r.ok
}
func (r Result_interface_string) UnwrapOr(defaultValue interface{}) interface{} {
if r.tag == ResultTagOk {
return *r.ok
}
return defaultValue
}
func (r Result_interface_string) UnwrapErr() string {
if r.tag != ResultTagErr {
panic("called UnwrapErr on Ok")
}
if r.err == nil {
panic("Result contains nil Err value")
}
return *r.err
}
func (r Result_interface_string) UnwrapOrElse(fn func(string) interface{}) interface{} {
if r.tag == ResultTagOk && r.ok != nil {
return *r.ok
}
if r.err != nil {
return fn(*r.err)
}
panic("Result in invalid state")
}
func (r Result_interface_string) Map(fn func(interface{}) interface{}) interface{} {
if r.tag == ResultTagOk && r.ok != nil {
u := fn(*r.ok)
return struct {
tag ResultTag
ok *interface{}
err *string
}{tag: ResultTagOk, ok: &u}
}
return struct {
tag ResultTag
ok *interface{}
err *string
}{tag: r.tag, ok: nil, err: r.err}
}
func (r Result_interface_string) MapErr(fn func(string) interface{}) interface{} {
if r.tag == ResultTagErr && r.err != nil {
f := fn(*r.err)
return struct {
tag ResultTag
ok *interface{}
err *interface{}
}{tag: ResultTagErr, ok: nil, err: &f}
}
return struct {
tag ResultTag
ok *interface{}
err *interface{}
}{tag: r.tag, ok: r.ok, err: nil}
}
func (r Result_interface_string) Filter(predicate func(interface{}) bool) Result_interface_string {
if r.tag == ResultTagOk && predicate(*r.ok) {
return r
}
return r
}
func (r Result_interface_string) AndThen(fn func(interface{}) interface{}) interface{} {
if r.tag == ResultTagOk && r.ok != nil {
return fn(*r.ok)
}
return struct {
tag ResultTag
ok *interface{}
err *string
}{tag: r.tag, ok: nil, err: r.err}
}
func (r Result_interface_string) OrElse(fn func(string) interface{}) interface{} {
if r.tag == ResultTagErr && r.err != nil {
return fn(*r.err)
}
return struct {
tag ResultTag
ok *interface{}
err *interface{}
}{tag: r.tag, ok: r.ok, err: nil}
}
func (r Result_interface_string) And(other interface{}) interface{} {
if r.tag == ResultTagOk {
return other
}
return r
}
func (r Result_interface_string) Or(other Result_interface_string) Result_interface_string {
if r.tag == ResultTagOk {
return r
}
return other
}
type Result_interface_error struct {
tag ResultTag
ok *interface{}
err *error
}
func Result_interface_error_Ok(arg0 interface{}) Result_interface_error {
return Result_interface_error{tag: ResultTagOk, ok: &arg0}
}
func Result_interface_error_Err(arg0 error) Result_interface_error {
return Result_interface_error{tag: ResultTagErr, err: &arg0}
}
func (r Result_interface_error) IsOk() bool {
return r.tag == ResultTagOk
}
func (r Result_interface_error) IsErr() bool {
return r.tag == ResultTagErr
}
func (r Result_interface_error) Unwrap() interface{} {
if r.tag != ResultTagOk {
panic("called Unwrap on Err")
}
if r.ok == nil {
panic("Result contains nil Ok value")
}
return *r.ok
}
func (r Result_interface_error) UnwrapOr(defaultValue interface{}) interface{} {
if r.tag == ResultTagOk {
return *r.ok
}
return defaultValue
}
func (r Result_interface_error) UnwrapErr() error {
if r.tag != ResultTagErr {
panic("called UnwrapErr on Ok")
}
if r.err == nil {
panic("Result contains nil Err value")
}
return *r.err
}
func (r Result_interface_error) UnwrapOrElse(fn func(error) interface{}) interface{} {
if r.tag == ResultTagOk && r.ok != nil {
return *r.ok
}
if r.err != nil {
return fn(*r.err)
}
panic("Result in invalid state")
}
func (r Result_interface_error) Map(fn func(interface{}) interface{}) interface{} {
if r.tag == ResultTagOk && r.ok != nil {
u := fn(*r.ok)
return struct {
tag ResultTag
ok *interface{}
err *error
}{tag: ResultTagOk, ok: &u}
}
return struct {
tag ResultTag
ok *interface{}
err *error
}{tag: r.tag, ok: nil, err: r.err}
}
func (r Result_interface_error) MapErr(fn func(error) interface{}) interface{} {
if r.tag == ResultTagErr && r.err != nil {
f := fn(*r.err)
return struct {
tag ResultTag
ok *interface{}
err *interface{}
}{tag: ResultTagErr, ok: nil, err: &f}
}
return struct {
tag ResultTag
ok *interface{}
err *interface{}
}{tag: r.tag, ok: r.ok, err: nil}
}
func (r Result_interface_error) Filter(predicate func(interface{}) bool) Result_interface_error {
if r.tag == ResultTagOk && predicate(*r.ok) {
return r
}
return r
}
func (r Result_interface_error) AndThen(fn func(interface{}) interface{}) interface{} {
if r.tag == ResultTagOk && r.ok != nil {
return fn(*r.ok)
}
return struct {
tag ResultTag
ok *interface{}
err *error
}{tag: r.tag, ok: nil, err: r.err}
}
func (r Result_interface_error) OrElse(fn func(error) interface{}) interface{} {
if r.tag == ResultTagErr && r.err != nil {
return fn(*r.err)
}
return struct {
tag ResultTag
ok *interface{}
err *interface{}
}{tag: r.tag, ok: r.ok, err: nil}
}
func (r Result_interface_error) And(other interface{}) interface{} {
if r.tag == ResultTagOk {
return other
}
return r
}
func (r Result_interface_error) Or(other Result_interface_error) Result_interface_error {
if r.tag == ResultTagOk {
return r
}
return other
}
type Result_bool_error struct {
tag ResultTag
ok *bool
err *error
}
func Result_bool_error_Ok(arg0 bool) Result_bool_error {
return Result_bool_error{tag: ResultTagOk, ok: &arg0}
}
func Result_bool_error_Err(arg0 error) Result_bool_error {
return Result_bool_error{tag: ResultTagErr, err: &arg0}
}
func (r Result_bool_error) IsOk() bool {
return r.tag == ResultTagOk
}
func (r Result_bool_error) IsErr() bool {
return r.tag == ResultTagErr
}
func (r Result_bool_error) Unwrap() bool {
if r.tag != ResultTagOk {
panic("called Unwrap on Err")
}
if r.ok == nil {
panic("Result contains nil Ok value")
}
return *r.ok
}
func (r Result_bool_error) UnwrapOr(defaultValue bool) bool {
if r.tag == ResultTagOk {
return *r.ok
}
return defaultValue
}
func (r Result_bool_error) UnwrapErr() error {
if r.tag != ResultTagErr {
panic("called UnwrapErr on Ok")
}
if r.err == nil {
panic("Result contains nil Err value")
}
return *r.err
}
func (r Result_bool_error) UnwrapOrElse(fn func(error) bool) bool {
if r.tag == ResultTagOk && r.ok != nil {
return *r.ok
}
if r.err != nil {
return fn(*r.err)
}
panic("Result in invalid state")
}
func (r Result_bool_error) Map(fn func(bool) interface{}) interface{} {
if r.tag == ResultTagOk && r.ok != nil {
u := fn(*r.ok)
return struct {
tag ResultTag
ok *interface{}
err *error
}{tag: ResultTagOk, ok: &u}
}
return struct {
tag ResultTag
ok *interface{}
err *error
}{tag: r.tag, ok: nil, err: r.err}
}
func (r Result_bool_error) MapErr(fn func(error) interface{}) interface{} {
if r.tag == ResultTagErr && r.err != nil {
f := fn(*r.err)
return struct {
tag ResultTag
ok *bool
err *interface{}
}{tag: ResultTagErr, ok: nil, err: &f}
}
return struct {
tag ResultTag
ok *bool
err *interface{}
}{tag: r.tag, ok: r.ok, err: nil}
}
func (r Result_bool_error) Filter(predicate func(bool) bool) Result_bool_error {
if r.tag == ResultTagOk && predicate(*r.ok) {
return r
}
return r
}
func (r Result_bool_error) AndThen(fn func(bool) interface{}) interface{} {
if r.tag == ResultTagOk && r.ok != nil {
return fn(*r.ok)
}
return struct {
tag ResultTag
ok *interface{}
err *error
}{tag: r.tag, ok: nil, err: r.err}
}
func (r Result_bool_error) OrElse(fn func(error) interface{}) interface{} {
if r.tag == ResultTagErr && r.err != nil {
return fn(*r.err)
}
return struct {
tag ResultTag
ok *bool
err *interface{}
}{tag: r.tag, ok: r.ok, err: nil}
}
func (r Result_bool_error) And(other interface{}) interface{} {
if r.tag == ResultTagOk {
return other
}
return r
}
func (r Result_bool_error) Or(other Result_bool_error) Result_bool_error {
if r.tag == ResultTagOk {
return r
}
return other
}
type Result_int64_error struct {
tag ResultTag
ok *int64
err *error
}
func Result_int64_error_Ok(arg0 int64) Result_int64_error {
return Result_int64_error{tag: ResultTagOk, ok: &arg0}
}
func Result_int64_error_Err(arg0 error) Result_int64_error {
return Result_int64_error{tag: ResultTagErr, err: &arg0}
}
func (r Result_int64_error) IsOk() bool {
return r.tag == ResultTagOk
}
func (r Result_int64_error) IsErr() bool {
return r.tag == ResultTagErr
}
func (r Result_int64_error) Unwrap() int64 {
if r.tag != ResultTagOk {
panic("called Unwrap on Err")
}
if r.ok == nil {
panic("Result contains nil Ok value")
}
return *r.ok
}
func (r Result_int64_error) UnwrapOr(defaultValue int64) int64 {
if r.tag == ResultTagOk {
return *r.ok
}
return defaultValue
}
func (r Result_int64_error) UnwrapErr() error {
if r.tag != ResultTagErr {
panic("called UnwrapErr on Ok")
}
if r.err == nil {
panic("Result contains nil Err value")
}
return *r.err
}
func (r Result_int64_error) UnwrapOrElse(fn func(error) int64) int64 {
if r.tag == ResultTagOk && r.ok != nil {
return *r.ok
}
if r.err != nil {
return fn(*r.err)
}
panic("Result in invalid state")
}
func (r Result_int64_error) Map(fn func(int64) interface{}) interface{} {
if r.tag == ResultTagOk && r.ok != nil {
u := fn(*r.ok)
return struct {
tag ResultTag
ok *interface{}
err *error
}{tag: ResultTagOk, ok: &u}
}
return struct {
tag ResultTag
ok *interface{}
err *error
}{tag: r.tag, ok: nil, err: r.err}
}
func (r Result_int64_error) MapErr(fn func(error) interface{}) interface{} {
if r.tag == ResultTagErr && r.err != nil {
f := fn(*r.err)
return struct {
tag ResultTag
ok *int64
err *interface{}
}{tag: ResultTagErr, ok: nil, err: &f}
}
return struct {
tag ResultTag
ok *int64
err *interface{}
}{tag: r.tag, ok: r.ok, err: nil}
}
func (r Result_int64_error) Filter(predicate func(int64) bool) Result_int64_error {
if r.tag == ResultTagOk && predicate(*r.ok) {
return r
}
return r
}
func (r Result_int64_error) AndThen(fn func(int64) interface{}) interface{} {
if r.tag == ResultTagOk && r.ok != nil {
return fn(*r.ok)
}
return struct {
tag ResultTag
ok *interface{}
err *error
}{tag: r.tag, ok: nil, err: r.err}
}
func (r Result_int64_error) OrElse(fn func(error) interface{}) interface{} {
if r.tag == ResultTagErr && r.err != nil {
return fn(*r.err)
}
return struct {
tag ResultTag
ok *int64
err *interface{}
}{tag: r.tag, ok: r.ok, err: nil}
}
func (r Result_int64_error) And(other interface{}) interface{} {
if r.tag == ResultTagOk {
return other
}
return r
}
func (r Result_int64_error) Or(other Result_int64_error) Result_int64_error {
if r.tag == ResultTagOk {
return r
}
return other
}
type Result_User_error struct {
tag ResultTag
ok *User
err *error
}
func Result_User_error_Ok(arg0 User) Result_User_error {
return Result_User_error{tag: ResultTagOk, ok: &arg0}
}
func Result_User_error_Err(arg0 error) Result_User_error {
return Result_User_error{tag: ResultTagErr, err: &arg0}
}
func (r Result_User_error) IsOk() bool {
return r.tag == ResultTagOk
}
func (r Result_User_error) IsErr() bool {
return r.tag == ResultTagErr
}
func (r Result_User_error) Unwrap() User {
if r.tag != ResultTagOk {
panic("called Unwrap on Err")
}
if r.ok == nil {
panic("Result contains nil Ok value")
}
return *r.ok
}
func (r Result_User_error) UnwrapOr(defaultValue User) User {
if r.tag == ResultTagOk {
return *r.ok
}
return defaultValue
}
func (r Result_User_error) UnwrapErr() error {
if r.tag != ResultTagErr {
panic("called UnwrapErr on Ok")
}
if r.err == nil {
panic("Result contains nil Err value")
}
return *r.err
}
func (r Result_User_error) UnwrapOrElse(fn func(error) User) User {
if r.tag == ResultTagOk && r.ok != nil {
return *r.ok
}
if r.err != nil {
return fn(*r.err)
}
panic("Result in invalid state")
}
func (r Result_User_error) Map(fn func(User) interface{}) interface{} {
if r.tag == ResultTagOk && r.ok != nil {
u := fn(*r.ok)
return struct {
tag ResultTag
ok *interface{}
err *error
}{tag: ResultTagOk, ok: &u}
}
return struct {
tag ResultTag
ok *interface{}
err *error
}{tag: r.tag, ok: nil, err: r.err}
}
func (r Result_User_error) MapErr(fn func(error) interface{}) interface{} {
if r.tag == ResultTagErr && r.err != nil {
f := fn(*r.err)
return struct {
tag ResultTag
ok *User
err *interface{}
}{tag: ResultTagErr, ok: nil, err: &f}
}
return struct {
tag ResultTag
ok *User
err *interface{}
}{tag: r.tag, ok: r.ok, err: nil}
}
func (r Result_User_error) Filter(predicate func(User) bool) Result_User_error {
if r.tag == ResultTagOk && predicate(*r.ok) {
return r
}
return r
}
func (r Result_User_error) AndThen(fn func(User) interface{}) interface{} {
if r.tag == ResultTagOk && r.ok != nil {
return fn(*r.ok)
}
return struct {
tag ResultTag
ok *interface{}
err *error
}{tag: r.tag, ok: nil, err: r.err}
}
func (r Result_User_error) OrElse(fn func(error) interface{}) interface{} {
if r.tag == ResultTagErr && r.err != nil {
return fn(*r.err)
}
return struct {
tag ResultTag
ok *User
err *interface{}
}{tag: r.tag, ok: r.ok, err: nil}
}
func (r Result_User_error) And(other interface{}) interface{} {
if r.tag == ResultTagOk {
return other
}
return r
}
func (r Result_User_error) Or(other Result_User_error) Result_User_error {
if r.tag == ResultTagOk {
return r
}
return other
}
// Sum type for user status - no boilerplate needed!
type UserStatusTag uint8
const (
UserStatusTagActive UserStatusTag = iota
UserStatusTagPending
UserStatusTagSuspended
)
type UserStatus struct {
tag UserStatusTag
}
func UserStatusActive() UserStatus {
return UserStatus{tag: UserStatusTagActive}
}
func UserStatusPending() UserStatus {
return UserStatus{tag: UserStatusTagPending}
}
func UserStatusSuspended() UserStatus {
return UserStatus{tag: UserStatusTagSuspended}
}
func (e UserStatus) IsActive() bool {
return e.tag == UserStatusTagActive
}
func (e UserStatus) IsPending() bool {
return e.tag == UserStatusTagPending
}
func (e UserStatus) IsSuspended() bool {
return e.tag == UserStatusTagSuspended
}
// Domain models
type User struct {
ID int
Username string
Email string
Status UserStatus
Profile *UserProfile // Optional profile (Phase 7 - safe navigation)
}
type UserProfile struct {
Bio *string
Website *string
PhoneNumber *string
Country *string
}
type RegisterRequest struct {
Username string
Email string
Password string
Profile *ProfileInput // Optional profile data
}
type ProfileInput struct {
Bio *string
Website *string
Phone *string
Country *string
}
func validateEmail(email string) Result[string, error] {
if !strings.Contains(email, "@") || !strings.Contains(email, ".") {
return Result_interface_string{tag: ResultTagErr, err: func() *string {
tmp14 := "invalid email format"
return &tmp14
}()}
}
return Result_interface_error{tag: ResultTagOk, ok: &email}
}
func validatePassword(password string) Result[string, error] {
if len(password) < 8 {
return Result_interface_string{tag: ResultTagErr, err: func() *string {
tmp15 := "password must be at least 8 characters"
return &tmp15
}()}
}
return Result_interface_error{tag: ResultTagOk, ok: &password}
}
func validateUsername(username string) Result[string, error] {
if len(username) < 3 {
return Result_interface_string{tag: ResultTagErr, err: func() *string {
tmp16 := "username must be at least 3 characters"
return &tmp16
}()}
}
if len(username) > 20 {
return Result_interface_string{tag: ResultTagErr, err: func() *string {
tmp17 := "username too long"
return &tmp17
}()}
}
return Result_interface_error{tag: ResultTagOk, ok: &username}
}
// Database operations using Result types
func checkUserExists(db *sql.DB, email string) Result[bool, error] {
var exists bool
tmp, err := db.QueryRow("SELECT EXISTS(SELECT 1 FROM users WHERE email = ?)").Scan(&exists)
if err != nil {
return nil, err
}
// dingo:e:1
var err = tmp
if err != nil {
return Result_interface_error{tag: ResultTagErr, err: &err}
}
return Result_interface_error{tag: ResultTagOk, ok: &exists}
}
func hashPassword(password string) Result[string, error] {
if password == "" {
return Result_interface_string{tag: ResultTagErr, err: func() *string {
tmp18 := "cannot hash empty password"
return &tmp18
}()}
}
return Result_interface_error{tag: ResultTagOk, ok: func() *interface{} {
tmp19 := "hashed_" + password
return &tmp19
}()}
}
func saveUser(db *sql.DB, username string, email string, hashedPwd string, status UserStatus, profile *UserProfile) Result[int64, error] {
bio := func() string {
coalesce := profile
if coalesce.IsSome() {
return coalesce.Unwrap()
}
return ""
}()
website := func() string {
coalesce1 := profile
if coalesce1.IsSome() {
return coalesce1.Unwrap()
}
return ""
}()
phone := func() string {
coalesce2 := profile
if coalesce2.IsSome() {
return coalesce2.Unwrap()
}
return ""
}()
country := func() string {
coalesce3 := profile
if coalesce3.IsSome() {
return coalesce3.Unwrap()
}
return "US"
}()
result, err := db.Exec(
"INSERT INTO users __TUPLE_8__LITERAL__eb050a9d(username, email, password, status, bio, website, phone, country) VALUES __TUPLE_8__LITERAL__93fb6712(?, ?, ?, ?, ?, ?, ?, ?)",
username, email, hashedPwd, status, bio, website, phone, country,
)
if err != nil {
return Result_interface_error{tag: ResultTagErr, err: &err}
}
id, err1 := result.LastInsertId()
if err1 != nil {
return Result_interface_error{tag: ResultTagErr, err: &err1}
}
return Result_interface_error{tag: ResultTagOk, ok: &id}
}
// Main business logic - showcases error propagation and safe navigation
// Demonstrates manual error handling (? operator support coming in future phase)
// NEW (Phase 7): Safe navigation (?.) and null coalescing (??) for optional fields
func registerUser(db *sql.DB, req RegisterRequest) Result[User, error] {
emailResult := validateEmail(req.Email)
if emailResult.IsErr() {
return Result_interface_string{tag: ResultTagErr, err: func() *string {
tmp20 := "email validation failed"
return &tmp20
}()}
}
email := emailResult.Unwrap()
passwordResult := validatePassword(req.Password)
if passwordResult.IsErr() {
return Result_interface_string{tag: ResultTagErr, err: func() *string {
tmp21 := "password validation failed"
return &tmp21
}()}
}
password := passwordResult.Unwrap()
usernameResult := validateUsername(req.Username)
if usernameResult.IsErr() {
return Result_interface_string{tag: ResultTagErr, err: func() *string {
tmp22 := "username validation failed"
return &tmp22
}()}
}
username := usernameResult.Unwrap()
existsResult := checkUserExists(db, email)
if existsResult.IsErr() {
return Result_interface_string{tag: ResultTagErr, err: func() *string {
tmp23 := "failed to check user existence"
return &tmp23
}()}
}
if existsResult.Unwrap() {
return Result_interface_string{tag: ResultTagErr, err: func() *string {
tmp24 := "user already exists"
return &tmp24
}()}
}
userProfile := buildUserProfile(req.Profile)
hashedPasswordResult := hashPassword(password)
if hashedPasswordResult.IsErr() {
return Result_interface_string{tag: ResultTagErr, err: func() *string {
tmp25 := "password hashing failed"
return &tmp25
}()}
}
hashedPassword := hashedPasswordResult.Unwrap()
idResult := saveUser(db, username, email, hashedPassword, UserStatus_Pending, userProfile)
if idResult.IsErr() {
return Result_interface_string{tag: ResultTagErr, err: func() *string {
tmp26 := "failed to save user"
return &tmp26
}()}
}
id := idResult.Unwrap()
return Result_User_error{tag: ResultTagOk, ok: func() *User {
tmp27 := User{
ID: int(id),
Username: username,
Email: email,
Status: UserStatus_Pending,
Profile: userProfile,
}
return &tmp27
}()}
}
// NEW (Phase 7): Build user profile with safe defaults using ?. and ??
func buildUserProfile(input *ProfileInput) *UserProfile {
return &UserProfile{
Bio: input,
Website: input,
PhoneNumber: input,
Country: input,
}
}
// HTTP handler - clean and focused on business logic
func handleRegister(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req RegisterRequest
err := json.NewDecoder(r.Body).Decode(&req)
if err != nil {
http.Error(w, "invalid request body", http.StatusBadRequest)
return
}
result := registerUser(db, req)
if result.IsOk() {
user := result.Unwrap()
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(user)
} else {
err1 := result.UnwrapErr()
http.Error(w, err1.Error(), http.StatusBadRequest)
}
}
}
// NEW (Phase 7): Handler demonstrating safe navigation in response formatting
func handleGetUser(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
userID := r.URL.Query().Get("id")
if userID == "" {
http.Error(w, "user ID required", http.StatusBadRequest)
return
}
user := getUserByID(db, userID)
response := map[string]interface{}{
"id": userID,
"username": func() string {
coalesce4 := user
if coalesce4.IsSome() {
return coalesce4.Unwrap()
}
return "unknown"
}(),
"email": func() string {
coalesce5 := user
if coalesce5.IsSome() {
return coalesce5.Unwrap()
}
return "no-email@example.com"
}(),
"status": getUserStatusString(user),
"bio": func() string {
coalesce6 := user
if coalesce6.IsSome() {
return coalesce6.Unwrap()
}
return "No bio provided"
}(),
"website": func() string {
coalesce7 := user
if coalesce7.IsSome() {
return coalesce7.Unwrap()
}
return ""
}(),
"phone": func() string {
coalesce8 := user
if coalesce8.IsSome() {
return coalesce8.Unwrap()
}
return ""
}(),
"country": func() string {
coalesce9 := user
if coalesce9.IsSome() {
return coalesce9.Unwrap()
}
return "Unknown"
}(),
}
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(response)
}
}
// Helper functions for new handler
func getUserByID(db *sql.DB, id string) *User {
return nil
}
func getUserStatusString(status UserStatus) string {
if status == UserStatus_Active {
return "active"
}
if status == UserStatus_Pending {
return "pending"
}
if status == UserStatus_Suspended {
return "suspended"
}
return "unknown"
}
Test: showcase_01_api_server.dingo
Status: 🌟 PRIMARY LANDING PAGE EXAMPLE 🌟
Purpose: Demonstrate ALL currently implemented Dingo features in one realistic, production-like example
Context: User registration API endpoint with validation, database operations, and error handling
This is THE flagship showcase example - the first thing visitors see at dingolang.com!
Maintenance Responsibilities:
go test ./tests -run TestGoldenFiles/showcase_01_api_server -vCurrently Demonstrates:
enum UserStatus - 85.7% code reduction vs Go tagged unions!)? operator eliminates if err != nil): syntax for function parameters)let bindings (immutable variable declarations)See CLAUDE.md for full maintenance guidelines.
This showcase is THE flagship example. It MUST demonstrate all working features to maximize impact:
Enums / Sum Types - enum UserStatus { Active, Pending, Suspended }
Error Propagation (? operator) - let email = validateEmail(req.Email)?
if err != nil { return ..., err } boilerplateType Annotations (: syntax) - func validateEmail(email: string)
let Bindings - let email = validateEmail(...)?
Comments Preservation - Currently missing in Go output
Lambda Syntax (if supported) - Short function notation
func(w http.ResponseWriter, r *http.Request) { ... }This comprehensive example showcases every major feature currently implemented in Dingo:
enum keyword)enum UserStatus {
Active,
Pending,
Suspended
}Dingo: 4 lines of clean, declarative code Go Equivalent: 18+ lines of tagged union boilerplate with:
const)isUserStatus())Code Reduction: ~78% (4 lines vs 18 lines)
func validateEmail(email: string) Result<string, error> {
if !strings.Contains(email, "@") {
return Err(errors.New("invalid email format"))
}
return Ok(email)
}Dingo: Explicit Result type makes errors visible in function signatures Go Equivalent: Same semantics, but less explicit about error handling intent
Benefit:
? operator)The star of the show - compare these two versions:
func registerUser(db: *sql.DB, req: RegisterRequest) Result<User, error> {
// All validations with automatic error propagation
email := validateEmail(req.Email)?
password := validatePassword(req.Password)?
username := validateUsername(req.Username)?
exists := checkUserExists(db, email)?
if exists {
return Err(errors.New("user already exists"))
}
hashedPassword := hashPassword(password)?
id := saveUser(db, username, email, hashedPassword, UserStatus.Pending)?
user := User{
ID: int(id),
Username: username,
Email: email,
Status: UserStatus.Pending,
}
return Ok(user)
}func registerUser(db *sql.DB, req RegisterRequest) (User, error) {
email, err := validateEmail(req.Email)
if err != nil {
return User{}, err
}
password, err := validatePassword(req.Password)
if err != nil {
return User{}, err
}
username, err := validateUsername(req.Username)
if err != nil {
return User{}, err
}
exists, err := checkUserExists(db, email)
if err != nil {
return User{}, err
}
if exists {
return User{}, errors.New("user already exists")
}
hashedPassword, err := hashPassword(password)
if err != nil {
return User{}, err
}
id, err := saveUser(db, username, email, hashedPassword, UserStatusPendingValue())
if err != nil {
return User{}, err
}
user := User{
ID: int(id),
Username: username,
Email: email,
Status: UserStatusPendingValue(),
}
return user, nil
}Code Reduction: ~68% (11 lines of logic vs 34 lines with boilerplate)
Error Handling Statements:
if err != nil checks (handled by ?): syntax)func validateEmail(email: string) Result<string, error>
func handleRegister(db: *sql.DB) http.HandlerFuncBenefit:
| Metric | Dingo | Go | Reduction |
|---|---|---|---|
| Total Lines | 135 | 159 | 15% |
| Enum Boilerplate | 4 | 22 | 78% |
| Error Checks | 0 (? operator) |
10 (if err != nil) |
100% |
| registerUser() Function | 27 | 41 | 34% |
| Clarity | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | Subjective but significant |
Dingo:
?Go:
if err != nil everywhereUser{}, 0, "") scattered throughoutThis is a small example (135 lines). Imagine a real API with:
Extrapolated savings for a 10,000 line Go codebase:
if err != nil checks// Developer spends cognitive energy on:
// 1. Writing if err != nil checks
// 2. Remembering zero values for early returns
// 3. Implementing tagged unions manually
// 4. Reading through error handling to find business logic// Developer focuses on:
// 1. Business logic only
// 2. Domain modeling (enums, types)
// 3. Happy path is immediately visible
// 4. Errors are handled automaticallyThis example addresses three of the highest-voted Go proposals:
Error Propagation - Proposal #71203
? operator eliminates repetitive error handlingSum Types - Proposal #19412
enum keyword with zero boilerplateResult Types - [Community discussions across multiple proposals]
Result<T,E> type that transpiles to idiomatic (T, error)(T, error) tuples (zero runtime cost)? operator → Expanded to if err != nil { return ..., err } (no magic)The generated Go code is:
go buildThis is the FIRST example visitors see at dingolang.com
Left Side - Dingo (The Future):
// 27 lines of clean, readable code
func registerUser(db: *sql.DB, req: RegisterRequest) (User, error) {
let email = validateEmail(req.Email)?
let password = validatePassword(req.Password)?
let username = validateUsername(req.Username)?
// ... beautiful, focused business logic ...
}Right Side - Go (The Present):
// 59 lines of verbose, repetitive code
func registerUser(db *sql.DB, req RegisterRequest) (User, error) {
__tmp0, __err0 := validateEmail(req.Email)
if __err0 != nil {
return User{}, __err0
}
var email = __tmp0
// ... 50+ more lines of boilerplate ...
}Above the code:
"Look how short and cool that is!"
Dingo is Go, but 54% shorter and infinitely more readable.
Below the code:
if err != nil checks - handled automatically with ?Track these for landing page optimization:
This showcase demonstrates that Dingo is not just syntax sugar - it's a productivity multiplier that:
The value proposition is clear: Write Dingo, get cleaner code, ship faster, maintain easier.
And this example proves it at first glance. 🎯
See Also:
error_prop_01_simple.reasoning.md - Error propagation deep divesum_types_01_simple_enum.reasoning.md - Sum types explanationtests/golden/README.md - Complete test catalogJoin the discussion to share your thoughts, ask questions, and connect with the Dingo community.
Loading comments...