This library are not supposed to be used that way. Importer should be used directly:
package main import ( "fmt" "go/importer" "go/types" ) var imprt = importer.For("source", nil) func main() { p1, err := imprt.Import("awesome/pkg1") if err != nil { panic(err) } p2, err := imprt.Import("awesome/pkg2") if err != nil { panic(err) } iface := p1.Scope().Lookup("Interface").(*types.TypeName).Type().(*types.Named).Underlying().(*types.Interface) impl1 := p1.Scope().Lookup("Implementation1").Type() fmt.Printf("%s\n", impl1.(*types.Named).Method(0).Name()) impl2 := p2.Scope().Lookup("Implementation2").Type() fmt.Println("Implementation1 implements Interface", types.Implements(impl1, iface)) fmt.Println("Implementation2 implements Interface", types.Implements(impl2, iface)) } Введите код... The problem though ASTs are not cached. I copied implementation of importer from go/internal/srcimporter and extended it with caching (I need ASTs besides *type.Package for style checks) суббота, 5 мая 2018 г., 2:04:34 UTC+3 пользователь Denis Cheremisov написал: > > Hi! > > I am writing a special linting-like piece of code and struggle dealing > with the Implements <https://golang.org/pkg/go/types/#Implements> that > doesn't work for my configuration. I made a simplified testing example to > show the issue: > > > - I have package speaker with interface Speaker and its default > implementation. > > package speaker > type Default struct{} > func (Default) Speak(Arg) string { > return "speak" > } > type Arg struct{} > type Speaker interface { > Speak(Arg) string > } > > - > > Now, I have another package, with "Russian speaker": > > > package ru > import "awesome/speaker" > type Russian struct{} > func (Russian) Speak(speaker.Arg) string { > return "говорить" > } > > - > > An finally I have a main package > > > package main > > import ( > "fmt" > "go/ast" > "go/importer" > "go/parser" > "go/token" > "go/types" > "path/filepath" > "runtime" > ) > > func getPath() string { > fpcs := make([]uintptr, 5) > frameIter := runtime.CallersFrames(fpcs[:runtime.Callers(1, fpcs)]) > var frames []runtime.Frame > frame, more := frameIter.Next() > frames = append(frames, frame) > if !more { > panic("stack frames must exists for a call") > } > return filepath.Dir(frame.File) > } > > func getTypes(path ...string) *types.Package { > path = append([]string{getPath()}, path...) > fullpath := filepath.Join(path...) > fset := token.NewFileSet() > pkgs, err := parser.ParseDir(fset, fullpath, nil, parser.ParseComments) > if err != nil { > panic(err) > } > for _, pkg := range pkgs { > config := &types.Config{ > IgnoreFuncBodies: false, > FakeImportC: false, > Error: nil, > Importer: importer.Default(), > Sizes: nil, > DisableUnusedImportCheck: false, > } > info := types.Info{ > Types: map[ast.Expr]types.TypeAndValue{}, > Defs: map[*ast.Ident]types.Object{}, > Uses: map[*ast.Ident]types.Object{}, > } > var files []*ast.File > for _, file := range pkg.Files { > files = append(files, file) > } > typeInfo, err := config.Check(fullpath, fset, files, &info) > if err != nil { > panic(err) > } > return typeInfo > } > return nil > } > > func main() { > mainPkg := getTypes("speaker") > ruPkg := getTypes("ru") > > iface := > mainPkg.Scope().Lookup("Speaker").Type().Underlying().(*types.Interface) > dflt := mainPkg.Scope().Lookup("Default").Type() > russian := ruPkg.Scope().Lookup("Russian").Type() > > fmt.Println(types.Implements(dflt, iface)) > fmt.Println(types.Implements(russian, iface)) > } > > > Output is: > true > false > > The output is true-true without the argument. Is it a feature or a bug? > How can I walk around it? > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.