Skip to content

Instantly share code, notes, and snippets.

@yusufsyaifudin
Created March 23, 2021 11:22
Show Gist options
  • Save yusufsyaifudin/22157b16b98b8d744d4d9cf229f239ca to your computer and use it in GitHub Desktop.
Save yusufsyaifudin/22157b16b98b8d744d4d9cf229f239ca to your computer and use it in GitHub Desktop.
Implement As method to convert interface type to the right data structure as it is first write. That means, if it use struct A, it only valid to output target as A. If we re-declare struct A, it will not match since it is not the real A in the first declaration.
package main_test
import (
"fmt"
"reflect"
"testing"
)
type AnimalName string
const (
C AnimalName = "crocodile"
L AnimalName = "lion"
)
type Crocodile struct {
CanineTooth bool
}
type Lion struct {
CanineTooth bool
}
type Animal struct {
Type AnimalName
Feature interface{}
}
// As return Feature data as type variable.
// Before convert to the out variable, it validate whether current value in Feature
// is match with the AnimalName data structure.
func (a *Animal) As(out interface{}) error {
outVal := reflect.ValueOf(out)
outType := outVal.Type()
if outType.Kind() != reflect.Ptr || outVal.IsNil() {
return fmt.Errorf("not type of pointer")
}
trueDataStructureVal := reflect.ValueOf(a.Feature)
targetType := outType.Elem()
if !reflect.TypeOf(a.Feature).AssignableTo(targetType) {
return fmt.Errorf("target has type %s but the true structure is %s",
targetType.String(), trueDataStructureVal.Type().String(),
)
}
// set if assignable
outVal.Elem().Set(trueDataStructureVal)
return nil
}
func TestTypeConversion(t *testing.T) {
animal := Animal{
Type: L,
Feature: Lion{CanineTooth: true},
}
var lion Lion
err := animal.As(&lion)
if err != nil {
t.Fatalf(err.Error())
return
}
var crocodile Crocodile
err = animal.As(&crocodile)
if err == nil {
t.Fatalf("should error because is not type of %T", crocodile)
return
}
type Lion struct {
CanineTooth bool
}
var likeLion Lion
err = animal.As(&likeLion)
if err == nil {
t.Fatalf("should error because is not type of %T", likeLion)
return
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment