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.

Reply via email to