Generics - is there an equivalent to Rust "Self" type

Rust generic has a “Self” which is the Concrete type of the instantiated Generic type. Is there an equivalent in Go?

Specifically, so i can get Clone() to return a Self. Then i can have generic struct which will implement the Clone interface.

Something like,

type Cloner[T any] interface {
    Clone() T
}

type Parent[T any] struct {
    parentAttr T
    Cloner[Self] 
}

func (p Parent[T]) Clone() Parent[T] {  return a clone of the parent obj }

type Child[T any] struct {
   Parent[T]
   childAttr string
}

func (c Child[T]) Clone() Child[T] { return a clone of the child obj }

Hi @globalflea,

It is indeed possible that an interface method’s argument refers to the interface type - see this article for details:

How to use generics for creating self-referring interfaces

TL;DR:

Step 1. The Cloner interface stays unchanged.

type Cloner[C any] interface {
	Clone() C
}

C is not restricted to anything yet, but step 2 takes care of this.

Step 2. A function that clones any type uses Cloner[T] as type restriction:

func CloneAny[T Cloner[T]](c T) T {
	return c.Clone()
}

Then, for any variable s whose type implements Cloner, you can simply call

CloneAny(s)

to clone s.

Playground link

The blog article explains this solution in more detail.

1 Like

Thanks.

Hi Christoph,

thank you for your blog post.

You use this snippet in the post:

cloned := CloneAny(s)
if cs, ok := cloned.(CloneableSlice); ok {
    fmt.Println(cs[3])
}

Why not use cloned := s.Clone() and make every Clone-method return the particular type?

Then you don’t need a type assertion.

Hi @guettli,

Because then the Clone methods would not implement the Cloner interface.

Your solution is of course perfectly fine if a Cloner interface is not required. Always use the simplest solution possible!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.