Last active
April 25, 2016 08:37
-
-
Save christophberger/9a547aa820e766f33830d43c633d9b9c to your computer and use it in GitHub Desktop.
Approach to accessing struct-specific attributes through an interface using typecast in Go
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 | |
import "fmt" | |
// The interface. | |
type interf interface { | |
Method(string) string | |
} | |
// A struct. | |
type struct1 struct { | |
attr1 string | |
} | |
// struct1 implements the interf interface. | |
func (s struct1) Method(i string) string { | |
return i + s.attr1 | |
} | |
// Another struct. | |
type struct2 struct { | |
attr2 string | |
} | |
// struct2 also implements the interf interface. | |
func (s struct2) Method(i string) string { | |
return i + s.attr2 | |
} | |
// Invoke the method of the interface. | |
// m can be a struct1 or a struct2, since both implement method "Method". | |
func processInterf(m interf) string { | |
return m.Method("Interface 'm' says: ") | |
} | |
// Access a struct specific attr via typecast. | |
func processStruct1(m interf) string { | |
s1, ok := m.(struct1) | |
if ! ok { | |
panic("s1 is not of type struct1") | |
} | |
return "Typecast to s1: " + s1.attr1 | |
} | |
// Access a struct specific attr via typecast. | |
func processStruct2(m interf) string { | |
s2, ok := m.(struct2) | |
if ! ok { | |
panic("s1 is not of type struct2") | |
} | |
return "Typecast to s2: " + s2.attr2 | |
} | |
// Use a name to map a call to different struct-specific functions. | |
func processStruct(m interf, name string) string { | |
switch name { | |
case "1": | |
return processStruct1(m) | |
case "2": | |
return processStruct2(m) | |
default: | |
panic("Invalid name: " + name) | |
} | |
} | |
func main() { | |
s1 := struct1{attr1: "I am attr1 of struct1"} | |
s2 := struct2{attr2: "I am attr2 of struct2"} | |
// Pass the structs in place of the inteface parameter. | |
// processinterf can handle both structs since both structs satisfy the interface. | |
fmt.Println(processInterf(s1)) | |
fmt.Println(processInterf(s2)) | |
// processStruct dispatches the call depending on the name. | |
fmt.Println(processStruct(s1, "1")) | |
fmt.Println(processStruct(s2, "2")) | |
fmt.Println("Done.") | |
} | |
// Also published as playground snippet: https://play.golang.org/p/A4A_QmeKRS |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I used this code in a discussion on stackoverflow about how to access struct attributes that are not accessible through the methods that are exposed in the common interface. The OP used a name-to-func mapping scheme for one of the structs (similar to the one in processStruct(), but m was not an interface but the struct itself), and I suggested to extend this mapping to the other structs via typecast.
The preferred method of course would be to use the interface rather than a typecast whenever possible.