Skip to content

fix: 修复32位系统编译问题#194

Open
wdong1227 wants to merge 1 commit intolarksuite:v3_mainfrom
wdong1227:fix/32bit-build
Open

fix: 修复32位系统编译问题#194
wdong1227 wants to merge 1 commit intolarksuite:v3_mainfrom
wdong1227:fix/32bit-build

Conversation

@wdong1227
Copy link
Copy Markdown

修复了:32位编译时整数溢出错误,同时满足项目go1.13版本要求。
满足go1.13版本的修改方案:int(^uint(0) >> 1)
大于go1.17版本的修改方案:math.MaxInt(go1.17版本开始支持math.MaxInt)

修复这个PR(https://github.com/larksuite/oapi-sdk-go/pull/192)不满足go1.13版本的问题

根本原因: 在 service/drive/v1/api_ext.go:30 使用了 math.MaxInt64,而在32位系统上 int 类型是32位的,最大值只有 2147483647,无法容纳 math.MaxInt64 的值 9223372036854775807,导致编译时整数溢出错误。

解决方案: 使用位运算 int(^uint(0) >> 1) 动态获取当前平台的最大int值,兼容所有架构。

详细解释一下 int(^uint(0) >> 1) 和 math.MaxInt64 的区别:

math.MaxInt64 vs int(^uint(0) >> 1)

  1. math.MaxInt64 - 固定的64位最大值

const MaxInt64 = 1<<63 - 1 // = 9223372036854775807

  • 类型: int64 (始终是64位)
  • 值: 固定为 9223372036854775807 (2^63 - 1)
  • 问题: 在32位系统上,当赋值给 int 类型时会溢出

type ListFileIterator struct {
limit int // 32位系统: int = int32, 范围 -2^31 到 2^31-1
}

// 32位系统编译错误:
limit: math.MaxInt64 // ❌ 9223372036854775807 超过 int32 的最大值 2147483647


  1. int(^uint(0) >> 1) - 动态适配当前平台

这是一个位运算技巧,逐步分解:

步骤1: uint(0)

32位系统: 00000000 00000000 00000000 00000000 (uint32)
64位系统: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 (uint64)

步骤2: ^uint(0) (按位取反)

32位系统: 11111111 11111111 11111111 11111111 = 4294967295 (2^32-1)
64位系统: 11111111...11111111 (64个1) = 18446744073709551615 (2^64-1)

步骤3: ^uint(0) >> 1 (右移1位)

32位系统: 01111111 11111111 11111111 11111111 = 2147483647 (2^31-1) = MaxInt32
64位系统: 01111111...11111111 (1个0 + 63个1) = 9223372036854775807 (2^63-1) = MaxInt64

步骤4: int(...) (转换为int)

32位系统: int(2147483647) = 2147483647 ✅
64位系统: int(9223372036854775807) = 9223372036854775807 ✅


  1. 对比表

┌──────────────┬─────────────────────┬────────────────────────────────┐
│ 特性 │ math.MaxInt64 │ int(^uint(0) >> 1) │
├──────────────┼─────────────────────┼────────────────────────────────┤
│ 值(32位系统) │ 9223372036854775807 │ 2147483647 (MaxInt32) │
├──────────────┼─────────────────────┼────────────────────────────────┤
│ 值(64位系统) │ 9223372036854775807 │ 9223372036854775807 (MaxInt64) │
├──────────────┼─────────────────────┼────────────────────────────────┤
│ 32位编译 │ ❌ 溢出错误 │ ✅ 成功 │
├──────────────┼─────────────────────┼────────────────────────────────┤
│ 64位编译 │ ✅ 成功 │ ✅ 成功 │
├──────────────┼─────────────────────┼────────────────────────────────┤
│ 适配性 │ 固定64位 │ 自动适配平台 │
└──────────────┴─────────────────────┴────────────────────────────────┘


  1. 实际测试结果

package main

import (
"fmt"
"math"
"unsafe"
)

func main() {
intSize := unsafe.Sizeof(int(0)) * 8
fmt.Printf("当前系统 int 大小: %d 位\n", intSize)

  maxIntDynamic := int(^uint(0) >> 1)
  fmt.Printf("int(^uint(0) >> 1) = %d\n", maxIntDynamic)
  fmt.Printf("math.MaxInt      = %d\n", math.MaxInt)

}

image
  1. 为什么需要这个技巧?

Go 语言的 int 类型大小是平台相关的:

  • 32位系统: int = int32 (4字节)
  • 64位系统: int = int64 (8字节)

当你需要一个"尽可能大的int值"时:

  • ❌ 使用 math.MaxInt64 → 32位系统编译失败
  • ✅ 使用 int(^uint(0) >> 1) → 所有平台都能编译

  1. Go 1.17+ 的替代方案

从 Go 1.17 开始,标准库提供了更清晰的方式:

import "math"

const maxInt = math.MaxInt // 自动适配平台

但飞书SDK使用的是 go 1.13,所以需要手动实现这个技巧。


总结

  • math.MaxInt64: 固定64位值,不适合赋值给平台相关的 int 类型
  • int(^uint(0) >> 1): 通过位运算动态获取当前平台的最大int值,兼容32位和64位系统
  • 这是在 Go 1.17 之前获取 math.MaxInt 的标准技巧

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants