gpt4 book ai didi

parsing - go/types 查找结构是否实现了接口(interface)

转载 作者:IT王子 更新时间:2023-10-29 00:47:25 26 4
gpt4 key购买 nike

好的,所以看看使用 go/types、go/parser...等等来生成一些代码;但是需要识别所有实现我已经弄清楚的特定接口(interface)的结构,但是,如果结构函数上的结构定义与使用 types.Implements 不匹配。

确定代码示例:

获取接口(interface)

package ifacepkg

const interfacePkg = `package ifacepkg

type MyInterface interface {
MyFunction() error
}
`

func getIface() *types.Interface {

fset := token.NewFileSet()

f, err := parser.ParseFile(fset, "iface.go", interfacePkg, 0)
if err != nil {
panic(err)
}

config := &types.Config{
Error: func(e error) {
fmt.Println(e)
},
Importer: importer.Default(),
}

info := types.Info{
Types: make(map[ast.Expr]types.TypeAndValue),
Defs: make(map[*ast.Ident]types.Object),
Uses: make(map[*ast.Ident]types.Object),
}

pkg, e := config.Check("genval", fset, []*ast.File{f}, &info)
if e != nil {
fmt.Println(e)
}

return pkg.Scope().Lookup("MyInterface").Type().Underlying().(*types.Interface)
}

测试文件

package test

import "ifacepkg"

// User struct
type User struct {
FirstName string
LastName string
}

func (u User) MyFunction() error {
return nil
}

var _ ifacepkg.MyInterface = &User{}

正在加载测试文件并尝试查看用户是否实现了 MyInterface

fset := token.NewFileSet()

pkgs, e := parser.ParseDir(fset, "./test", nil, 0)
if e != nil {
log.Fatal(e)
// return
}

var astf []*ast.File

for _, pkg := range pkgs {
fmt.Printf("package %v\n", pkg.Name)
for fn, f := range pkg.Files {
fmt.Printf("file %v\n", fn)
astf = append(astf, f)
}
}

config := &types.Config{
Error: func(e error) {
fmt.Println(e)
},
Importer: importer.Default(),
}

info := types.Info{
Types: make(map[ast.Expr]types.TypeAndValue),
Defs: make(map[*ast.Ident]types.Object),
Uses: make(map[*ast.Ident]types.Object),
}

pkg, e := config.Check(path, fset, astf, &info)
if e != nil {
fmt.Println(e)
}

vIface := getIface()
fmt.Println(vIface)

scope := pkg.Scope()

for _, name := range scope.Names() {

obj := scope.Lookup(name)

_, ok := obj.Type().Underlying().(*types.Struct)
imp := types.Implements(obj.Type(), vIface)

fmt.Println(obj.Name(), ok, imp)
}

好的,所以 fmt.Println(obj.Name(), ok, imp) 打印 User true true 一切都很好!但是,如果我将源文件函数从

func (u User) MyFunction() error {

func (u *User) MyFunction() error {

它现在打印 User true false

所以函数 types.Implements 报告说 User 没有实现 MyInterface,这是不正确的。

所以我的问题是:type.Implements 方法是否存在问题,或者在调用该函数之前我必须对我的对象做些什么。

回答

确定解决我自己的问题,将代码的最后部分更改为

scope := pkg.Scope()

for _, name := range scope.Names() {

obj := scope.Lookup(name)

_, ok := obj.Type().Underlying().(*types.Struct)
ptr := types.NewPointer(obj.Type())
imp := types.Implements(ptr.Underlying(), vIface)

fmt.Println(obj.Name(), ok, imp)
}

它适用于指针和非指针接收器

最佳答案

您的编译器告诉您的是真实的。 *Type != 输入 Go。如果您希望 *User 实现您的接口(interface),那么方法接收器必须是 *User 如果您希望它是 User 那么它需要成为用户。我真的不知道还能怎么解释它……Go 的类型系统是严格的,而且它们是不一样的。如果您为指针类型定义了 (u *User) MyFunction() do ptr := &MyUser 然后检查是否 MyUser,您可以更实际地看到这一点code> 和 ptr 实现接口(interface),ptr 会,MyUser 不会。

关于parsing - go/types 查找结构是否实现了接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34497840/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com