March 15th, 2022... just two weeks ago. The Go team [released Go 1.18](https://go.dev/blog/go1.18) to the world. What seems like a trivial point release actually brings a huge new feature to the Go language: Generics.
In this article, I want to show you how you can use this new feature to build a great developer experience with your abstractions for your Pulumi programs.
<!--more-->
## Using Go 1.18
The first thing you need to do is ensure you have Go 1.18 installed. You can run `go version` to check. If you see anything less than 1.18, you'll need to go upgrade first. The second thing you need to do is update the `go.mod` in your Pulumi program to specify 1.18 as the minimum version.
```go
go 1.18
```
Once you've done these two steps, you're ready to start using generics in your Pulumi programs.
## Using Generics
Let's start by asking a question. What is a good use-case for generics? In my experience, generics work really well for allowing us to provide a common interface to our consumers (developers using our APIs) that allows them to use that same interface to accomplish a collection of similar tasks that require different implementations.
For example, let's assume we want to provide a platform to our developers and allow them to install **ANY** Kubernetes resource. Our goal is to provide an `AddComponent` method that they can call to install either pre-supported components, components created by the platform team, or their own custom components. The glue and important aspect here is that all these components conform to the same interface.
### Defining The Interface
In the simplest form, we just need an `Install` function to call that returns either an error or an array of Pulumi resources.
```go
type Component interface {
Install(ctx *pulumi.Context, name string) ([]pulumi.Resource, error)
}
```
### Creating our Components
Now we need to provide a component that satisfies this interface. So let's assume that we want to install nginx. First, we create a struct that contains fields for any points of configuration. For today's example, we'll just request the version to be installed and a name; the name being used to ensure if the component is installed more than once, it can be uniquely identified.
```go
type Nginx struct {
Version string
}
func (c *Nginx) Install(ctx *pulumi.Context, name string) ([]pulumi.Resource, error) {
return []
}
```
From there, we can begin to flesh out the `Install` implementation for nginx.
This is rather contrived, but hopefully you can see the power of using generics as an interface for platform engineering. Our `AddComponent` implementation for nginx could return a deployment, a service, an ingress with horizontal pod auto-scalers, or any other resource that you want.
## Using the Components
Finally, we create our generic function, `AddComponent`, and start having some fun.
```go
func AddComponent[C Component](ctx *pulumi.Context, name string, component C) ([]pulumi.Resource, error) {