Skip to content

Latest commit

 

History

History
75 lines (50 loc) · 2.59 KB

ch13.md

File metadata and controls

75 lines (50 loc) · 2.59 KB

第十三章 低级编程

  • unsafe 包广泛使用在和操作系统交互的低级包中,例如:runtime, os, syscall, net。普通程序不需要使用

13.1 unsafe.Sizeof, Alignof 和 Offsetof

  • Sizeof 报告参数在内存中的字节长度,参数可以是任何类型的表达式。Sizeof结果是常量,可以用作数组长度或计算其他的常量。

  • 聚合类型的值的长度至少是它的成员或元素长度之和。或用于对齐的内存空位,比长度之和稍大。

  • 32 位的系统上,的长度是 4 个字节; 64 位的系统上是 8 个字节:

    类型 大小
    bool 1 个字节
    intN, uintN, floatN, complexN N/8 个字节
    int, uint, uintptr 1 个字
    *T 1 个字
    string 2 个字(数据,长度)
    []T 3 个字(数据,长度,容量)
    map 1 个字
    func 1 个字
    chan 1 个字
    interface 2 个字(类型,长度)
  • Alignof 报告参数类型要求的对齐方式,返回一个常量

  • Offsetof(x.f) 计算成员 f 相对于结构体 x 起始地址的偏移量,内存空位也计算在内

    //64位上,sizeof:32    alignof:  8
    var x struct {
        a bool      //sizeof:1      alignof:1       offsetof:0
        b int16     //sizeof: 2      alignof: 2       offsetof: 2
        c []int     //sizeof: 24     alignof: 8       offsetof: 8
    }

13.2 unsafe.Pointer

  • 一个普通的指针 *T 可以转换为 unsafe.Pointer 类型的指针,然后再转换回普通指针,而且类型不一定和 *T 相同

    func Float64bits(f float64) uint64 { return *(*uint64)(unsafe.Pointer(&f)) }
  • unsafe.Pointer 类型可以转换为 uintptr 类型,以便对地址进行数值计算。但是从 uintptr 转换 为 unsafe.Pointer 可能破坏类型系统

13.3 示例:深度相等

  • 可以用 reflect.DeepEqual 比较组合类型,或者不能用 == 比较的值

  • 对于 map 和 slice,DeepEqual 比较 nil 和 空值的结果为不相等:

    var a, b []string = nil, []string{}
    fmt.Println(reflect.DeepEqual(a, b))  //false
    
    var c, d map[string]int = nil, make(map[string]int)
    fmt.Println(reflect.DeepEqual(c, d))  //false

13.4 使用 cgo 调用 C 代码

  • 在 Go 项目中定义 .c 文件,其中 #include C 库的头文件以及定义包装函数

  • 在 .go 文件 import "C" 之前在注释中声明 cgo 的编译器参数 -I -L 发现头文件以及库,inlucde 以及函数声明

  • 在 go 代码中使用 C. 来调用 C 语言函数

13.5 关于安全的注意事项

  • 新手避免使用 reflect 和 unsafe 包,需要时再复习最后两张。

(完)