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 |
|---|
| 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 |
|---|
| 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 |
|---|
| 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 |
|---|
| 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 |
|---|
| // ✅ 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 |
|---|
| // ✅ 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.