Skip to content

Instantly share code, notes, and snippets.

@sedyh
Last active February 9, 2023 16:25
Show Gist options
  • Save sedyh/2e7948ed208308bc796b3f7b19befc7a to your computer and use it in GitHub Desktop.
Save sedyh/2e7948ed208308bc796b3f7b19befc7a to your computer and use it in GitHub Desktop.
Getting around type incovariance in Go, a cool slice trick
package main
import (
"fmt"
"strconv"
)
type Point struct {
Name int
Marked // You don't need to initialize it
}
func (p *Point) String() string {
return strconv.Itoa(p.Name)
}
type Marker interface {
Delete()
Dead() bool
}
type Marked struct {
mark bool
}
func (d *Marked) Delete() {
d.mark = true
}
func (d *Marked) Dead() bool {
return d.mark
}
// Delete removes points from slice
// Previously, you had to duplicate casts up and down for each structure.
func Delete[T Marker](list []T) []T {
temp := list[:0]
for _, item := range list {
if item.Dead() {
temp = append(temp, item)
}
}
return temp
}
func main() {
a, b, c := &Point{Name: 1}, &Point{Name: 2}, &Point{Name: 3}
points := []*Point{a, b, c}
fmt.Println("Before:", points)
b.Delete()
points = Delete(points)
fmt.Println("After:", points)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment