Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Type Assertion and Struct Handling in Go

Tech May 15 15

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...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

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