go - go/types.Identical 不能比较其他包中的两个相同类型?
问题描述
我编写了一些代码以通过“go/types”获取特殊类型
import (
"go/ast"
"go/importer"
"go/parser"
"go/token"
"go/types"
"log"
)
const (
Src = `
package types
import (
"io"
"net/http"
)
var (
IOReader io.Reader
Err error
StatusCode int
Request *http.Request
Response *http.Response
)
`
)
const (
TypeIOReader = "IOReader"
TypeErr = "Err"
TypeStatusCode = "StatusCode"
TypeRequest = "Request"
TypeResponse = "Response"
)
func GetType(name string) types.Type {
fset := token.NewFileSet()
file, err := parser.ParseFile(fset, "types.go", Src, 0)
if err != nil {
log.Fatal(err)
}
conf := types.Config{Importer: importer.Default()}
pkg, err := conf.Check("impler/types", fset, []*ast.File{file}, nil)
return pkg.Scope().Lookup(name).Type()
}
该功能GetType(name string) types.Type
可以实现。
当我比较两种类型时,我得到了一些奇怪的结果
log.Println(types.Identical(GetType(TypeResponse), GetType(TypeResponse)))
log.Println(types.Identical(GetType(TypeIOReader), GetType(TypeIOReader)))
log.Println(types.Identical(GetType(TypeStatusCode), GetType(TypeStatusCode)))
log.Println(types.Identical(GetType(TypeErr), GetType(TypeErr)))
结果是
false
false
true
true
似乎types.Identical
无法比较其他包中的两种相同类型?我该如何比较它们?
够types.TypeString(typ1, nil) == types.TypeString(typ2, nil)
健壮吗?
解决方案
问题是您每次都重新解析源,创建一个新实例types.Package
及其关联types.Scope
,这导致命名类型源自不同的声明(链接)。
内置类型,如int
和error
您获得true
的是基本类型,通过比较(链接)区别对待。它们也在“宇宙”范围内声明,我相信,无论您重新解析多少次Src
(链接),它总是相同的。
要解决您的问题,您必须解析一次源代码,然后共享生成的*types.Package
.
package main
import (
"go/ast"
"go/importer"
"go/parser"
"go/token"
"go/types"
"log"
)
const Src = `
package types
import (
"io"
"net/http"
)
var (
IOReader io.Reader
Response *http.Response
)
`
const (
TypeIOReader = "IOReader"
TypeResponse = "Response"
)
func GetType(name string, pkg *types.Package) types.Type {
return pkg.Scope().Lookup(name).Type()
}
func main() {
fset := token.NewFileSet()
file, err := parser.ParseFile(fset, "types.go", Src, 0)
if err != nil {
panic(err)
}
conf := types.Config{Importer: importer.Default()}
pkg, err := conf.Check("impler/types", fset, []*ast.File{file}, nil)
if err != nil {
panic(err)
}
log.Println(types.Identical(GetType(TypeResponse, pkg), GetType(TypeResponse, pkg)))
log.Println(types.Identical(GetType(TypeIOReader, pkg), GetType(TypeIOReader, pkg)))
}
推荐阅读
- simulation - OpenModelica:“警告:达到最大迭代次数但未找到根”,带有条件方程
- list - 对象以“s”结尾时的命名约定列表
- xpath - Xml.etree.ElementTree 在 Xpath 谓词中支持 AND
- java - Xpath selenium Webdriver 实现销售人员自动化
- typescript - 使最后一个参数有条件地可选打字稿
- angular - RxJS 中使用 combineLatest 运算符的客户端过滤不起作用,分配有问题吗?
- django - django runserver,跳过/缓存?多个同时执行的请求
- javascript - 异常可以为空或未定义吗?
- javascript - 使用 Ant Design Components 时升级到 React 版本 16.10.2 错误。函数组件不能给出 refs
- powershell - 服务器扫描返回补丁数据非常旧和旧