title: Table Testing Go Generics
body: <p>I'm excited for Go 1.18 and wanted to test the new generics feature.
  Feels pretty neat to use, but I stumbled over an issue:</p>
  <p>How do you table test generic functions?</p>
  <p>I came up with this <a href="https://gotipplay.golang.org/p/pnqIho7BEe_d" rel="nofollow noreferrer">code</a>, but I need to redeclare my testing logic over each function since I can't instantiate <code>T</code> values.
  (Inside my project I use structs instead of <code>string</code> and <code>int</code>. Just didn't want to include them because it's already enough code)</p>
  <p>How would you approach this problem?</p>
  <p>Edit:
  Here's the code:</p>
  <pre class="lang-golang prettyprint-override"><code>package main
  
  import (
      &quot;testing&quot;
  
      &quot;github.com/stretchr/testify/assert&quot;
  )
  
  type Item interface {
      int | string
  }
  
  type store[T Item] map[int64]T
  
  // add adds an Item to the map if the id of the Item isn't present already
  func (s store[T]) add(key int64, val T) {
      _, exists := s[key]
      if exists {
          return
      }
      s[key] = val
  }
  
  func TestStore(t *testing.T) {
      t.Run(&quot;ints&quot;, testInt)
      t.Run(&quot;strings&quot;, testString)
  }
  
  type testCase[T Item] struct {
      name     string
      start    store[T]
      key      int64
      val      T
      expected store[T]
  }
  
  func testString(t *testing.T) {
      t.Parallel()
      tests := []testCase[string]{
          {
              name:  &quot;empty map&quot;,
              start: store[string]{},
              key:   123,
              val:   &quot;test&quot;,
              expected: store[string]{
                  123: &quot;test&quot;,
              },
          },
          {
              name: &quot;existing key&quot;,
              start: store[string]{
                  123: &quot;test&quot;,
              },
              key: 123,
              val: &quot;newVal&quot;,
              expected: store[string]{
                  123: &quot;test&quot;,
              },
          },
      }
      for _, tc := range tests {
          t.Run(tc.name, runTestCase(tc))
      }
  }
  
  func testInt(t *testing.T) {
      t.Parallel()
      tests := []testCase[int]{
          {
              name:  &quot;empty map&quot;,
              start: store[int]{},
              key:   123,
              val:   456,
              expected: store[int]{
                  123: 456,
              },
          },
          {
              name: &quot;existing key&quot;,
              start: store[int]{
                  123: 456,
              },
              key: 123,
              val: 999,
              expected: store[int]{
                  123: 456,
              },
          },
      }
      for _, tc := range tests {
          t.Run(tc.name, runTestCase(tc))
      }
  }
  
  func runTestCase[T Item](tc testCase[T]) func(t *testing.T) {
      return func(t *testing.T) {
          tc.start.add(tc.key, tc.val)
          assert.Equal(t, tc.start, tc.expected)
      }
  }
  
  </code></pre>