DEV Community

ym qu
ym qu

Posted on

Mastering Go Reflection: A Comprehensive Guide from Basics to Advanced πŸš€

Go's reflection is a powerful feature that allows inspection and manipulation of program types at runtime. It's primarily implemented through the reflect package.

Why Use Reflection?

  1. Dynamic Type Checking: Examine variable types and properties at runtime
  2. Dynamic Invocation: Call functions or methods of unknown types at runtime
  3. Serialization/Deserialization: Traverse struct fields for JSON parsing
  4. Frameworks & Libraries: Handle dynamic types in DI and ORM frameworks

Core Concepts

  1. Type: Represents Go types using reflect.Type
  2. Value: Represents Go values using reflect.Value

Basic Operations

1. Getting Reflection Objects

  • Use reflect.TypeOf for type information
  • Use reflect.ValueOf for value information

2. Type Checking

  • Use the Kind method to check variable categories

3. Struct Field Operations

  • Get and set struct field values, invoke struct methods

Code Examples

Getting Type and Value

package main

import (
    "fmt"
    "reflect"
)

func main() {
    var x float64 = 3.4
    fmt.Println("type:", reflect.TypeOf(x))
    fmt.Println("value:", reflect.ValueOf(x))
}
Enter fullscreen mode Exit fullscreen mode

Dynamic Value Setting

package main

import (
    "fmt"
    "reflect"
)

func main() {
    var x float64 = 3.4
    v := reflect.ValueOf(&x)
    v = v.Elem()
    if v.CanSet() {
        v.SetFloat(7.1)
    }
    fmt.Println(x)
}
Enter fullscreen mode Exit fullscreen mode

Working with Struct Fields

package main

import (
    "fmt"
    "reflect"
)

type Person struct {
    Name string
    Age  int
}

func main() {
    p := Person{"Alice", 30}
    v := reflect.ValueOf(&p).Elem()

    name := v.FieldByName("Name")
    age := v.FieldByName("Age")

    fmt.Println("Name:", name)
    fmt.Println("Age:", age)

    if name.CanSet() {
        name.SetString("Bob")
    }
    if age.CanSet() {
        age.SetInt(40)
    }

    fmt.Println("Updated person:", p)
}
Enter fullscreen mode Exit fullscreen mode

Important Considerations

  1. Performance: Reflection adds overhead; use cautiously in performance-critical code
  2. Type Safety: Bypasses compile-time type checking, may cause runtime errors
  3. Exported Fields: Only exported fields (capitalized) can be accessed

Common Use Cases

  1. Serialization/Deserialization: JSON, XML parsing
  2. Dependency Injection: Automatic dependency wiring
  3. ORM Frameworks: Object-relational mapping

Summary

Reflection is a powerful Go feature for runtime type and value manipulation. While it offers great flexibility, consider performance implications and type safety. Use it judiciously based on your specific requirements.

Top comments (0)