Last active
December 17, 2020 16:06
-
-
Save mt-inside/5900c96655649e06add9209c7e4521f1 to your computer and use it in GitHub Desktop.
A tour of interfaces and type assertions.
This file contains hidden or 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
type Foo interface { | |
GetA() int | |
} | |
type Bar interface { | |
GetA() int | |
GetB() string | |
} | |
type lol struct { | |
x int | |
} | |
type rofl struct { | |
x int | |
y float64 | |
} | |
func (self lol) GetA() int { | |
return self.x | |
} | |
func (self lol) GetB() string { | |
return strconv.Itoa(self.x) | |
} | |
func main() { | |
f := Foo(lol{5}) | |
b := Bar(lol{5}) | |
fmt.Printf("%d\n", f.GetA()) | |
fmt.Printf("%s\n", b.GetB()) | |
/* Iface -> struct */ | |
// needs type assertion, becuase this Foo might not be wrapping a lol | |
// other structs might satisfy Foo | |
var l lol | |
l = f.(lol) | |
fmt.Printf("%d\n", l.x) | |
/* struct -> iface */ | |
// just works, as the compiler can see there's a GetA() that recieves lo | |
// ifaces aren't really involved here at all, because method implimentat | |
l1 := lol{5} | |
fmt.Printf("%d\n", l1.GetA()) | |
/* iface -> iface */ | |
// this is what you commonly see in the wild | |
// I have a thing typed as one iface, and I want to use it as another if | |
// need a type assertion here, as there could be >1 structs satisfying F | |
// "this type quacks like a Foo, but does is also quack like a Bar?" | |
var b1 Bar | |
b1 = f.(Bar) | |
fmt.Printf("%s\n", b1.GetB()) | |
// don't need a type assertion for this degenerate case, as I guess the | |
// my ifaces are defined explicity, but this is what you'd get with ifac | |
var f1 Foo | |
f1 = b | |
fmt.Printf("%d\n", f1.GetA()) | |
/* struct -> struct */ | |
// var r rofl | |
// r = l.(rofl) - can't do this; "non-interface type on left" | |
/* type assertions */ | |
// both of these match, just change the other to see the other | |
// NB: one is a struct and one is an interface; these branches do pretty different things with the same syntax | |
switch x := f.(type) { | |
case Bar: | |
fmt.Printf("f's wrapped struct also satisfies Bar: %s\n", x.GetB | |
case lol: | |
fmt.Printf("f wraps a lol: %d\n", x.x) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment