V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
jeesk
V2EX  ›  Go 编程语言

golang 指针的问题

  •  
  •   jeesk · 2022-08-07 18:23:22 +08:00 · 1801 次点击
    这是一个创建于 868 天前的主题,其中的信息可能已经有所发展或是发生改变。
    func testMutex() {
    
    	stu := &Stu{
    		name: "song",
    		age:  "12",
    		s:    Stu1{name: "stu1"},
    	}
    	stu.st1 = &Stu{
    		name: "i amstu.st1",
    		age:  "",
    		s:    Stu1{},
    		st1:  nil,
    	}
    	// 获取第一个
    	fmt.Println((*Stu)(unsafe.Pointer(uintptr(unsafe.Pointer(stu)))).name)
    	i := *(*string)(unsafe.Pointer(uintptr(unsafe.Pointer(stu)) + unsafe.Sizeof("")))
    	// 获取第二个
    	fmt.Println(i)
    	// 获取第三个
    	ci := (*Stu1)(unsafe.Pointer(uintptr(unsafe.Pointer(stu)) + unsafe.Sizeof("") + unsafe.Sizeof("")))
    	fmt.Println(ci.name)
    	// 获取第四个
    	ci1 := *(*Stu)(unsafe.Pointer(uintptr(unsafe.Pointer(stu)) + unsafe.Sizeof("") + unsafe.Sizeof("") + unsafe.Sizeof(stu.s)))
    	fmt.Println(ci1)
    }
    
    type Stu struct {
    	name string
    	age  string
    	s    Stu1
    	st1  *Stu
    }
    
    type Stu1 struct {
    	name string
    }
    
    

    代码如上。 我发现 这样搞, 获取不到 Stu 里面的 st1 指针对象。 尴尬住了

    8 条回复    2022-08-07 19:52:45 +08:00
    luguhu
        1
    luguhu  
       2022-08-07 18:32:21 +08:00
    unsafe.Sizeof(reflect.ValueOf(stu.s))))
    luguhu
        2
    luguhu  
       2022-08-07 19:07:15 +08:00
    用 unsafe.Sizeof(reflect.TypeOf(stu.s)) 才对
    Trim21
        3
    Trim21  
       2022-08-07 19:12:12 +08:00 via Android
    直接用 unsafe.Offset…
    Trim21
        4
    Trim21  
       2022-08-07 19:14:23 +08:00 via Android
    unsafe.Offset(Stu{}.s) 就是 s 的 offset 了。你这样手动拼接出来的不一定对。如果编译器做了 align 的话用 size 是没法得到正确结果的。
    Trim21
        5
    Trim21  
       2022-08-07 19:17:09 +08:00 via Android
    @luguhu reflect.TypeOf(Stu{}).Filed(3).Offset)
    luguhu
        6
    luguhu  
       2022-08-07 19:35:06 +08:00
    @Trim21 我发现获取不到指针可能不是 offset 的问题, 因为获取到的 st1 的 offset 是 48, 但是指针要再 + 16 才能获取到
    Trim21
        7
    Trim21  
       2022-08-07 19:44:13 +08:00   ❤️ 1
    @luguhu #6 有两个问题,一个是这样的 offset 可能是错的,另一个是你 st1 解引用的时候类型错了,应该用 *(**Stu)(unsafe.Add(p, unsafe.Offsetof(Stu{}.st1)))

    https://go.dev/play/p/GsBLT4ENqN-

    然后还有一个潜在问题,反射包里有一个未导出的方法 reflect.ifaceIndir ,如果一个结构体是 direct 的时候指针字段(包括 map 和 slice 等)还会各种奇怪的行为...
    luguhu
        8
    luguhu  
       2022-08-07 19:52:45 +08:00
    @Trim21 确实是这样
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1095 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 18:03 · PVG 02:03 · LAX 10:03 · JFK 13:03
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.