Created
March 23, 2021 11:22
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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