Issue
type SipField interface {
Info() (id, name, defaultValue string, length int)
}
type Field string
func (f *Field) Get() string {
return string(*f)
}
func (f *Field) Set(s string) {
*f = Field(s)
}
type CommandID Field
func (cid *CommandID) Info() (id, name, defaultValue string, length int) {
return "", "command ID", "", 2
}
type Language Field
func (l *Language) Info() (id, name, defaultValue string, length int)
{
return "", "language", "019", 3
}
func InitField(f interface{}, val string) error {
sipField, ok := f.(SipField)
if !ok {
return errors.New("InitField: require a SipField")
}
_, _, defaultValue, length := sipField.Info()
field, ok := f.(*Field)
if !ok {
return errors.New("InitField: require a *Field")
}
return nil
}
How should I do for converting interface{}
to Field(CommandID, Language...)
in InitField()
function? I try to directly type assert by
field, ok := f.(*Field)
but it not working.I have tried to use unsafe.Pointer but failed also.
Solution
Have a look at Type assertions chapter in Go reference. It states:
x.(T)
More precisely, if T is not an interface type, x.(T) asserts that the dynamic type of x is identical to the type T.
Types CommandID and Field are not identical as described in Type identity.
A defined type is always different from any other type.
Both types CommandId and Fields are defined as described in Type definitions.
A type definition creates a new, distinct type with the same underlying type and operations as the given type, and binds an identifier to it.
TypeDef = identifier Type .
You can only do
field, ok := f.(*CommandID)
or
field, ok := f.(*Language)
As @mkopriva mentioned in the comment, you can do type conversion later to *Field
but this it does not seem to be your goal.
Other solution is to introduce a Field interface with Set and Get methods. Then you will need to provide an implementation for every implementing type.
Answered By – Grzegorz Żur
Answer Checked By – Senaida (GoLangFix Volunteer)