《快学 Go 语言》第 14 课 —— 魔术变性指针

1
2
0
1. 云栖社区>
2. 码洞>
3. 博客>
4. 正文

## 《快学 Go 语言》第 14 课 —— 魔术变性指针

unsafe.Pointer
Pointer 代表着变量的内存地址，可以将任意变量的地址转换成 Pointer 类型，也可以将 Pointer 类型转换成任意的指针类型，它是不同指针类型之间互转的中间类型。Pointer 本身也是一个整型的值。

type Pointer int

Pointer 虽然是整型的，但是编译器禁止它直接进行加减运算。如果要进行运算，需要将 Pointer 类型转换 uintptr 类型进行加减，然后再将 uintptr 转换成 Pointer 类型。uintptr 其实也是一个整型。

type uintptr int

package main

import "fmt"
import "unsafe"

type Rect struct {
Width int
Height int
}

func main() {
var r = Rect {50, 50}
// *Rect => Pointer => *int => int
var width = *(*int)(unsafe.Pointer(&r))
// *Rect => Pointer => uintptr => Pointer => *int => int
var height = *(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&r)) + uintptr(8)))
fmt.Println(width, height)
}

------
50 50

package main

import "fmt"
import "unsafe"

type Rect struct {
Width int
Height int
}

func main() {
var r = Rect {50, 50}
// var pw *int
var pw = (*int)(unsafe.Pointer(&r))
// var ph *int
var ph = (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&r)) + uintptr(8)))
*pw = 100
*ph = 100
fmt.Println(r.Width, r.Height)
}

--------
100 100

var ph = (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&r)) + unsafe.Offsetof(r.Height))

package main

import "fmt"
import "unsafe"

func main() {
// body = [1,2,3,4,5,6,7,8,9,10]
var s = []int{1,2,3,4,5,6,7,8,9,10}
var len = (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&s)) + uintptr(8)))
var cap = (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&s)) + uintptr(16)))
for i:=0; i< len(body); i++ {
fmt.Printf("%d ", body[i])
}
}

------------------
0xc42000a080 10 10
1 2 3 4 5 6 7 8 9 10

package main

import "fmt"
import "unsafe"

func main() {
fmt.Println(bytes2str(str2bytes("hello")))
}

func str2bytes(s string) []byte {
}

func bytes2str(bs []byte) string {
return *(*string)(unsafe.Pointer(&bs))
}

-----
hello

package main

import "fmt"
import "unsafe"

type Rect struct {
Width int
Height int
}

func main() {
var r = Rect{50, 50}
// {typeptr, dataptr}
var s interface{} = r

var sptrs = *(*[2]*Rect)(unsafe.Pointer(&s))
// var dataptr *Rect
var sdataptr = sptrs[1]
fmt.Println(sdataptr.Width, sdataptr.Height)

// 修改原对象，看看接口指向的对象是否受到影响
r.Width = 100
fmt.Println(sdataptr.Width, sdataptr.Height)
}

-------
50 50
50 50

package main

import "fmt"
import "unsafe"

type Rect struct {
Width int
Height int
}

func main() {
// {typeptr, dataptr}
var s interface{} = Rect{50, 50}
var r = s

var rptrs = *(*[2]*Rect)(unsafe.Pointer(&r))
var rdataptr = rptrs[1]
var sptrs = *(*[2]*Rect)(unsafe.Pointer(&s))
var sdataptr = sptrs[1]

fmt.Println(sdataptr.Width, sdataptr.Height)
fmt.Println(rdataptr.Width, rdataptr.Height)

// 修改原对象
sdataptr.Width = 100
// 再对比一下原对象和目标对象
fmt.Println(sdataptr.Width, sdataptr.Height)
fmt.Println(rdataptr.Width, rdataptr.Height)
}

-----------
50 50
50 50
100 50
100 50

package main

import "fmt"
import "unsafe"

type Areable interface {
Area() int
}

type Rect struct {
Width int
Height int
}

func (r Rect) Area() int {
return r.Width * r.Height
}

func main() {
// {typeptr, dataptr}
var s Areable = Rect{50, 50}
var r interface{} = s

var rptrs = *(*[2]*Rect)(unsafe.Pointer(&r))
var rdataptr = rptrs[1]
var sptrs = *(*[2]*Rect)(unsafe.Pointer(&s))
var sdataptr = sptrs[1]

fmt.Println(sdataptr.Width, sdataptr.Height)
fmt.Println(rdataptr.Width, rdataptr.Height)

// 修改原对象
sdataptr.Width = 100
// 再对比一下原对象和目标对象
fmt.Println(sdataptr.Width, sdataptr.Height)
fmt.Println(rdataptr.Width, rdataptr.Height)
}

------
50 50
50 50
100 50
100 50

package main

import "fmt"
import "unsafe"

type Areable interface {
Area() int
}

type Rect struct {
Width int
Height int
}

func (r Rect) Area() int {
return r.Width * r.Height
}

func main() {
// {typeptr, dataptr}
var s interface{} = Rect{50, 50}
var r Areable = s.(Areable)

var rptrs = *(*[2]*Rect)(unsafe.Pointer(&r))
var rdataptr = rptrs[1]
var sptrs = *(*[2]*Rect)(unsafe.Pointer(&s))
var sdataptr = sptrs[1]

fmt.Println(sdataptr.Width, sdataptr.Height)
fmt.Println(rdataptr.Width, rdataptr.Height)

// 修改原对象
sdataptr.Width = 100
// 再对比一下原对象和目标对象
fmt.Println(sdataptr.Width, sdataptr.Height)
fmt.Println(rdataptr.Width, rdataptr.Height)
}

------
50 50
50 50
100 50
100 50

package main

import "fmt"
import "unsafe"

type Areable interface {
Area() int
}

type Rect struct {
Width int
Height int
}

func (r Rect) Area() int {
return r.Width * r.Height
}

func main() {
// {typeptr, dataptr}
var s interface{} = Rect{50, 50}
var r Rect = s.(Rect)

var sptrs = *(*[2]*Rect)(unsafe.Pointer(&s))
var sdataptr = sptrs[1]

// 修改原对象
sdataptr.Width = 100
// 再对比一下原对象和目标对象
fmt.Println(sdataptr.Width, sdataptr.Height)
fmt.Println(r.Width, r.Height)
}

+ 关注