unsafe
- 任何类型的指针和 unsafe.Pointer 可以相互转换。
- uintptr 类型和 unsafe.Pointer 可以相互转换。
1.Pointer 可以指向任意类型,实际上它类似于 C 语言里的 void*
2.pointer 不能直接进行数学运算,但可以把它转换成 uintptr,对 uintptr 类型进行数学运算,再转换成 pointer 类型。
注意:uintptr 并没有指针的语义,意思就是 uintptr 所指向的对象会被 gc 无情地回收。而 unsafe.Pointer 有指针语义,可以保护它所指向的对象在“有用”的时候不会被垃圾回收。
go/src/cmd/compile/internal/gc/unsafe.go 路径下,可以看到编译期间 Go 对 unsafe 包中函数的处理。
type Programmer struct {
name string
age int
language string
}
func main() {
p := Programmer{"stefno", 18, "go"}
fmt.Println(p)
lang := (*string)(unsafe.Pointer(uintptr(unsafe.Pointer(&p)) + unsafe.Sizeof(int(0)) + unsafe.Sizeof(string(""))))
*lang = "Golang"
fmt.Println(p)
}
//通过 unsafe.Sizeof() 函数可以获取成员大小,进而计算出成员的地址,直接修改内存。
string和数字
int, err := strconv.Atoi(string) //转换成int
int64, err := strconv.ParseInt(string, 10, 64)//转成int64,也可以是0,8,16,32,64
string := strconv.Itoa(int)//int转成string
string := strconv.FormatInt(int64,10)//转成string
byte数组转string
string([...]byte)
string和slice
githubissues
src/reflect/value.go
反射有时候会被gc
type StringHeader struct {
Data uintptr
Len int
}
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
func bytes2string(b []byte) (string){
//pbytes:=(*reflect.SliceHeader)(unsafe.Pointer(&b))
//pstring:=(*reflect.StringHeader)(unsafe.Pointer(&s))
//pstring.Data = pbytes.Data
//pstring.Len = pbytes.Len
sliceHead:=(*reflect.SliceHeader)(unsafe.Pointer(&b))
strHead:=reflect.StringHeader{
sliceHead.Data,
sliceHead.Len,
}
//runtime.KeepAlive(&bytes) // this line is essential.
return *(*string)(unsafe.Pointer(&strHead))
}
func string2bytes(s string) ([]byte){
//pbytes:=(*reflect.SliceHeader)(unsafe.Pointer(&b))
//pstring:=(*reflect.StringHeader)(unsafe.Pointer(&s))
//pbytes.Data = pstring.Data
//pbytes.Len = pstring.Len
//pbytes.Cap = pstring.Len
stringHead:=(*reflect.StringHeader)(unsafe.Pointer(&s))
sh:=reflect.SliceHeader{
stringHead.Data,
stringHead.Len,
stringHead.Len,
}
return *(*[]byte)(unsafe.Pointer(&sh))
}
func string2bytes(s string) []byte {
return *(*[]byte)(unsafe.Pointer(&s))
}
func bytes2string(b []byte) string{
return *(*string)(unsafe.Pointer(&b))
}//more efficient way
slice和数组
slice底层就是数组
参考:
1.unsafe.Pointer使用
有疑问加站长微信联系(非本文作者)