Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Type Assertion and Struct Handling in Go

Tech May 15 1

Go's type assertion mechanism provides a powerful way to work with interface values and extract concrete types. This article explores practical applications through a search and data retrieval example combining Elasticsearch and MySQL.

package main

import (
    "context"
    "database/sql"
    "encoding/json"
    "fmt"
    "log"
    "strconv"
    "strings"

    "github.com/elastic/go-elasticsearch/v7"
    _ "github.com/go-sql-driver/mysql"
)

type ChapterMetadata struct {
    ChapterID int    `json:"chapter_id"`
    Name      string `json:"name"`
}

type BookInformation struct {
    ChapterID      int
    Name           string
    Writer         string
    Description    string
    ReleaseDate    string
}

func executeSearch() {
    client, err := elasticsearch.NewDefaultClient()
    if err != nil {
        log.Fatalf("Client initialization failed: %s", err)
    }

    targetName := "狼性总裁"
    
    searchQuery := fmt.Sprintf(`{
        "query": {
            "match": {
                "title": "%s"
            }
        }
    }`, targetName)

    result, err := client.Search(
        client.Search.WithContext(context.Background()),
        client.Search.WithIndex("book_chapters_index"),
        client.Search.WithBody(strings.NewReader(searchQuery)),
        client.Search.WithTrackTotalHits(true),
    )
    if err != nil {
        log.Fatalf("Search execution error: %s", err)
    }
    defer result.Body.Close()

    var responseData map[string]interface{}
    if err := json.NewDecoder(result.Body).Decode(&responseData); err != nil {
        log.Fatalf("Response parsing error: %s", err)
    }

    hitList := responseData["hits"].(map[string]interface{})["hits"].([]interface{})
    var chapterIDs []int
    for _, item := range hitList {
        sourceData := item.(map[string]interface{})["_source"].(map[string]interface{})
        chapterID := int(sourceData["id"].(float64))
        chapterIDs = append(chapterIDs, chapterID)
    }

    if len(chapterIDs) == 0 {
        fmt.Println("No matching chapters found")
        return
    }

    fmt.Printf("Located chapter IDs: %v\n", chapterIDs)

    connectionString := "user:pass@tcp(localhost:3306)/library"
    database, err := sql.Open("mysql", connectionString)
    if err != nil {
        log.Fatalf("Database connection failed: %s", err)
    }
    defer database.Close()

    idStrings := make([]string, len(chapterIDs))
    for i, id := range chapterIDs {
        idStrings[i] = strconv.Itoa(id)
    }
    idClause := strings.Join(idStrings, ",")
    
    dbQuery := fmt.Sprintf(
        "SELECT chapter_id, name, writer, description, release_date FROM book_chapters WHERE chapter_id IN (%s)",
        idClause,
    )

    rows, err := database.Query(dbQuery)
    if err != nil {
        log.Fatalf("Query execution error: %s", err)
    }
    defer rows.Close()

    var books []BookInformation
    for rows.Next() {
        var book BookInformation
        if err := rows.Scan(&book.ChapterID, &book.Name, &book.Writer, &book.Description, &book.ReleaseDate); err != nil {
            log.Fatalf("Row scanning error: %s", err)
        }
        books = append(books, book)
    }

    for _, book := range books {
        fmt.Printf("ID: %d, Title: %s, Author: %s, Summary: %s, Date: %s\n",
            book.ChapterID, book.Name, book.Writer, book.Description, book.ReleaseDate)
    }
}

func main() {
    executeSearch()
}

The example demonstrates multiple type assertion pattterns:

  • Extracting map data from interface{} resposnes
  • Convreting float64 to int for ID values
  • Handling slice interfaces from external APIs

Type assertions are performed using the .(desiredType) syntax, which panics if the assertion fails. For production code, consider using the comma-ok variant:

if sourceMap, ok := item.(map[string]interface{}); ok {
    // Safe to use sourceMap
}

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

SBUS Signal Analysis and Communication Implementation Using STM32 with Fus Remote Controller

Overview In a recent project, I utilized the SBUS protocol with the Fus remote controller to control a vehicle's basic operations, including movement, lights, and mode switching. This article is aimed...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.