程序如何在静态类型语言中在运行时知道原始类型的类型?

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

How do programs know the types at runtimes of primitives statically typed languages

问题

Go和Scala都提供了在运行时检查类型的方法:

Scala:

class A
class B extends A

val a: A = new A // 静态类型: A 动态类型: A
val ab: A = new B // 静态类型: A 动态类型: B
val b: B = new B // 静态类型: B 动态类型: B

def thing(x: Any): String = x match {
    case t: Int => "Int"
    case t: A => "A"
    case t: B => "B"
    case t: String => "String"
    case _ => "unknown type"
}

Go:

package main

import (
    "fmt"
    "reflect"
)

type A struct {
    field1 int
    field2 string
}

func printTypeOf(t interface{}) {
    fmt.Println(reflect.TypeOf(t))
}

func main() {
    i := 234234 // int
    s := "hello world" // string
    p := &A{3234234, "stuff"} // *A

    fmt.Print("The type of i is: ")
    printTypeOf(i)
    fmt.Print("The type of s is: ")
    printTypeOf(s)
    fmt.Print("The type of p is: ") // pass a pointer
    printTypeOf(p)
    fmt.Print("The type of the reference of p is: ") // pass a value
    printTypeOf(*p)
}

这些代码是如何在内部工作的?我猜对于结构体和类,对象的类型存储在一个隐藏字段中(所以在golang中的结构实际上是struct { field1 int field2 string type type })。但是,函数如何得到11010110并知道它是指向内存地址214的指针、整数214还是字符Ö?所有的值是否都以表示其类型的字节进行传递?

英文:

Both Go and Scala provide ways of checking types at runtime:

Scala:

class A
class B extends A

val a: A = new A // static type: A dynamic type: A
val ab: A = new B // static type: A dynamic type: B
val b: B = new B // static type: B dynamic type: B

def thing(x: Any): String = x match {
	case t: Int => "Int"
	case t: A => "A"
	case t: B => "B"
	case t: String => "String"
	case _ => "unknown type"
}

Go:

package main

import (
	"fmt"
	"reflect"
)

struct A {
	field1 int
	field2 string
}

func printTypeOf(t interface{}) {
	fmt.Println(reflect.TypeOf(t))
}

func main() {
	i := 234234 // int
	s := "hello world" // string
	p := &A{3234234, "stuff"} // *A

	fmt.Print("The type of i is: ")
	printTypeOf(i)
	fmt.Print("The type of s is: ")
	printTypeOf(s)
	fmt.Print("The type of p is: ") // pass a pointer
	printTypeOf(p)
	fmt.Print("The type of the reference of p is: ") // pass a value
	printTypeOf(*p)
}

How exactly does this work internally? I presume for structs and classes, the type of the object is stored in a hidden field (so the structure in golang is really struct { field1 int field2 string type type }. But how on earth can function be given 11010110 and know whether it's a pointer to memory address at 214, the integer 214 or the character Ö? Are all values secretly passed with a byte which represents its type?

答案1

得分: 2

在Scala中,每个对象都有一个指向其类的指针。当你使用原始参数(IntChar等)调用thing时,它会自动装箱为一个对象(java.lang.Integerjava.lang.Character等)。你代码中对Int的匹配实际上被转换为对Integer的匹配。

在Go中,类型不存储在结构体中,而是存储在接口值中:

接口值表示为一个两个字的对,其中一个指向存储在接口中的类型信息的指针,另一个指向关联数据的指针。将b分配给类型为Stringer的接口值会设置接口值的两个字。

因此,当你调用printTypeOf(whatever)时,whatever会被转换为interface{},并且它的类型会与whatever本身一起存储在这个新值中。

英文:

In Scala, each object has a pointer to its class. When you call thing with a primitive argument (Int, Char, etc.), it's automatically boxed to an object (java.lang.Integer, java.lang.Character, etc.). The match against Int in your code is actually translated to a match against Integer.

In Go, the type isn't stored in structs, but in interface values:

> Interface values are represented as a two-word pair giving a pointer to information about the type stored in the interface and a pointer to the associated data. Assigning b to an interface value of type Stringer sets both words of the interface value.

So when you call printTypeOf(whatever), whatever is converted to interface {} and its type is stored in this new value along with whatever itself.

huangapple
  • 本文由 发表于 2016年3月30日 21:57:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/36311041.html
匿名

发表评论

匿名网友

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

确定