Skip to content

Instantly share code, notes, and snippets.

@christophberger
Last active April 25, 2016 08:37
Show Gist options
  • Save christophberger/9a547aa820e766f33830d43c633d9b9c to your computer and use it in GitHub Desktop.
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
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
@christophberger
Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment