【问题标题】:Finding the type of a variable through static analysis?通过静态分析找到变量的类型?
【发布时间】:2022-06-10 20:51:45
【问题描述】:

如何通过静态分析判断变量的类型?

假设我有以下代码:

func doSomething(x interface{}) {}

func main() {
  p := Person()
  doSomething(p)
}

而我要分析doSomething(person),是否可以通过静态分析得到Person的类型?

如果有多个级别的分配怎么办?

p1 := Person()
p2 := p1
doSomething(p2)

parent := Parent()
p := Parent.Child() // type Person
doSomething(p)

用例是我有一个在整个(非常大的)代码库中常用的通用函数,并且想介绍这个函数的新类型安全版本。为此,我希望自动确定函数的“类型”并相应地对其进行重构:

// old
DB.InsertRow(person)

// new
Person.InsertRow(person)

【问题讨论】:

  • 如果 Person() 返回一个具体类型,是的,可以得到 p1p2parentp 的类型(假设 Parent.Child() 也返回具体类型)。但是,如果函数返回一个接口,其动态类型是根据程序在运行时获取的一些参数(例如用户输入、来自数据库或互联网等)决定的,那么静态分析将不足以获取类型.
  • 如果将其作为赏金 - 在此处为您的更大目标添加更多清晰度可能会有所帮助。

标签: go types static-analysis


【解决方案1】:

通过静态分析找到表达式的类型并非易事,有时甚至是不可能的,详情请参阅Golang static identifier resolution

用例是我有一个在整个(非常大的)代码库中常用的通用函数,并且想介绍这个函数的新类型安全版本。为此,我希望自动确定函数的“类型”并相应地对其进行重构:

// old
DB.InsertRow(person)

// new
Person.InsertRow(person)

仅出于重构目的,我认为不值得麻烦去实现它。

您可以做的是暂时更改DB.InsertRow() 的签名以仅接受特定类型,例如int 或您确定不会在任何地方使用的自定义类型(例如type tempFoo struct{})。

为了什么目的?这样做,编译器将为您完成艰苦的工作。您将看到错误消息准确显示您的代码库试图传递给DB.InsertRow() 的类型,所以我会说任务已完成。

例如这段代码编译:

func doSomething(x interface{}) {}

func main() {
    doSomething(image.Pt(1, 2))
    doSomething("abc")
    doSomething(image.Rect) // image.Rect is a function which we don't call,
                            // so we're passing a value of a function type here
}

如果我们改变doSomething():

func doSomething(x int) {}

我们从编译器中得到我们正在寻找的类型:

./prog.go:10:14: 不能在 doSomething 的参数中使用 image.Pt(1, 2)(image.Point 类型的值)作为 int 类型

./prog.go:11:14: 不能在 doSomething 的参数中使用“abc”(无类型 字符串常量)作为 int 值

./prog.go:12:14: 不能使用 image.Rect(func(x0 int, y0 int, x1 int, y1 int) image.Rectangle 类型的值) 作为 int 类型在做某事的论据中

【讨论】:

    【解决方案2】:

    编译器在编译时解析变量和参数的类型 - 所以是的,可以在特定代码行确定类型。您可以使用 go/ast 之类的包遍历 Go 源代码。

    但是,使用运行时反射来检查空白 interface{} 后面的类型可能更容易。 fmt 包可以为你做这种类型的反射:

    fmt.Printf("x's type: %T", x)    // x's type: main.Person
    

    https://go.dev/play/p/ToMz_z6iclb

    【讨论】:

      猜你喜欢
      • 2014-06-26
      • 2011-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多