golang 编译器浅析

181 阅读1分钟

0.1+0.2≠0.3的问题

先看一个例子

package main
import "fmt"
func main() {
    fmt.Println(add())
}
func add() bool {
    d := 0.1 + 0.2
    return d == 0.3
}

输出? image.png

开发人员都知道双精度浮点类型 0.1+0.2≠0.3,在go语言中相等是为什么?

通过 go build -gcflags -S main.go 查看这段代码生成的汇编

"".add STEXT nosplit size=6 args=0x0 locals=0x0 funcid=0x0 align=0x0
        TEXT    "".add(SB), NOSPLIT|ABIInternal, $0-0  
        FUNCDATA        $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
        FUNCDATA        $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
        MOVL    $1, AX
        RET

add函数编译为

// d := 0.1 + 0.2
// d == 0.3
MOVL $1, AX  // 搬运数据1 到寄存器AX  相当于直接赋值true
RET //返回

go编译器对常量进行了优化,常量提前计算, 并且小数使用分数的表示方式计算,达到精确计算。