不安全指针,空接口词

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

Unsafe pointers, emptyInterface word

问题

我正在尝试理解Go语言中的unsafe.Pointers内部机制。在结构体中只有一个字段并且返回指向Foo的指针时,是否有办法始终返回指向Foo而不是Bar的指针?只有当*FooFoo具有多个字段时才起作用。这是编译器优化,还是与堆/栈分配有关?

type Bar struct {
	ID    int
	Name  string
	Price float64
}
type Foo struct {
	Bar *Bar
}

aFoo := Foo{
	Bar: &Bar{},
}

// xunsafe.AsPointer 实现:
//
// func AsPointer(v interface{}) unsafe.Pointer {
//	empty := (*emptyInterface)(unsafe.Pointer(&v))
//	return empty.word
//}

fmt.Printf("Foo ptr: %v, Bar ptr: %v\n", AsPointer(aFoo), unsafe.Pointer(aFoo.Bar))
// 输出: Foo ptr: 0xc00010a060, Bar ptr: 0xc00010a060

编辑:我正在使用go1.17版本。

英文:

I am trying to understand Go unsafe.Pointers internal. In case when there is only one field in the struct and returns me a pointer to the Foo, returns a pointer to the Bar.

Is there a way to actually return allways pointer to the Foo not Bar? It works only when *Foo or Foo has more than one field. Is it compiler optimization, or is it related with Heap/Stack allocation?

type Bar struct {
	ID    int
	Name  string
	Price float64
}
type Foo struct {
	Bar *Bar
}

aFoo := Foo{
	Bar: &Bar{},
}

//xunsafe.AsPointer implementation:
//
// func AsPointer(v interface{}) unsafe.Pointer {
//	empty := (*emptyInterface)(unsafe.Pointer(&v))
//	return empty.word
//}

fmt.Printf("Foo ptr: %v, Bar ptr: %v\n", AsPointer(aFoo), unsafe.Pointer(aFoo.Bar))
//Output: Foo ptr: 0xc00010a060, Bar ptr: 0xc00010a060

Edit: I am using the go1.17.

答案1

得分: 2

使用&aFoo来获取指向Foo的指针。

类型unsafe.Pointer是编译器理解的一种特殊类型。编译器允许在unsafe.Pointer和其他类型之间进行转换,而这些转换在语言规范中通常是不允许的。

关于xunsafe.Pointer:你会看到不同的结果,因为这两种类型在存储在接口值中时具有不同的表示形式。

type Foo struct {
    Bar *Bar
}

type Foo struct {
    Bar *Bar
    ASecondField int
}

这是因为这些类型在存储在接口值中时具有不同的表示形式。大于一个字的值被复制到接口值私有的内存中,并且接口值存储指向该内存的指针。xunsafe.AsPointer函数确实有处理这两种表示形式的代码。

英文:

Use &aFoo to get a pointer to the Foo.

The type unsafe.Pointer is a special type understood by the compiler. The compiler allows conversions between unsafe.Pointer and other types that are not normally allowed by the language specification.

Regarding xunsafe.Pointer: You see different results for

type Foo struct {
    Bar *Bar
}

and

type Foo struct {
    Bar *Bar
    ASecondField int
}

because those types have different representations when stored in an interface value. Values larger than a word are copied to memory private to the interface value and the interface value stores a pointer to that memory. The xunsafe.AsPointer function does have code to handle both of representations.

huangapple
  • 本文由 发表于 2023年2月17日 07:31:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/75478950.html
匿名

发表评论

匿名网友

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

确定