返回信息流就是普通的struct对象,看这个对象的内存布局并没有java那种对象头指向类型的设计,那他实现的机制是什么,recevier指针有什么玄机么?
猜测是:编译器自动给对象加了个vptr指向类型,这个指针只能被runtime看到,不知道怎么才能验证下
------------------------更新下
GO是静态类型 <=> 编译时确定所有变量的类型 <=> 只能有interface转换(reflect.TypeOf(var))才能找到类型信息
如果编译器在编译时就知道了每个变量的类型,为何还用反射获取变量类型?反射如何实现,
类型变量转换到interface时是在运行时发生的么?编译器how保留了变量的what信息才能保证转换成interface?
还有多态机制,go是如何实现?如何更好的理解下类型系统,静态和动态的差异等等,真的要去学编译原理么[em9][em9]
------------------------分割线
静态类型系统 编译器编译知道所有变量的类型,这里“知道”的意思是维护一种变量<=>映射,还是说通过约束将这个变量上进行的操作固定下来,从而暗含 做哪些事情的变量就是某某类型的 意思?
这是一条镜像帖。来源:北邮人论坛 / golang / #995同步于 2018/3/27
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Golang机器人发帖
golang没有对象头,如何找到类型metadata(非interface转换)
henceman
2018/3/27镜像同步6 回复
订阅后,新回复会通过你的通知中心匿名送达。
6 条回复
【 在 henceman 的大作中提到: 】
: 就是普通的struct对象,看这个对象的内存布局并没有java那种对象头指向类型的设计,那他实现的机制是什么,recevier指针有什么玄机么?
: 猜测是:编译器自动给对象加了个vptr指向类型,这个指针只能被runtime看到,不知道怎么才能验证下
package main
import (
"fmt"
"reflect"
)
type A struct{
id int64
}
func main() {
a := A{
id: 1,
}
fmt.Println(reflect.TypeOf(a))
}
汇编代码如下
那个runtime.convT2E是如何实现的啊,传入一个变量a,变量a是引用还是指针呢?假如是引用的话,但是convT2E如何知道a的类型的?
【 在 henceman 的大作中提到: 】
: 就是普通的struct对象,看这个对象的内存布局并没有java那种对象头指向类型的设计,那他实现的机制是什么,recevier指针有什么玄机么?
: 猜测是:编译器自动给对象加了个vptr指向类型,这个指针只能被runtime看到,不知道怎么才能验证下
继续看,发现自己想问的问题是静态类型绑定是如何实现的,也就是编译期做了哪些东西?
自己编译原理方面的知识很匮乏,想找个思路也没有体系指导,也只能乱打乱撞,现在查到并总结到的是,静态类型在编译期时通过程序分析or类型推导,将每个变量的类型确定,但这里的类型确定含义并不是通过我臆想中的有一个符号表类似的东西映射变量名和类型,而是通过语法分析约束确定每个变量在最终汇编代码中的位置。
【 在 henceman 的大作中提到: 】
: 继续看,发现自己想问的问题是静态类型绑定是如何实现的,也就是编译期做了哪些东西?
: 自己编译原理方面的知识很匮乏,想找个思路也没有体系指导,也只能乱打乱撞,现在查到并总结到的是,静态类型在编译期时通过程序分析or类型推导,将每个变量的类型确定,但这里的类型确定含义并不是通过我臆想中的有一个符号表类似的东西映射变量名和类型,而是通过语法分析约束确定每个对象变量在最终汇编代码中的位置。
:
没人鸟我。。继续自high
一旦实现对象变量对类型的显示绑定,比如指针,那么这个变量当然可以动态的改变指向的类型,所以叫动态绑定,那为什么需要改变对象变量的指向呢?一个原因是动态多态(相对于静态多态),为啥会出现动态多态,因为oop的继承思想,不需要继承的oop无非就是少点复用,冗余了些,这也或许是高司令说再来一次的话会放弃面向对象而实现基于对象java,继承真的那么重要?
结论:所谓静态类型绑定和动态类型绑定都是满足语言设计者一些私欲的手段,有和没有或者两者共存都可以,功能还是那些功能,至于实现就是要了解设计者到底想要什么?那他们想要什么呢?(一种猜测,语言设计者认为程序员是什么样的)
更正下:
golang是静态类型,编译器能推断出所有变量的类型,对象不需要知道类型信息,需要类型信息的地方golang的设计就是用接口来实现,接口里有指向对象类型的信息(type rtype struct)和对象内存指针,只不过有些地方显示的进行类型和interface的转换,有些地方是隐式进行的。golang没有所谓的“动态”
对于OO的继承,多态,golang做了一些取舍,有些也把golang称为"伪多态",比如父类指针指向子类对象,golang编译是报错的,但可以通过interface{}啰嗦一点实现同样的逻辑,再比如泛型,同样是通过接口实现"伪泛型“。
golang这样设计也确保了类型安全(unsafe.pointer例外)吧,代价也是舍弃了一些灵活(话说真的是每个程序员都想掌控一切么)
只是根据之前的困惑,片面的理解,望大家指点
看山是山,看山不是山,看山又是山
你的4楼讲的没错 Go是静态类型编译语言 不同类型不能互相赋值(long和int间也不能) 类也一样 这决定了go不能像java那样通过动态绑定用子类去覆盖父类实现多态 go的接口采用非侵入式 不用java里的类必须要显示声明实现了某一接口 而go不用 只要实现了接口的所有方法就行 然后就可以将该类型的变量赋值给该接口的变量 比如下面的例子 Dog和Cat都实现了MakeNoise()方法 而animalSounder接口只实现了MakeNoise()方法 在go里Dog和Cat就可以被认为是实现了animalSounder接口 然后就可以把引用或指针赋值给这个接口 编译器则根据类型的不同调用相应的方法实现多态
type Animal struct {
Name string
mean bool
}
type AnimalSounder interface {
MakeNoise()
}
type Dog struct {
Animal
BarkStrength int
}
type Cat struct {
Basics Animal
MeowStrength int
}
func main() {
myDog := &Dog{
Animal{
"Rover", // Name
false, // mean
},
2, // BarkStrength
}
myCat := &Cat{
Basics: Animal{
Name: "Julius",
mean: true,
},
MeowStrength: 3,
}
MakeSomeNoise(myDog)
MakeSomeNoise(myCat)
}
func (animal *Animal) PerformNoise(strength int, sound string) {
if animal.mean == true {
strength = strength * 5
}
for voice := 0; voice < strength; voice++ {
fmt.Printf("%s ", sound)
}
fmt.Println("")
}
func (dog *Dog) MakeNoise() {
dog.PerformNoise(dog.BarkStrength, "BARK")
}
func (cat *Cat) MakeNoise() {
cat.Basics.PerformNoise(cat.MeowStrength, "MEOW")
}
func MakeSomeNoise(animalSounder AnimalSounder) {
animalSounder.MakeNoise()
}
go的interface有一个itab的结构记录一些信息,然后我记得interface{}可以类比于Java的Object,可以认为所有的struct都是个interface{}吧,所以应该都在这里面有存?