Skip to content

Structs in Harneet

Harneet supports Go-like struct types for creating custom data structures with named fields, methods, and seamless integration with maps and JSON.

Struct Definitions

Define struct types using the type keyword:

Define Struct Types
type Person struct {
    name string
    age int
}

type Point struct {
    x int
    y int
}

type Employee struct {
    id int
    name string
    department string
    salary float64
    active bool
}

Struct Literals

Create struct instances using struct literals:

Single-line Literals

Single-line Struct Literals
var person1 = Person{name: "Alice", age: 30}
var point1 = Point{x: 10, y: 20}

Multi-line Literals

Multi-line Struct Literals
1
2
3
4
5
6
7
var employee = Employee{
    id: 1001,
    name: "John Smith",
    department: "Engineering",
    salary: 75000.0,
    active: true
}

Field Access

Access struct fields using dot notation:

Access Struct Fields
1
2
3
4
5
6
7
var person = Person{name: "Alice", age: 30}

// Access individual fields
var name = person.name     // "Alice"
var age = person.age       // 30

fmt.Printf("Name: %s, Age: %d\n", name, age)

Struct Methods

Define methods on struct types using receiver syntax:

Method Definition

Define Struct Methods
type Person struct {
    name string
    age int
}

// Method with no return value
function (p Person) greet() {
    fmt.Printf("Hello, my name is %s\n", p.name)
}

// Method with return value
function (p Person) getAge() int {
    return p.age
}

// Method with boolean return
function (p Person) isAdult() bool {
    return p.age >= 18
}

Method Calls

Call Struct Methods
1
2
3
4
5
6
var person = Person{name: "Alice", age: 30}

// Call methods on struct instances
person.greet()                    // "Hello, my name is Alice"
var age = person.getAge()         // 30
var adult = person.isAdult()      // true

Complex Methods

Complex Struct Methods
type Rectangle struct {
    width int
    height int
}

function (r Rectangle) area() int {
    return r.width * r.height
}

function (r Rectangle) perimeter() int {
    return 2 * (r.width + r.height)
}

function (r Rectangle) describe() {
    fmt.Printf("Rectangle: %dx%d (area=%d, perimeter=%d)\n", 
        r.width, r.height, r.area(), r.perimeter())
}

var rect = Rectangle{width: 10, height: 5}
rect.describe()  // "Rectangle: 10x5 (area=50, perimeter=30)"

Struct-to-Map Casting

Structs can be seamlessly converted to maps using the cast module:

Struct to Map Conversion
import cast

type User struct {
    id int
    username string
    active bool
}

var user = User{id: 123, username: "alice", active: true}

// Convert struct to map
var userMap, err = cast.ToMap(user)
if err == None {
    fmt.Printf("User as map: %s\n", userMap)
    // Output: User as map: {id: 123, username: alice, active: true}
}

// Check if conversion is possible
var canCast, _ = cast.CanCast(user, "map")
fmt.Printf("Can cast to map: %s\n", canCast)  // true

JSON Integration

Structs integrate seamlessly with JSON through map conversion:

Struct JSON Integration
import cast
import json

type Product struct {
    id int
    name string
    price float64
    inStock bool
}

var product = Product{
    id: 12345,
    name: "Laptop Computer",
    price: 999.99,
    inStock: true
}

// Struct → Map → JSON
var productMap, _ = cast.ToMap(product)
var jsonStr, _ = json.Marshal(productMap)
fmt.Printf("JSON: %s\n", jsonStr)
// Output: {"id":12345,"name":"Laptop Computer","price":999.99,"inStock":true}

Typed Arrays

Harneet supports typed arrays with a specified size and element type:

Primitive Type Arrays

Primitive Type Arrays
1
2
3
4
var numbers = int[5]{1, 2, 3, 4, 5}
var names = string[3]{"Alice", "Bob", "Charlie"}
var flags = bool[2]{true, false}
var scores = float64[4]{95.5, 87.2, 92.8, 88.1}

Struct Type Arrays

Struct Type Arrays
var points = Point[3]{
    Point{x: 0, y: 0},
    Point{x: 10, y: 20},
    Point{x: 30, y: 40}
}

