type
Post
status
Published
date
Apr 11, 2022
slug
go-bottom-up-book-note-2&3
summary
Go语言底层原理剖析 第二&三章 读书笔记
tags
go
note
category
学习笔记
icon
password
书名: Go语言底层原理剖析 基于 Go 1.14 其他链接: 豆瓣链接, 示例源码及勘误

第二章 浮点数

Go与其他语言一样, 使用IEEE-754浮点数标准存储小数 本章其他内容除了一些浮点相关的库函数, 都是些计算机基础内容, 没什么好做笔记的

高精度运算

在高精度场景下, 可以使用math/big标准库中处理大数的三种数据类型:big.Int, big.Floatbig.Rat

big.Int

type Int struct { neg bool // sign abs nat // absolute value of the integer } type nat []Word type Word uint
原理: 是用uint切片存储大数, 理论上无限扩容 大数运算要处理保留和进位---这一点上就和在logisim中设计更高位数的运算器一样, 需要将多次运算组合起来

big.Float

type Float struct { prec uint32 mode RoundingMode acc Accuracy form form neg bool mant nat exp int32 }
原理: 把浮点数转换为大整数运算 由于进制转换间存在无限循环的情况, 即使是big.Float也会损失精度, 如果希望有理数计算不丢失精度, 可以使用big.Rat

big.Rat

type Rat struct { a, b Int }
原理: 将有理数的运算转换为分数的运算, a是分子, b是分母 其中Int就是big.Int, 依然依赖大整数运算
 
 

第三章 类型推断

类型推断, 在编译时确定未显式指明的类型 go的类型推断比较简单, 只能在声明新的变量or常量时使用
归根结底, 类型推断都是为了减少码量, 提升易读性. 真从性能的角度讲, 显式指定肯定是要更好的
下面谈谈赋值时使用类型推断的原理

词法解析&语法解析

词法解析阶段会把赋值语句右侧常量会被解析为一个未定义的类型 位于syntax/tokens.go可选项结构体如下:
const ( IntLit LitKind = iota FloatLit ImagLit RuneLit StringLit )
由于go源码采用UTF-8的编码方式, 词法解析其实就是读取常量在代码中的字符串, 然后解析字符串(e.g.字符串首字符为"or')分类讨论, 先给予未定义的类型
语法解析阶段赋值语句以AssignStmt结构表示, 源码&图示见第一章笔记的”语法解析”
a := 333为例, 其完成词法解析&语法解析后, OpOAS, LhsRhs分别为左右表达式, 右边的常量此时的类型为IntLit

抽象语法树生成&类型检查

仍以a := 333为例
抽象语法树阶段, gc会将AssignStmt结构为Node结构, 摘录Node结构体中部分成员如下:
type Node struct { Left *Node Right *Node Ninit Nodes Nbody Nodes List Nodes Rlist Nodes Type *types.Type E interface{} ... }
经过解析, Left为变量a, Right为整数333 RightE接口存储着333, 前一阶段的IntLit在这里转化为Mplint类型, 摘录Mpint的结构体源码如下:
type Mpint struct { Val big.Int Ovf bool // set if Val overflowed compiler limit (sticky) Rune bool // set if syntax indicates default type rune }
注意到这里整数通过big.Int高精度存储, 如果是浮点常量的话显然会是big.Float
类型检查阶段, RightType字段会变为types.Types[TINT], 这对应着Go语言内置的int类型
然后完成最后的类型赋值, 将Right的类型赋值给Left
上述示例中的变量a存储的大数会在SSA阶段转换为int64, 也就是说常量真正转换为内置标准类型发生在SSA阶段

总结

一言以蔽之: 推断右侧表达式的类型, 然后赋值给左侧, 这一切都发生在编译时 既能在编写时省略细节, 给人以动态类型的感觉, 又能确定变量的类型, 保持静态类型的安全
[读书笔记]编译器_Go语言底层原理剖析 第一章[读书笔记]常量与隐式类型转换_Go语言底层原理剖析 第四章