// Playground for https://stackoverflow.com/a/56699658/11458991

package main

import (
	"fmt"
	"errors"
	"log"
	"reflect"
	"strings"
)

// RowID stores the ID of a single row in a table. An ID can be a composite of multiple columns
type RowID []string

// String implements Stringer interface for RowID
func (r RowID) String() string {
	return fmt.Sprintf("[%s]", strings.Join(r, ", "))
}

func castToStringerSlice(iface interface{}) ([]fmt.Stringer, bool /* ok */) {
	if reflect.TypeOf(iface).Kind() != reflect.Slice {
		return nil, false
	}
	
    v := reflect.ValueOf(iface)
	stringers := make([]fmt.Stringer, v.Len())

    for i := 0; i < v.Len(); i++ {
        stringers[i] = v.Index(i)
    }
    
    return stringers, true
}

func PrintChanges(iface_ids interface{}) {
	ids, ok := castToStringerSlice(iface_ids)
	if !ok {
		log.Fatal(errors.New("the argument to PrintChanges must be a slice of Stringers"))
	}
	for _, id := range ids {
		fmt.Println(id)
	}
}

func PrintChange(id fmt.Stringer) {
	fmt.Println(id)
}

func main() {
	rowIDs := []RowID{
		{"1", "2"},
		{"22"},
	}

	PrintChange(rowIDs[0])
	
	PrintChanges(rowIDs)
}