Created
July 11, 2023 08:02
-
-
Save rcosnita/02e27db6df90561abcde6c26e4e3b7cf to your computer and use it in GitHub Desktop.
Provide a simple example for using golang generics for simulating strong type API http clients.
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" | |
type Versionable interface { | |
Version() string | |
} | |
type Neg10_0_1 struct { | |
Attr10_1_0 string | |
} | |
func (v Neg10_0_1) Version() string { | |
return "10.0.1" | |
} | |
type Neg10_1_0 struct { | |
} | |
func (v Neg10_1_0) Version() string { | |
return "10.1.0" | |
} | |
type NegOperData11_2_5 struct { | |
Name string | |
} | |
func (v NegOperData11_2_5) Version() string { | |
return "11.2.5" | |
} | |
type NegOperData11_0_1 struct { | |
} | |
func (v NegOperData11_0_1) Version() string { | |
return "11.0_1" | |
} | |
type NegCompatibilityOperData interface { | |
NegOperData11_0_1 | NegOperData11_2_5 | |
} | |
type NegCompatibility interface { | |
Neg10_0_1 | Neg10_1_0 | |
} | |
type NegResult[NegData NegCompatibility, OperData NegCompatibilityOperData] struct { | |
Neg NegData | |
OperationalData OperData | |
} | |
type ResourceFetcher = func(id string) (interface{}, error) | |
type OperationalDataFetcher = func(id string) (interface{}, error) | |
var supportedResourceFetchers map[string]ResourceFetcher | |
var supportedOperationalDataFetchers map[string]OperationalDataFetcher | |
func init() { | |
supportedResourceFetchers = map[string]ResourceFetcher{} | |
supportedOperationalDataFetchers = map[string]OperationalDataFetcher{} | |
supportedResourceFetchers["10.0.1"] = func(id string) (interface{}, error) { | |
fmt.Println("fetching neg with major version 10") | |
return Neg10_0_1{Attr10_1_0: "cool attribute"}, nil | |
} | |
supportedOperationalDataFetchers["11.2.5"] = func(id string) (interface{}, error) { | |
fmt.Println("fetching neg operational data with major version 11") | |
return NegOperData11_2_5{Name: "cool neg operational data"}, nil | |
} | |
} | |
func FetchNeg[NegData NegCompatibility, OperData NegCompatibilityOperData](negId string) (NegResult[NegData, OperData], error) { | |
empty := new(NegData) | |
version := any(empty).(Versionable).Version() | |
resourceFetcher, found := supportedResourceFetchers[version] | |
if !found { | |
return NegResult[NegData, OperData]{}, fmt.Errorf("version %s of neg is not supported", version) | |
} | |
newNeg, err := resourceFetcher(negId) | |
if err != nil { | |
panic(err) | |
} | |
emptyOperData := new(OperData) | |
operDataVersion := any(emptyOperData).(Versionable).Version() | |
operDataFetcher, found := supportedOperationalDataFetchers[operDataVersion] | |
if !found { | |
return NegResult[NegData, OperData]{}, fmt.Errorf("version %s of neg operational data is not supported", operDataVersion) | |
} | |
// TODO(rcosnita) make some computation to determine the correct operdata id if needed. | |
newOperData, err := operDataFetcher(negId) | |
if err != nil { | |
panic(err) | |
} | |
return NegResult[NegData, OperData]{Neg: newNeg.(NegData), OperationalData: newOperData.(OperData)}, nil | |
} | |
func main() { | |
result, err := FetchNeg[Neg10_0_1, NegOperData11_2_5]("1234") | |
if err != nil { | |
panic(err) | |
} | |
fmt.Println(result.Neg.Version(), result.OperationalData.Version()) | |
fmt.Println(result.Neg.Attr10_1_0) | |
fmt.Println(result.OperationalData.Name) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment