Hone logo
Hone
Problems

Dynamic Object Inspection and Modification with Reflection

Reflection allows a program to examine and modify the structure and data of another program at runtime. This challenge asks you to build a simplified reflection system in Go that can inspect the fields of a struct, retrieve their values, and optionally, modify them. This is useful for tasks like generic data processing, serialization/deserialization, and dynamic configuration.

Problem Description

You are tasked with creating a Reflector type in Go that can inspect and manipulate the fields of a struct. The Reflector should provide the following functionalities:

  1. Inspect(s interface{}) ([]FieldInfo, error): This method takes an interface{} representing any struct as input. It should return a slice of FieldInfo structs, each containing the field's name and its value. If the input is not a struct, it should return an error.

  2. SetField(s interface{}, fieldName string, newValue interface{}) error: This method takes an interface{} representing a struct, a field name (string), and a new value (interface{}). It should attempt to set the value of the specified field in the struct to the new value. If the field does not exist or the type is incompatible, it should return an error.

  3. FieldInfo struct: This struct should have two fields: Name string and Value interface{}.

The Inspect method should handle various data types for the field values (e.g., strings, integers, booleans, other structs). The SetField method should handle type conversions where possible (e.g., setting an integer field to a string representation of an integer). If a type conversion is not possible, it should return an error.

Examples

Example 1:

Input:
type Person struct {
    Name string
    Age  int
    IsActive bool
}

p := Person{Name: "Alice", Age: 30, IsActive: true}
Reflector.Inspect(p)

Output:
[
    {Name: "Name", Value: "Alice"},
    {Name: "Age", Value: 30},
    {Name: "IsActive", Value: true},
]

Explanation: The Inspect method correctly identifies and retrieves the name, age, and isActive fields and their corresponding values from the Person struct.

Example 2:

Input:
type Person struct {
    Name string
    Age  int
}

p := Person{Name: "Bob", Age: 25}
Reflector.SetField(p, "Age", "35")
fmt.Println(p)

Output:
{Bob 35}

Explanation: The SetField method successfully modifies the Age field of the Person struct to 35. Note that the string "35" is implicitly converted to the integer 35.

Example 3: (Edge Case)

Input:
type Person struct {
    Name string
    Age  int
}

p := Person{Name: "Charlie", Age: 40}
Reflector.SetField(p, "Address", "123 Main St")

Output:
Error: Field Address not found

Explanation: The SetField method returns an error because the Address field does not exist in the Person struct.

Constraints

  • The input struct can contain fields of any basic Go type (string, int, bool, float64) and nested structs.
  • The SetField method should handle type conversions where possible. If a conversion is not possible, it should return an error.
  • The Inspect method should handle exported fields only (fields starting with a capital letter).
  • The SetField method should only modify exported fields.
  • The code should be well-documented and easy to understand.
  • Error handling is crucial. Return meaningful errors when appropriate.

Notes

  • Use the reflect package in Go to achieve reflection.
  • Consider using reflect.ValueOf and reflect.TypeOf to inspect the struct and its fields.
  • Pay close attention to type safety when setting field values.
  • Think about how to handle errors gracefully and provide informative error messages.
  • The interface{} type allows for flexibility in handling different data types, but also requires careful type assertions and conversions.
  • This is a simplified reflection system. A full reflection system would handle more complex scenarios, such as pointers, slices, and maps. Focus on the core functionality described above.
Loading editor...
go