Golang Go语言中 求大佬们看一下,通过指针强行转换类型,运行时会不会被教育.
有个非常大的结构而且是数组. 走 grpc 返回结果要一个一个赋值
想直接通过指针转换过来, 看起来可行 但是怕运行时被教育
https://go.dev/play/p/v5vJ53sXiEs
// You can edit this code!
// Click here and start typing.
package main
import (
“fmt”
“sync”
“unsafe”
)
// NoUnkeyedLiterals can be embedded in a struct to prevent unkeyed literals.
type NoUnkeyedLiterals struct{}
// DoNotCompare can be embedded in a struct to prevent comparability.
type DoNotCompare [0]func()
// DoNotCopy can be embedded in a struct to help prevent shallow copies.
// This does not rely on a Go language feature, but rather a special case
// within the vet checker.
//
// See https://golang.org/issues/8005.
type DoNotCopy [0]sync.Mutex
// Requirements:
// - The type M must implement protoreflect.ProtoMessage.
// - The address of m must not be nil.
// - The address of m and the address of m.state must be equal,
// even though they are different Go types.
type MessageState struct {
NoUnkeyedLiterals
DoNotCompare
DoNotCopy
// atomicMessageInfo *MessageInfo
}
type (
UnknownFields = unknownFieldsA // TODO: switch to unknownFieldsB
unknownFieldsA = []byte
)
type JuDianUpdateTeamReq struct {
state MessageState
sizeCache int32
unknownFields UnknownFields
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
CurHp uint64 `protobuf:"varint,2,opt,name=curHp,proto3" json:"curHp,omitempty"`
TotalHp uint64 `protobuf:"varint,3,opt,name=totalHp,proto3" json:"totalHp,omitempty"`
}
type TeamData struct {
Id string json:"id,omitempty"
CurHp uint64 json:"curHp,omitempty"
TotalHp uint64 json:"totalHp,omitempty"
}
func main() {
juDianUpdateTeamReq := &JuDianUpdateTeamReq{
Id: “team1”,
CurHp: 100,
TotalHp: 200,
}
teamData := (*TeamData)(unsafe.Pointer(&juDianUpdateTeamReq.Id))
fmt.Println(“teamData”, teamData)
}
Golang Go语言中 求大佬们看一下,通过指针强行转换类型,运行时会不会被教育.
更多关于Golang Go语言中 求大佬们看一下,通过指针强行转换类型,运行时会不会被教育.的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
就这个例子来讲,直接指针转换可以省去内存分配和拷贝,写法也更方便,但是要注意juDianUpdateTeamReq
和teamData
指向同一片内存了,它们是会相互影响的,小心不要出现内存竞争。
更多关于Golang Go语言中 求大佬们看一下,通过指针强行转换类型,运行时会不会被教育.的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
肯定是未定义行为,但是实践上应该没太大问题。
不知大直接这样定义行不行 https://go.dev/play/p/phb2AxTdvyN
#4 因为要通过另一套结构返回给别的接口. 那个接口定义的 TeamData
#5 这样不满足我的需求. grpc 的结构是通过 proto 自动生成的. teamdata 结构也是自动生成的 是两套系统
对内存细节没理解清楚的话,不要乱用 unsafe
为什么不用最简单的写法呢<br> teamData := TeamData{<br> Id: <a target="_blank" href="http://juDianUpdateTeamReq.Id" rel="nofollow noopener">juDianUpdateTeamReq.Id</a>,<br> // CurHp: 0,<br> // TotalHp: 0,<br> }<br> fmt.Println("teamData", &teamData)<br>
string 本身就是个 fat pointer
#8 是这样的,这个只是示例结构.实际结构 都是数组,而且字段非常多.
所以用 unsafe 是为了减少内存分配.并且提高性能.
- 过早优化是万恶之源
- 不要滥用指针 包括指针数组 减轻 GC 的负担
- 你计算过这个 struct 的字节大小吗
#11 > 过早优化是万恶之源
大佬说的太对了. 只是一个一个字段的赋值也是很麻
指针数组倒是没有用,.另外这 proto-go-gen 生成的结构都是指针,在 issue 查了一下,说是就是这样设计的.
一个 struct 大概 10-30 个左右的字段吧
一个 struct 大概 10-30 个左右的字段
常见的 数字 string slice map 类型,都很小
这样一个 struct 也就几十 /上百字节
slice []MyStruct 本身也是胖指针,没记个字节
数组 [n]MyStruct 的大小是 n * MyStruct 大小
这些在栈上传递都很快的
自己用 unsafe 处理指针,全靠自己记住内存布局,编译器帮不上忙
如果源 struct 后面有调整,旧代码也不会报错,可能会得到莫名其妙的结果
而且这种代码搜索和修改也很麻烦
#14
写了个结构体大小的比较.计算不对直接 panic, 后面的事后面再说 哈哈
不能只比较大小的
瞎玩 unsafe 是作死行为
在Golang(Go语言)中,通过指针强行转换类型是一种非常危险且不推荐的做法。这种操作在编译时可能不会报错,但在运行时很可能导致未定义行为,甚至程序崩溃,因此你提到的“被教育”实际上是指可能遇到严重的运行时错误。
Go语言是一种强类型语言,其类型系统旨在提供安全和可预测的行为。直接通过指针进行类型转换,会绕过Go的类型检查机制,从而可能引入难以调试的错误。
例如,如果你有一个int
类型的指针,并试图将其转换为*struct
类型的指针,然后解引用该指针以访问结构体成员,这将是未定义行为。因为int
和struct
在内存中的布局完全不同,这样的操作很可能导致内存访问违规。
如果你需要在Go中进行类型转换,应该使用显式的类型转换语句,但这些转换通常仅限于兼容类型之间。对于不兼容的类型,你应该重新考虑你的设计,使用接口(interface)或其他Go惯用的设计模式来实现所需的功能。
总之,通过指针强行转换类型在Go语言中是不安全的,应该避免这种做法。如果你确实需要进行类型相关的操作,请确保你的类型转换是安全的,并且符合Go语言的类型系统规范。这样可以避免运行时错误,提高代码的健壮性和可维护性。