一段奇怪代码引起的终极,请解惑

原文链接:遇到一段无法理解的代码,求解惑!
千言万语,最后归结为下面一段代码:

type pp struct {
    arg any
}

func main() {
    m := 1
    l := 1
    n := 1

    foo(m)

    fmt.Println(m, l, n)
    println(m, l, n)
}

func foo(a any) {
    println("foo", a, &a)

    type S struct {
        t    unsafe.Pointer
        data unsafe.Pointer
    }

    eval(a)

    s := (*S)(unsafe.Pointer(&a))
    *(*int)(s.data) = 10
}

func eval(a any) {
    println(a, &a)
    p := new(pp)
    p.arg = a

}

现在的问题是:

  1. 函数 eval 中,p.arg 会导致 变量 m 逃逸。为什么?
  2. 在小于 255 的整数中,相同值的变量 l, n,使用 fmt.Println 打印时,会受到逃逸变量 m 影响,变成 10,而使用 println 打印时,m,l,n 三个变量的值仍然为 1。为什么?
  3. foo 函数中,接口类型变量 a 通过结构体类型 S 强制转换时,接口变量a 中,存储的两个指针(第一个指针表示接口中存储变量 m 类型信息的内存地址,第二个指针表示接口中存储变量m值的内存地址), 第一个指针赋给字段 t,第二个指针赋给字段 data。为什么?
  4. 在main函数中,m,l,n 三个变量的值相同,且均小于255的情况下,使用 eval 函数时,代码如下:
func main() {
    m := 1
    l := 1
    n := 1

    eval(m)
    eval(l)
    eval(n)
}

那么在 eval 函数中,println(a),打印的值(都是指针)均相同。为什么?

提示:fmt 包中的 pp 结构体,也包含一个接口类型的 arg 字段。

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 15

那么多AI工具,就没想着问问看?

1个月前 评论
KingSolvewer (楼主) 1个月前
xbvan (作者) 1个月前
KingSolvewer (楼主) 1个月前
xbvan (作者) 1个月前
KingSolvewer (楼主) 1个月前
don178 1个月前

我愿意相信。

1个月前 评论
  1. m的逃逸应该是 fmt.Println(m, l, n) 这行代码引起的。
  2. println 不会引起逃逸,fmt.Println会引起逃逸,因为fmt.Println的参数是any类型。
  3. 这个你要看下原文的评论区去理解,这些问题其实就两个关键点,一个逃逸分析一个golang内部的缓存,逃逸分析可以看https://geektutu.com/post/hpg-escape-analysis.html,golang内部缓存的时间看原文的评论区,我有粘贴源码。
1个月前 评论
KingSolvewer (楼主) 1个月前
KingSolvewer (楼主) 1个月前
don178 (作者) 1个月前
KingSolvewer (楼主) 1个月前
don178 (作者) 1个月前
KingSolvewer (楼主) 1个月前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!