SoFunction
Updated on 2025-04-05

Three usage scenarios of reflection mechanism in go language

Three usage scenarios

1. JSON analysis: reflection can be used to implement general structure analysis and dynamically map fields.
2. ORM framework: Reflection can be used to dynamically process the mapping of database fields and structure fields.
3. Interface adaptation: dynamically check and implement interfaces.

1. JSON analysis: Use reflection to implement general structure analysis

In actual projects, we may encounter situations where we need to parse JSON data into different structures. Through the reflection mechanism, we can write a general function that dynamically parses JSON data into a structure passed in any way.

Sample code

package main

import (
    "encoding/json"
    "fmt"
    "reflect"
)

// General JSON parsing functionfunc parseJSON(data []byte, result interface{}) error {
    // Make sure that the result passed in is the pointer type    if (result).Kind() !=  {
        return ("result must be a pointer type")
    }
    return (data, result)
}

type User struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

type Product struct {
    ID    int     `json:"id"`
    Title string  `json:"title"`
    Price float64 `json:"price"`
}

func main() {
    // Example JSON data    userJSON := `{"name": "Alice", "age": 30}`
    productJSON := `{"id": 101, "title": "Laptop", "price": 999.99}`

    // parse into User structure    var user User
    if err := parseJSON([]byte(userJSON), &user); err != nil {
        ("User parsing failed:", err)
    } else {
        ("Resolved User: %+v\n", user)
    }

    // parse into Product structure    var product Product
    if err := parseJSON([]byte(productJSON), &product); err != nil {
        ("Product parsing failed:", err)
    } else {
        ("Resolved Product: %+v\n", product)
    }
}

Output result

Analyzed User: {Name:Alice Age:30}
Analytical Product: {ID:101 Title:Laptop Price:999.99}

explain

  • We use reflection to check if the incoming result is a pointer type.
  • Dynamically parse JSON data into different structures.

2. ORM framework: Mapping database fields and structure fields through reflection

When building an ORM (Object Relational Mapping) framework, you can use the reflection mechanism to dynamically map database query results to the structure. The following example shows how to use reflection to generate a structure instance from a database query result.

Sample code

package main

import (
    "database/sql"
    "fmt"
    "reflect"

    _ "/mattn/go-sqlite3"
)

// General database row mapping functionfunc mapRowToStruct(rows *, dest interface{}) error {
    // Get the value and type of the structure    destValue := (dest).Elem()
    destType := ()

    // Get the column name    columns, err := ()
    if err != nil {
        return err
    }

    // Create slices that store column data    values := make([]interface{}, len(columns))
    for i := range values {
        values[i] = (("")).Interface()
    }

    // Read row data    if () {
        if err := (values...); err != nil {
            return err
        }
    }

    // Map column data to structure fields    for i, column := range columns {
        field := (func(s string) bool {
            return (s).("db") == column
        })

        if () && () {
            (*(values[i].(*string)))
        }
    }
    return nil
}

type Employee struct {
    Name string `db:"name"`
    Age  string `db:"age"`
}

func main() {
    // Create a database and insert data    db, _ := ("sqlite3", ":memory:")
    defer ()

    ("CREATE TABLE employees (name TEXT, age TEXT)")
    ("INSERT INTO employees (name, age) VALUES ('Bob', '28')")

    // Query the database    rows, _ := ("SELECT name, age FROM employees")

    // Map the result to the structure    var emp Employee
    if err := mapRowToStruct(rows, &emp); err != nil {
        ("Map failed:", err)
    } else {
        ("Queryed Employee: %+v\n", emp)
    }
}

Output result

Query Employee: {Name:Bob Age:28}

explain

  • Use the db tag to map column names and structure fields.
  • Implements a common mapping from database rows to structures.

3. Interface adaptation: dynamically check and implement interfaces

Sometimes, we need to check whether a type implements an interface, or call interface methods dynamically at runtime. The following example shows how to use reflection to implement interface adaptation.

Sample code

package main

import (
    "fmt"
    "reflect"
)

// Define the interfacetype Speaker interface {
    Speak() string
}

// Implement the structure of the interfacetype Dog struct {
    Name string
}

func (d Dog) Speak() string {
    return "Woof! I'm " + 
}

type Robot struct {
    Model string
}

func (r Robot) Speak() string {
    return "Beep! I'm model " + 
}

// General interface calls functionsfunc callSpeakIfPossible(i interface{}) {
    value := (i)
    method := ("Speak")

    // Check whether the Speak method is implemented    if () {
        results := (nil) // Call method        (results[0])
    } else {
        ("Speak method not implemented")
    }
}

func main() {
    // Test different types    dog := Dog{Name: "Rex"}
    robot := Robot{Model: "RX-78"}
    stranger := "Just a string"

    callSpeakIfPossible(dog)     // Woof! I'm Rex
    callSpeakIfPossible(robot)   // Beep! I'm model RX-78
    callSpeakIfPossible(stranger) // Speak method not implemented}

Output result

Woof! I'm Rex
Beep! I'm model RX-78
Speak method not implemented

explain

  • Used to dynamically obtain and call methods.
  • Through reflection, determine whether the incoming type implements the Speak() method and call it at runtime.

Summarize

  • JSON parsing: Use reflection to implement a general structure analysis function, dynamically processing different types of JSON data.
  • ORM framework: Use reflection to map database results to structure fields to implement common database queries.
  • Interface adaptation: dynamically check and call methods to achieve flexible interface processing.

These three scenarios fully demonstrate the powerful functions of reflection in Go, but also remind us of the performance overhead and complexity that reflection may bring, so it should be used with caution in actual development.

This is the article about the three usage scenarios of reflection mechanism in go language. For more related go languages, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!