Weak Pointers with Embedded Interface Types - Type Casting Workaround

I’m using Go 1.22+ weak pointers to implement a read-only iterator that holds a weak reference to a file system. The issue is that my file system is stored as an interface field, and that interface embeds another interface.

The Problem:

I have:

type FileStorageGargoyle struct {
    mu sync.RWMutex
    fs gargoyle.FileSystem  // interface type
}

type FileStorageGargoyleReadFileIterator struct {
    fs weak.Pointer[gargoyle.Snapshot]  // want weak ptr to embedded interface
}

func (s *FileStorageGargoyle) ReadFile(fileId string (io.ReadSeekCloser, error) {
    s.mu.RLock()
    defer s.mu.RUnlock()
    
    // This doesn't work - type mismatch:
    // fs: weak.Make(&s.fs),  // s.fs is FileSystem, not Snapshot
}

Where gargoyle.FileSystem embeds gargoyle.Snapshot:

type FileSystem interface {
    Snapshot  // embedded
    CreateFile(id string) error
    // ... other methods
}

What I Tried:

  1. Direct assignment: weak.Make(&s.fs) — compilation error, type mismatch

  2. Type assertion: weak.Make(&(s.fs.(gargoyle.Snapshot))) — creates a local variable, weak pointer becomes dangling

  3. Variable copy:

var fs gargoyle.Snapshot = s.fs
weak.Make(&fs)  // Also dangling - fs is on the stack

The Workaround (Works, but feels awkward):

import "unsafe"

fs: weak.Make((*gargoyle.Snapshot)(unsafe.Pointer(&s.fs))),

This works because FileSystem embeds Snapshot, so the memory layout is compatible. The unsafe.Pointer cast lets me point directly to the s.fs field in the struct, which persists for the object’s lifetime.

My Questions:

  1. Is this the intended way to handle weak pointers to embedded interface fields?
  2. Are there safer alternatives that don’t involve unsafe?
  3. Should the weak package documentation cover this use case?
  4. Is there a Go idiom I’m missing here?
  5. I’d appreciate any feedback or suggestions!

An embedded struct field is just like a normal struct field with some added syntax sugar. gargoyle.FileSystem has a field named “Snapshot” which is of type gargoyle.Snapshot. If you want a reference to this field, you should make a weak pointer to that field: weak.Make(&s.fs.Snapshot)