var people = Person[2]{
    Person{name: "Alice", age: 30},
    Person{name: "Bob", age: 25}
}

Field Types

Structs support all Harneet primitive types:

  • string - Text values
  • int, int8, int16, int32, int64 - Integer values
  • uint, uint8, uint16, uint32, uint64, uintptr - Unsigned integers
  • float32, float64 - Floating-point values
  • bool - Boolean values

Type Safety

Harneet enforces type safety for structs:

Required Fields

All fields must be provided in struct literals:

Required Fields
1
2
3
4
5
// ✅ Valid - all fields provided
var person = Person{name: "Alice", age: 30}

// ❌ Error - missing 'age' field
var person = Person{name: "Alice"}

Field Validation

Only defined fields are allowed:

Field Validation
// ❌ Error - 'height' is not a field of Person
var person = Person{name: "Alice", age: 30, height: 170}

Method Validation

Methods are type-checked and validated:

Method Type Checking
1
2
3
4
5
// ✅ Valid method call
var age = person.getAge()

// ❌ Error - method doesn't exist
var invalid = person.nonExistentMethod()

Zero Values

Struct fields can be explicitly set to zero values:

Zero Values
var emptyPerson = Person{name: "", age: 0}
var emptyPoint = Point{x: 0, y: 0}

Advanced Examples

Complete Struct with Methods and Casting

Complete Struct Example
import fmt
import cast
import json

type Account struct {
    id int
    name string
    balance float64
    active bool
}

function (a Account) getBalance() float64 {
    return a.balance
}

function (a Account) isActive() bool {
    return a.active
}

function (a Account) getInfo() string {
    return a.name
}

function (a Account) describe() {
    fmt.Printf("Account %d: %s (Balance: %.2f, Active: %s)\n", 
        a.id, a.name, a.balance, a.active)
}

var account = Account{
    id: 1001,
    name: "Alice Johnson",
    balance: 2500.50,
    active: true
}

// Use methods
account.describe()
var balance = account.getBalance()
var active = account.isActive()

// Access fields
var name = account.name
var id = account.id

// Convert to map and JSON
var accountMap, _ = cast.ToMap(account)
var accountJson, _ = json.Marshal(accountMap)

fmt.Printf("As JSON: %s\n", accountJson)

Multiple Struct Types

Multiple Struct Types
type Customer struct {
    id int
    name string
    email string
}

function (c Customer) getContact() string {
    return c.email
}

type Order struct {
    id int
    customerId int
    amount float64
    status string
}

function (o Order) isComplete() bool {
    return o.status == "completed"
}

var customer = Customer{id: 1, name: "Alice", email: "alice@example.com"}
var order = Order{id: 100, customerId: 1, amount: 99.99, status: "completed"}

// Use methods on different types
var contact = customer.getContact()
var complete = order.isComplete()

// Convert both to maps
var customerMap, _ = cast.ToMap(customer)
var orderMap, _ = cast.ToMap(order)

Current Capabilities ✅

Struct Definitions: type Name struct { field type }
Struct Literals: Name{field: value} (single and multi-line)
Field Access: struct.field syntax
Methods: function (receiver Type) method() { ... }
Method Calls: struct.method() syntax
Typed Arrays: type[size]{elements} for all types
Struct-to-Map Casting: cast.ToMap(struct)
JSON Integration: Full struct ↔ map ↔ JSON workflow
Type Safety: Compile-time and runtime validation
Error Handling: Clear, actionable error messages

Future Enhancements

The struct system is designed to be extensible for future features:

  • Struct embedding for composition
  • Constructor functions
  • Access control modifiers (public/private)
  • Interface implementations
  • Pointer receivers for methods
  • Map-to-struct casting

Integration with Other Modules

Cast Module

  • cast.ToMap(struct) - Convert struct to map
  • cast.CanCast(struct, "map") - Check conversion possibility
  • Full type validation and error handling

JSON Module

  • Seamless struct → map → JSON conversion
  • Perfect for API responses and data serialization
  • Round-trip conversion support

Type System

  • Full compile-time type checking
  • Method signature validation
  • Field access validation
  • Type compatibility checking

This makes Harneet's struct system as powerful and developer-friendly as Go's, with the added benefit of seamless JSON integration and comprehensive type safety.