Struct Field Assignment
Harneet supports Go-like direct struct field assignment, allowing you to access and modify struct fields using dot notation.
Basic Syntax
Field Access
| Field Access |
|---|
| var person = Person{Name: "Alice", Age: 30}
var name = person.Name // Access field value
var age = person.Age // Access field value
|
Field Assignment
| Field Assignment |
|---|
| person.Name = "Bob" // Assign new value to field
person.Age = 25 // Assign new value to field
|
Zero Value Initialization
Structs can be declared without initialization, and all fields will be set to their zero values:
| Zero Values |
|---|
| type Person struct {
Name string
Age int
Active bool
}
function main() {
var p Person // Zero value initialization
// p.Name = "" (empty string)
// p.Age = 0 (zero integer)
// p.Active = false (false boolean)
// Assign fields directly
p.Name = "Alice"
p.Age = 30
p.Active = true
}
|
Nested Field Assignment
Harneet supports nested field assignment on chained dotted receivers.
| Nested Assignment |
|---|
| type Address struct { city string; zip int }
type Person struct { name string; addr Address }
function main() {
var p = Person{name: "Alice", addr: Address{city: "SF", zip: 94105}}
p.addr.city = "LA"
p.addr.zip = 90001
fmt.Println(p) // Person{name: Alice, addr: Address{zip: 90001, city: LA}}
}
|
Method Calls on Fields
You can call methods directly on field values without introducing intermediates.
| Method Calls on Fields |
|---|
| type Address struct { city string }
function (a Address) toString() string { return a.city }
type Person struct { name string; addr Address }
function main() {
var p = Person{name: "Alice", addr: Address{city: "Paris"}}
fmt.Println(p.addr.toString()) // Paris
}
|
Compile-time Validation of Dotted Chains
The type checker validates receivers for dotted access at compile-time:
- Struct receiver required: Each
. step must have a struct-like receiver (struct or user-defined struct type). - Invalid receiver error: Accessing a field or calling a method on a non-struct produces a type error.
Examples:
| Reference Semantics |
|---|
| type Person struct { name string }
var p = Person{name: "A"}
var n = 42
// ❌ Error: cannot access field name on type int
n.name = "x"
// ❌ Error: cannot call method toString on type int
n.toString()
// ✅ OK: structs and nested fields are validated step-by-step
p.name = "Bob"
|
Zero Values by Type
| Type | Zero Value |
string | "" (empty string) |
int | 0 |
float64 | 0.0 |
bool | false |
map[K]V | None (must be initialized) |
| Custom structs | All fields set to their zero values |
Complete Examples
Basic Field Operations
| Basic Operations |
|---|
| type Person struct {
Name string
Age int
Active bool
}
function main() {
// Method 1: Zero value initialization + field assignment
var p1 Person
p1.Name = "Alice"
p1.Age = 30
p1.Active = true
// Method 2: Struct literal initialization
var p2 = Person{Name: "Bob", Age: 25, Active: false}
// Field access
fmt.Printf("p1.Name: %s\n", p1.Name)
fmt.Printf("p2.Age: %d\n", p2.Age)
// Field modification
p2.Age = p2.Age + 1
p2.Active = !p2.Active
}
|
Multiple Struct Instances
| Multiple Instances |
|---|
| type Point struct {
X int
Y int
}
function main() {
var p1 Point
var p2 Point
// Each instance is independent
p1.X = 10
p1.Y = 20
p2.X = 30
p2.Y = 40
fmt.Printf("p1: (%d, %d)\n", p1.X, p1.Y) // (10, 20)
fmt.Printf("p2: (%d, %d)\n", p2.X, p2.Y) // (30, 40)
}
|
Field Assignment in Functions
| Functions with Structs |
|---|
| type Rectangle struct {
Width int
Height int
}
function setDimensions(rect Rectangle, w int, h int) {
rect.Width = w
rect.Height = h
}
function main() {
var r Rectangle
setDimensions(r, 100, 50)
fmt.Printf("Rectangle: %dx%d\n", r.Width, r.Height)
}
|
Export Rules (Go-like Convention)
Field visibility follows Go-like export conventions:
| Export Rules |
|---|
| type User struct {
Name string // Exported (accessible from other packages)
age int // Unexported (package-private)
Email string // Exported
password string // Unexported
}
|
- Exported fields: Start with uppercase letter, accessible from other packages
- Unexported fields: Start with lowercase letter, only accessible within the same package
Comparison with Other Languages
Go Similarity
| // Go
type Person struct {
Name string
Age int
}
function main() {
var p Person
p.Name = "Alice"
p.Age = 30
}
|
| Harneet Syntax |
|---|
| // Harneet (nearly identical)
type Person struct {
Name string
Age int
}
function main() {
var p Person
p.Name = "Alice"
p.Age = 30
}
|
Differences from JavaScript
| // JavaScript - dynamic typing
var person = {};
person.name = "Alice"; // Can add fields dynamically
person.age = 30;
|
| Static Typing |
|---|
| // Harneet - static typing
type Person struct {
Name string
Age int
}
var person Person // Must declare struct type first
person.Name = "Alice" // Only predefined fields allowed
person.Age = 30
|
Best Practices
- Use descriptive field names:
UserName instead of Name when context matters - Follow export conventions: Uppercase for public fields, lowercase for private
- Initialize before use: Always ensure structs are properly initialized
- Zero value awareness: Understand what zero values mean for your use case
- Prefer struct literals: Use
Person{Name: "Alice", Age: 30} when you have all values
Error Cases
| Error Cases |
|---|
| type Person struct {
Name string
Age int
}
function main() {
var p Person
// ✅ Valid operations
p.Name = "Alice"
var name = p.Name
// ❌ Invalid operations
// p.InvalidField = "value" // Error: field doesn't exist
// var x = p.Name.InvalidMethod() // Error: strings don't have methods
}
|
Integration with Other Features
With Maps
| Structs with Maps |
|---|
| type Config struct {
Settings map[string]string
}
function main() {
var cfg Config
cfg.Settings = {"theme": "dark", "lang": "en"}
var theme = cfg.Settings["theme"]
}
|
With Arrays
| Structs with Arrays |
|---|
| type Team struct {
Members []string
}
function main() {
var team Team
team.Members = ["Alice", "Bob", "Charlie"]
var firstMember = team.Members[0]
}
|
With Functions
| Structs with Functions |
|---|
| type Calculator struct {
Result float64
}
function (c Calculator) add(x float64) {
c.Result = c.Result + x
}
function main() {
var calc Calculator
calc.add(10.5)
fmt.Printf("Result: %f\n", calc.Result)
}
|
Current Limitations
- Field address taking: Cannot take addresses of fields (no pointers yet)
Future Enhancements
- Struct embedding and inheritance
- Field tags and metadata
- Pointer semantics for reference types