为什么这里是`*invalid type`而不是`*Games`?

huangapple go评论113阅读模式
英文:

Why is this `*invalid type` instead of `*Games`?

问题

如果你在这里运行分析包:https://github.com/frederikhors/iss-goland-invalid-type,使用以下命令:

go run ./analysis

它会打印出:

field.Name: id - field.Type: string
field.Name: name - field.Type: string        
field.Name: games - field.Type: *invalid type

我不明白的是为什么我得到的是 *invalid type 而不是 *Games

代码部分:

  • analyis/main.go:
package main

import (
	"go/types";

	"golang.org/x/tools/go/packages"
)

func main() {
	playerModel := LoadPackage("./player.go")

	var playerStruct *types.Struct

	for _, entity := range playerModel.Types.Scope().Names() {
		if entity == "Player" {

			playerStruct = GetStruct(entity, playerModel)

			break
		}
	}

	for i := 0; i < playerStruct.NumFields(); i++ {
		field := playerStruct.Field(i)

		println("field.Name: " + field.Name() + " - field.Type: " + field.Type().String())
	}
}

func LoadPackage(path string) *packages.Package {
	const mode = packages.NeedTypes |
		packages.NeedName |
		packages.NeedSyntax |
		packages.NeedFiles |
		packages.NeedTypesInfo |
		packages.NeedTypesInfo |
		packages.NeedModule

	cfg := &packages.Config{Mode: mode}

	pkgs, err := packages.Load(cfg, path)
	if err != nil {
		panic(err)
	}

	return pkgs[0]
}

func GetStruct(structName string, pkg *packages.Package) *types.Struct {
	foundStruct := pkg.Types.Scope().Lookup(structName)

	if foundStruct == nil {
		return nil
	}

	res, _ := foundStruct.Type().Underlying().(*types.Struct)

	return res
}
  • player.go:
type Player struct {
	id    string
	name  string
	games *Games
}
  • games.go:
package main

type Games struct {
	wins   []string
	losses []string
}
英文:

If you run the analysis package here: https://github.com/frederikhors/iss-goland-invalid-type with:

go run ./analysis

it will print:

field.Name: id - field.Type: string
field.Name: name - field.Type: string        
field.Name: games - field.Type: *invalid type

What I don't understand is why I'm having *invalid type instead of *Games?

Code

  • analyis/main.go:
package main

import (
	&quot;go/types&quot;

	&quot;golang.org/x/tools/go/packages&quot;
)

func main() {
	playerModel := LoadPackage(&quot;./player.go&quot;)

	var playerStruct *types.Struct

	for _, entity := range playerModel.Types.Scope().Names() {
		if entity == &quot;Player&quot; {

			playerStruct = GetStruct(entity, playerModel)

			break
		}
	}

	for i := 0; i &lt; playerStruct.NumFields(); i++ {
		field := playerStruct.Field(i)

		println(&quot;field.Name: &quot; + field.Name() + &quot; - field.Type: &quot; + field.Type().String())
	}
}

func LoadPackage(path string) *packages.Package {
	const mode = packages.NeedTypes |
		packages.NeedName |
		packages.NeedSyntax |
		packages.NeedFiles |
		packages.NeedTypesInfo |
		packages.NeedTypesInfo |
		packages.NeedModule

	cfg := &amp;packages.Config{Mode: mode}

	pkgs, err := packages.Load(cfg, path)
	if err != nil {
		panic(err)
	}

	return pkgs[0]
}

func GetStruct(structName string, pkg *packages.Package) *types.Struct {
	foundStruct := pkg.Types.Scope().Lookup(structName)

	if foundStruct == nil {
		return nil
	}

	res, _ := foundStruct.Type().Underlying().(*types.Struct)

	return res
}
  • player.go:
type Player struct {
	id    string
	name  string
	games *Games
}
  • games.go:
package main

type Games struct {
	wins   []string
	losses []string
}

答案1

得分: 3

你明确地只加载了一个文件,使用LoadPackage("./player.go")。而这个文件并不是声明Games类型的文件。要加载整个包中所有类型的信息,你需要加载整个包。

你需要使用LoadPackage(".")

英文:

You are explicitly loading only a single file with LoadPackage(&quot;./player.go&quot;). And that file is not the one in which the Games type is declared. To load information on all types of a package you need to load the whole package.

You need to use LoadPackage(&quot;.&quot;).

huangapple
  • 本文由 发表于 2022年1月29日 20:50:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/70905567.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定