func printDiff(t1, t2 types.Type, name, pkgName string) {
	switch t1.(type) {
	case *types.Named:
		switch t1.Underlying().(type) {
		case *types.Struct:
			structDiff(t1.Underlying().(*types.Struct), t2.Underlying().(*types.Struct), name, pkgName)
		case *types.Interface:
			interfaceDiff(t1.Underlying().(*types.Interface), t2.Underlying().(*types.Interface), name)
		default:
			log.Println("Unimplemented type", name, t1.Underlying())
		}
	}
}
Specific printning for structs and interfaces
package main
import (
	"fmt"
	"go/types"
	"log"
	"strings"
)
func diff(p1 *types.Package, p2 *types.Package) {
	examinedIdentifiers := make(map[string]bool)  
	removed := []string{}                         
	for _, p1name := range p1.Scope().Names() {
		obj1 := p1.Scope().Lookup(p1name)
		if !obj1.Exported() {  
			continue
		}
		examinedIdentifiers[p1name] = true
		obj2 := p2.Scope().Lookup(p1name)
		if obj2 == nil {
			removed = append(removed, p1name)
			continue
		}
		t1, t2 := obj1.Type().Underlying(), obj2.Type().Underlying()  
		t1StringRepr := strings.TrimPrefix(t1.String(), p1.Name()+".")
		t2StringRepr := strings.TrimPrefix(t2.String(), p2.Name()+".")
		generalPrinting := func() {
			log.Print(prettyPrint(obj2, "+", ""))
			log.Print(prettyPrint(obj1, "-", ""))
		}
		switch obj1.(type) {
		case *types.Var, *types.Const, *types.Func:
			if t1StringRepr != t2StringRepr {
				generalPrinting()
			}
		case *types.TypeName:
			_, t2Type := obj2.(*types.TypeName)
			if !t2Type {
				generalPrinting()
			}
			switch t1.(type) {
			case *types.Struct:
				_, isT2Struct := t2.(*types.Struct)
				if isT2Struct {
					structDiff(t1.(*types.Struct), t2.(*types.Struct), obj1.Name(), obj1.Pkg().Name())
				} else {
					generalPrinting()
				}
				printMethods(obj1.Type().(*types.Named), obj2.Type().(*types.Named), obj1.Name())
			case *types.Interface:
				_, isT2Interface := t2.(*types.Interface)
				if isT2Interface {
					interfaceDiff(t1.(*types.Interface), t2.(*types.Interface), obj1.Name())
				} else {
					generalPrinting()
				}
			default:
				if t1StringRepr != t2StringRepr {
					generalPrinting()
				}
			}
		default:
			log.Println("Not sure of ", obj1, "and", obj2)
		}
	}
	for _, name := range removed {
		log.Print(prettyPrint(p1.Scope().Lookup(name), "-", ""))
	}
	for _, name := range p2.Scope().Names() {
		o2 := p2.Scope().Lookup(name)
		if !o2.Exported() {
			continue
		}
		if _, ok := examinedIdentifiers[name]; ok {
			continue
		}
		log.Print(prettyPrint(p2.Scope().Lookup(name), "+", ""))
	}
}