Golang代码格式化工具Gofmt与Gofumpt的算术空格不一致问题探讨

Golang代码格式化工具Gofmt与Gofumpt的算术空格不一致问题探讨 gofmtgofumpt 在处理某些算术表达式时,产生了以下不一致的空格格式。

	var butteryPalettedsLen int

	switch o.Stitch {
	case Mirror:
		butteryPalettedsLen = 2*clonePalettedsLen - 1
	case FlipH:
		butteryPalettedsLen = 2 * clonePalettedsLen
	case FlipV:
		butteryPalettedsLen = 2 * clonePalettedsLen
	default:
		butteryPalettedsLen = clonePalettedsLen
	}

乘法星号 (*) 要么全部在其前后显示 ASCII 空格,要么都不显示。我认为前者更易于阅读,并且能更好地扩展到更长、更复杂的表达式。无论如何,至少在样式上要保持一致。

这个错误在使用相应的 CLI 工具时会发生。通过 Go 官方的 VSCode Go 插件使用相同工具时也会发生。与许多其他编程语言一样,我发现这个错误会被自动保存和其他常见操作触发,难以处理,因此选择完全禁用该插件。即使 VSCode 的基本语法高亮也并非特别可靠。


更多关于Golang代码格式化工具Gofmt与Gofumpt的算术空格不一致问题探讨的实战教程也可以访问 https://www.itying.com/category-94-b0.html

6 回复

我发现不统一的间距如此令人分心,以至于我再也无法专注于运算符优先级。

攻击者可能滥用间距来暗示不同的优先级。

不理解基本算术顺序的人不应该编写代码。

更多关于Golang代码格式化工具Gofmt与Gofumpt的算术空格不一致问题探讨的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


不可能是真诚的。

图片

我刚才意识到 Go 语言会这样做,我真的很喜欢这一点。在使用其他语言时,我也会添加很多不必要的括号,以确保任何读者都不会意外地混淆运算符优先级。(甚至有一些 ESLint 规则鼓励使用这些括号)

mcandre:

我发现这种不均匀的间距非常令人分心,以至于我无法再专注于运算符优先级。

不可能是认真的。这已经变成了一个梗,你抱怨 Go 工具链的方式越来越荒谬。这是愚人节玩笑吗?如果是的话,你骗到我了。

mcandre:

攻击者可能滥用间距来暗示不同的优先级。

什么??如果攻击者正在向你的代码库提交代码,那你还有更大的问题。这完全说不通。而且——鉴于大多数 Go 项目都强制执行 gofmt,这个论点就更荒谬了。

mcandre:

不理解基本算术顺序的人不应该写代码。

  1. 孩子可以(也应该!)写代码。不要当守门员。
  2. 我的意思是——你才是那个没有立刻看到间距就想到“运算顺序”的人。我第一次看到 gofmt 这样做时,我立刻就明白这是由于运算顺序。

我想这是我最后一次回复你了。我是从一个真诚的角度出发的,而我认为你不是。你似乎对某些事情耿耿于怀,并且发布越来越荒谬的内容来试图得到某种回应。也许你可以试试 Go 的 Discord 或 subreddit。祝你好运!

mcandre 说:

在使用相应的 CLI 工具时会出现此错误。通过 Go 官方的 VSCode Go 插件使用相同工具时也会出现。

这根本不是一个错误;它是一个功能特性。看起来您对运算顺序不太熟悉。当您在同一行添加乘法和减法时,格式化程序会适当地对它们进行分组,以便您能直观地看到运算顺序。

请考虑 rsc 的以下评论

我们为此付出了很多努力。到处加空格意味着你无法一眼看出运算符优先级。比较一下

x + y * z + w
x * y + z * w
x + y*z + w
x*y + z*w

mcandre 说:

无论如何,至少在样式上要保持一致

它绝对是保持一致的;并且非常有用。当我使用其他语言时,我几乎总是使用括号来减轻阅读函数时的脑力负担(即使不需要)。不用括号就能在视觉上对它们进行分组,这真是太棒了。

我还发现 VSCode 的语法高亮工作可靠(vim 插件也是如此)。这个抱怨非常模糊。如果您有真正的问题/错误,或许可以在 github 上获得支持。我知道很多人非常喜欢 goland;您可以试试看。另外——在 VSCode 吞噬一切之前的旧时代,我们很多人使用 LiteIDE

在Go语言中,gofmtgofumpt确实存在算术运算符空格处理不一致的问题。gofmt遵循Go官方格式化规范,而gofumpt作为更严格的格式化工具,对空格规则有额外要求。

以下是具体分析:

  1. gofmt行为:对于2*clonePalettedsLen这样的表达式,gofmt会保持原样,不强制在*前后添加空格。
  2. gofumpt行为gofumpt会强制在二元运算符前后添加空格,将2*clonePalettedsLen改为2 * clonePalettedsLen

示例代码对比:

// gofmt输出(保持原样)
butteryPalettedsLen = 2*clonePalettedsLen - 1

// gofumpt输出(添加空格)
butteryPalettedsLen = 2 * clonePalettedsLen - 1

这种不一致性源于两个工具的设计目标不同:

  • gofmt:保证代码可读性的最小格式化
  • gofumpt:执行更严格的代码风格规则

如果你希望在整个项目中保持一致的格式,有两种解决方案:

方案1:统一使用gofmt

# 使用gofmt格式化整个项目
gofmt -w .

方案2:统一使用gofumpt

# 安装gofumpt
go install mvdan.cc/gofumpt@latest

# 使用gofumpt格式化整个项目
gofumpt -w .

对于VSCode,可以在设置中指定格式化工具:

{
    "go.formatTool": "gofumpt",  // 或 "gofmt"
    "editor.formatOnSave": true
}

如果你需要在项目中强制使用特定工具,可以在CI/CD流程中添加检查:

# 检查gofmt格式
gofmt -d . | grep -q '^' && exit 1

# 或检查gofumpt格式
gofumpt -d . | grep -q '^' && exit 1

这种不一致性不是bug,而是两个工具设计哲学的差异。选择哪个工具取决于团队对代码风格严格程度的要求。

回到顶部