package main

import (
	"fmt"
	"reflect"
)

type Pengguna struct {
	ID    int64  `db:"id"`
	Nama  string `db:"nama"`
	Email string `db:"email"`
}

// mapBaris menyalin nilai satu baris hasil query ke field struct
// berdasarkan struct tag db:"..." — versi sederhana dari
// mekanisme mapping sqlx Get dan Select.
func mapBaris(baris map[string]any, dst any) error {
	v := reflect.ValueOf(dst).Elem()
	t := v.Type()
	for i := range t.NumField() {
		tag := t.Field(i).Tag.Get("db")
		nilai, ada := baris[tag]
		if !ada {
			continue
		}
		switch v.Field(i).Kind() {
		case reflect.Int64:
			n, ok := nilai.(int64)
			if !ok {
				return fmt.Errorf("kolom %s bukan int64", tag)
			}
			v.Field(i).SetInt(n)
		case reflect.String:
			s, ok := nilai.(string)
			if !ok {
				return fmt.Errorf("kolom %s bukan string", tag)
			}
			v.Field(i).SetString(s)
		}
	}
	return nil
}

func main() {
	barisan := []map[string]any{
		{"id": int64(1), "nama": "Budi", "email": "budi@example.com"},
		{"id": int64(2), "nama": "Siti", "email": "siti@example.com"},
	}
	for _, baris := range barisan {
		var p Pengguna
		if err := mapBaris(baris, &p); err != nil {
			fmt.Println("gagal memetakan:", err)
			return
		}
		fmt.Printf("%d %s <%s>\n", p.ID, p.Nama, p.Email)
	}
}
