Fix: QTTabBar Tabs Unable to Be Placed at the Top of Windows 11 File Explorer After an Update

After a Windows 11 update, my QTTabBar-enhanced File Explorer started crashing. Once relaunched, I couldn’t move the QTTabBar tabs or command bar to the top anymore.

In QTTabBar’s options, only these showed up: “Extra View (Left)”, “QT Command Bar (Vertical)”, “Extra View (Bottom)”, and “QTTabBar – Bottom”:

not as usual:

Tried the online advice: Control Panel > Internet Options > Programs tab > Manage add-ons > Enable all QTTabBar-related plugins (like QT Command Bar 2, QT Base Toolbar, Extra View (left)). Restarted the OS. Still nothing.

This seems tied to the Windows 11 update, likely enabling feature ID 57048216, which breaks third-party toolbars like QTTabBar from displaying or pinning to the top. Disabling it restores compatibility. Here’s how:

  1. Grab the latest ViVeTool from GitHub: https://github.com/thebookisclosed/ViVe/releases — download the ZIP (e.g., ViVeTool-v0.x.x.zip).
  2. Extract to a folder, say C:\ViVeTool.
  3. Open Command Prompt as admin (Win + S, search “cmd”, right-click > Run as administrator).
  4. CD into the folder:
    cd C:\ViVeTool
    adjust your path.
  5. Run:
    vivetool /disable /id:57048216
    If you’ve previously disabled native tabs, repeat for these IDs to be sure: 39145991, 36354489, 37634385. E.g., vivetool /disable /id:39145991
  6. Reboot.
  7. Open File Explorer, go to View > Options, and check if the QTTabBar option appears. If so, enable it.

Worked like a charm — tabs back on top!

If it doesn’t fix things, roll back by swapping /disable with /enable and re-running.

Windows 11更新系统后导致QTTabBar选项卡无法置于资源管理器顶部的解决方法

Windows 11更新系统后导致使用了QTTabBar的资源管理器奔溃,然后我重新打开资源管理器,发现无法将QTTabBar选项卡和命令栏移到资源管理器的顶部。

在QTTabBar的选项中,只有“额外视图(左侧)”、“QT 命令栏(垂直)”、“额外视图(底部)”和“QTTabBar – 底部”这几个选项:

没有正常的“QTTabBar”等选项:

我已经尝试恢复QTTabBar的默认设置,也卸载并重新安装过QTTabBar的最新版(2048版本)1043版本,都没有解决这个问题。

我按照网上的教程:依次打开控制面板->Internet选项->“程序”选项卡->管理加载项->启用所有QTTabBar加载项,即全部启用与 QTTabBar 相关的插件,例如 QT Command Bar 2、QT Base Toolbar、Extra View (left) 等,然后重启操作系统后,还是没有解决这个问题。

Windows 11更新系统后导致了这个问题,因此这个问题很有可能与Windows 11更新有关。Windows 11更新可能启用了ID 57048216的功能,导致第三方工具栏(如QTTabBar)无法显示或置顶。禁用它可恢复兼容性,步骤如下:

1 从GitHub下载ViVeTool最新版:https://github.com/thebookisclosed/ViVe/releases,下载ZIP文件(如ViVeTool-v0.x.x.zip)。

2 解压到任意文件夹(如C:\ViVeTool)。

3 以管理员身份打开命令提示符(按Win + S搜索”cmd”,右键“以管理员身份运行”)。

4 导航到解压文件夹:输入cd C:\ViVeTool(替换你的路径)。

5 执行命令:

vivetool /disable /id:57048216

如果之前已禁用原生标签,也可重复禁用这些ID以确保:39145991、36354489、37634385。命令如vivetool /disable /id:39145991等。

6 重启电脑。

7 打开资源管理器,检查View > Options中是否出现QTTabBar选项(顶部)。如果出现,勾选它。

按照步骤操作后,ViVeTool解决了这个问题,QTTabBar选项卡又可以置于资源管理器的顶部了!

注意,如果ViVeTool也不能解决这个问题,用/enable替换/disable重新执行上述命令回滚这些变更。

参考

https://blog.csdn.net/zxfrdas/article/details/51174382

http://qttabbar.wikidot.com/forum/t-1637257/can-t-move-qt-command-bar-and-qttabbar-to-the-top

如果系统启用了IPv6 dual-stack支持,Go的net.Listen函数就能同时处理IPv4和IPv6流量

在 Go 的 net/http 包中,地址格式”:8091″(即不指定 IP,只指定端口)会尝试监听所有可用网络接口,包括 IPv4 和 IPv6。这不是只监听 IPv4,而是依赖于系统的网络栈配置。

Go 的 net.Listen("tcp", ":8091")(这是 ListenAndServe 函数内部调用的)会优先解析为 IPv6 地址 [::]:8091,如果系统启用了 IPv6 dual-stack 支持(即 IPv6 套接字可以接受 IPv4 连接),它会同时处理 IPv4 和 IPv6 流量。这被称为 “IPv4-mapped IPv6 addresses”。

但是,如果你的系统:
● 未启用 IPv6(例如,内核模块未加载,或 /proc/sys/net/ipv6/conf/all/disable_ipv6 设置为 1(可以cat它看看))。
● 或者系统配置了 net.ipv6.bindv6only = 1(Linux 下检查 /proc/sys/net/ipv6/bindv6only(可以cat它看看))

则 IPv6监听不会fallback到 IPv4,导致实际只监听 IPv6,导致浏览器访问http://[::1]:8091/能正常访问到首页,访问http://localhost:8091/也能正常访问到首页,但是访问
http://127.0.0.1:8091/报错:

无法访问此网站
连接已重置。
请试试以下办法:
检查网络连接
检查代理服务器和防火墙
运行 Windows 网络诊断
ERR_CONNECTION_RESET

在实践中,许多开发环境(如 Windows、macOS 或某些 Linux 发行版)默认启用 dual-stack,所以它应该同时监听 IPv4 和 IPv6。

要确认实际监听情况,你可以用命令行工具检查:

● Linux/macOS运行:

ss -tuln | grep 8091 或 netstat -tuln | grep 8091

如果显示:

tcp6   0   0   :::8091   :::*   LISTEN

则支持 IPv6,如果只显示:

tcp   0   0   0.0.0.0:8091   0.0.0.0:*   LISTEN

则只支持 IPv4。

● Windows运行:netstat -ano | findstr 8091

检查系统是否启用IPv6:

● Linux:cat /proc/sys/net/ipv6/conf/all/disable_ipv6(应为 0);如果为 1,编辑 /etc/sysctl.conf 添加net.ipv6.conf.all.disable_ipv6 = 0,然后 sysctl -p 重载。
● Windows:控制面板 > 网络和共享中心 > 更改适配器设置 > 属性 > 启用 “Internet 协议版本 6 (TCP/IPv6)”。
● macOS:系统偏好 > 网络 > 高级 > TCP/IP > 配置 IPv6 为 “自动”。

Go路径(GOPATH)的作用是什么?

$ go help gopath

Go路径用来解析import语句导入的包路径。它由go/build包实现并给出文档。

GOPATH环境变量指导Go项目代码在何处查找要导入的包。在Unix系统里,GOPATH环境变量的值是冒号’:’分隔的路径字符串。在Windows系统里,该值是分号’;’分隔的路径字符串。在Plan 9系统里,该值是一个字符串列表。

GOPATH环境变量的默认值是用户家目录下名为”go”的文件夹的绝对路径(在Unix系统里是$HOME/go,在Windows系统里是%USERPROFILE%\go)。执行go env GOPATH命令查看GOPATH环境变量的当前值。

查看https://golang.org/wiki/SettingGOPATH文档,如何设置一个自定义的GOPATH值。

每个列在GOPATH变量里的目录,必须有一个预定义的结构:

  • src目录保存源代码。src目录里的子目录的路径决定了import导入的包的路径,src目录里的main包文件的名字决定了可执行文件的名字。
  • pkg目录保存了下载的包文件、编译后的静态库文件等。其中,每个操作系统和CPU架构对对应一个子目录(pkg/GOOS_GOARCH)。
  • 如果有某个目录DIR,它的路径列在GOPATH环境变量里,某个包的源代码放在DIR/src/foo/bar目录里,那么它就可以通过import “foo/bar”语句被其他Go代码文件导入,并且它编译后的静态库文件放在DIR/pkg/GOOS_GOARCH/foo/目录里,即DIR/pkg/GOOS_GOARCH/foo/bar.a。
  • bin目录保存了编译后的命令。每个命令的名字都以其源代码文件所在的目录的名字命名,而不是以整个包路径为名。也就是说,源代码在DIR/src/foo/quux/的命令安装在DIR/bin/quux/中,而不是DIR/bin/foo/quux/中。去掉了“foo/”前缀,这样你就可以将DIR/bin添加到PATH中,以访问已安装的命令。如果设置了GOBIN环境变量,则命令将安装到其值给出的目录中,而不是DIR/bin。GOBIN的值必须是绝对路径。

以下是一个列在GOPATH变量里的目录的布局实例:

    GOPATH=/home/user/go

    /home/user/go/
        src/
            foo/
                bar/               (在bar包中的Go源代码)
                    x.go
                quux/              (在main包中的Go源代码)
                    y.go
        bin/
            quux                   (安装的命令)
        pkg/
            linux_amd64/
                foo/
                    bar.a          (安装的包对象,即静态库文件)

Go会在GOPATH里列出的所有目录路径里搜索源代码,但是新下载的包总是会被放在第一个列出的目录里。

访问https://golang.org/doc/code.html查看示例。

GOPATH和模块(Modules)模式

当使用了模块模式,GOPATH不再用于解析import语句。但是它列出的目录仍旧用于存储下载的源代码(放在GOPATH/pkg/mod目录里)和编译后的命令(放在GOPATH/bin目录里)。

internal目录

名为“internal”的目录中或其子目录中的代码只能由“internal“的父目录树中的代码导入。例如:

/home/user/go/
        src/
            crash/
                bang/              (在bang包中的Go源代码)
                    b.go
            foo/                   (在foo包中的Go源代码)
                f.go
                bar/               (在bar包中的Go源代码)
                    x.go
                internal/
                    baz/           (在baz包中的Go源代码)
                        z.go
                quux/              (在main包中的Go源代码)
                    y.go

在z.go文件中的代码的导入路径是”foo/internal/baz”,但是只能被foo目录及其子孙目录下的代码文件导入。foo/f.go,foo/bar/x.go和foo/quux/y.go这几个代码文件可以导入”foo/internal/baz”,但是crash/bang/b.go代码文件不能。

关于“internal”目录的更多信息查看https://golang.org/s/go14internal。

vendor目录

Go 1.6支持导入外部依赖项的一份本地拷贝,通常把它们放在你的Go项目的一个名为vendor的目录里。

在vendor的目录里的代码只能被本Go项目中的除了vendor目录下的代码文件之外的代码文件导入,而且导入路径要省去Go项目根目录到vendor目录的那部分路径字符串。

以下目录结构和上面的目录结构一样,只是把internal目录换为了vendor目录,并增加了一个foo/vendor/crash/bang目录。

/home/user/go/
        src/
            crash/
                bang/              (在bang包中的Go源代码)
                    b.go
            foo/                   (在foo包中的Go源代码)
                f.go
                bar/               (在bar包中的Go源代码)
                    x.go
                vendor/
                    crash/
                        bang/      (在bang包中的Go源代码)
                            b.go
                    baz/           (在baz包中的Go源代码)
                        z.go
                quux/              (在main包中的Go源代码)
                    y.go

vendor目录里的Go包与internal目录里的Go包一样,只能被由vendor的父目录树中的代码导入。上面目录结构中,z.go的导入路径是”baz”,而不是”foo/vendor/baz”。

在vendor目录里的包的导入优先级高于在src目录的直接子目录里的包,例如在foo项目目录里导入”crash/bang”,导入的是”foo/vendor/crash/bang”,而非”src/crash/bang”。

在vendor目录里的Go代码文件的import路径不会被检查。更多信息见go help importpath命令的输出。

当go get命令检查或更新一个git仓库后,它也会更新里面的子模块。

vendor目录不会影响go get命令第一次检出的新的代码仓库的位置:因为go get命令下载的代码仓库总是放在GOPATH列出的目录里,而非放在vendor子目录里。

更多信息参见https://golang.org/s/go15vendor。

恭喜本网站首次达到月10万以上PV

今天赛博菩萨Cloudflare发来邮件,恭喜本网站首次达到月10万以上PV:

但是还要再接再厉,争取早日达到PageRank 3。我接下来的打算有:
1 继续经常写博客文章,争取每天写一篇。

2 过段时间(大概过一个月左右)学习一下WordPress插件和主题的开发,把本站的前端美化一下。现在用的是WordPress默认主题,说实话,很实用,但不太美观。

3 也是过段时间(具体要过多久还没法估计)学习一下SEO,然后SEO一下本站。现在本站没有做过任何SEO。

4 修订一下访问量比较大的的文章的格式,让用户体验更好。

Go环境变量

通过执行go help environment命令打印输出go命令识别的所有环境变量的信息列表。

go命令及其调用的工具会参考环境变量进行配置。如果环境变量未设置,go命令将使用合理的默认值。要查看环境变量<NAME>的值,请运行“go env<NAME>”。要更改默认设置的值,请运行“go env -w <NAME>=<VALUE>”。根据操作系统的报告,使用go env w命令更改的默认值将记录在每个用户的家目录中一个存储go环境变量的配置文件中,os.UserConfigDir函数的返回每个用户配置目录的路径。配置文件的路径可以通过设置环境变量GOENV来更改,go env GOENV命令可以打印输出当前设置的配置文件的路径,但无法通过go env -w来更改配置文件的路径。

有关go env命令可以通过go help env查看它的用法。

一、通用的环境变量

GO111MODULE:控制go命令是运行于模块模式还是GOPATH模式。值可以是off、on或auto。

GCCGO:为运行go build -compiler=gccgo设置的gccgo命令。

GOARCH:Go代码要编译到的CPU架构,例如amd64、386、arm、ppc64等。

GOBIN:运行go install命令安装某个命令到的目录的绝对路径。可以执行go list -f '{{.Target}}'命令查看当前项目的默认安装路径

GOCACHE:是一个目录的绝对路径,go命令将在该目录缓存信息以供未来构建程序使用。

GOMODCACHE:是一个目录的绝对路径,go命令把下载的模块缓存在该目录里。

GODEBUG:启用多种调式方式。运行go doc runtime查看相关信息。

GOENV:是一个文件的绝对路径,Go环境变量存储在该文件里。不能使用go env -w命令改变GOENV的值。可以设置GOENV=off来禁用默认的该配置文件。

GOFLAGS:默认会应用于go命令的通过-flag=value设置的以空格分隔的一个选项列表,当然当前go命令会忽略不认识的选项。每个条目都必须是一个独立的选项。由于条目以空格分隔,因此选项的值本身不得包含空格。命令行上列出的选项将于该列表之后应用,因此某些选项会覆盖该列表里给出的选项。

GOINSECURE:以逗号分隔的模块路径前缀的glob模式列表(见Go的path.Match语法),这些模块应始终以不安全的方式获取。仅适用于直接获取的依赖项。GOINSECURE不禁用校验和数据库验证,可以通过GOPRIVATEGONOSUMDB实现这一点。

GOOS:编译Go代码到的操作系统,例如linux、darwin、windows、netbsd等。

GOPATH:更多信息参见go help gopath的输出信息。

GOPROXY:Go模块的代理服务的地址,更多信息见 https://golang.org/ref/mod#environment-variables和https://golang.org/ref/mod#module-proxy。

GOPRIVATE, GONOPROXY, GONOSUMDB:逗号分隔的模块路径前缀的一个列表(具体语法见path.Match函数的文档),这些模块总是被直接获取或者不应该使用校验和数据库验证模块的完整性。

GOROOT:Go在操作系统里的安装路径。

GOSUMDB:使用的校验和数据库验的名字以及它的公钥和URL。

GOTMPDIR:一个目录的路径,go命令在该目录里存储临时代码文件、包和二进制文件。

GOVCS:版本控制命令的一个列表,可能被用于匹配相应的版本控制的服务器,更多信息见go help vcs的输出。

GOWORK:在模块模式下,使用给定的go.work文件作为工作空间文件。默认情况下,或者当GOWORK环境变量的值为“auto”时,go命令在当前目录中搜索名为go.work的文件,然后搜索子目录,直到找到一个go.work文件为止。如果找到一个有效的go.work文件,则其内指定的模块将共同作为主(main)模块。如果GOWORK处于“off”状态,或者在“auto”状态下找不到go.work文件,则不启用工作空间模式。

二、cgo使用的环境变量

AR:使用gccgo编译器构建时用于操作库文件的命令。默认值为“ar”。

CC:用于编译C代码的命令。

CGO_ENABLED:是否启用cgo命令。0或1。

CGO_CFLAGS:当编译C代码时,传递给编译器的标志。

CGO_CFLAGS_ALLOW:一个正则表达式,指定允许出现在#cgo CFLAGS源代码指令中的其他标志。不适用于CGO_CFLAGS环境变量。

CGO_CFLAGS_DISALLOW:一个正则表达式,指定不允许出现在#cgo CFLAGS源代码指令中的其他标志。不适用于CGO_CFLAGS环境变量。

CGO_CPPFLAGS, CGO_CPPFLAGS_ALLOW, CGO_CPPFLAGS_DISALLOW:类似于CGO_CFLAGS、CGO_CFLAGS_ALLOW和CGO_CFLAGS_DISALLOW,但是用于C++预处理器。

CGO_CXXFLAGS, CGO_CXXFLAGS_ALLOW, CGO_CXXFLAGS_DISALLOW:类似于CGO_CFLAGS、CGO_CFLAGS_ALLOW和CGO_CFLAGS_DISALLOW,但是用于C++编译器。

CGO_FFLAGS, CGO_FFLAGS_ALLOW, CGO_FFLAGS_DISALLOW:类似于CGO_CFLAGS、CGO_CFLAGS_ALLOW和CGO_CFLAGS_DISALLOW,但是用于Fortran编译器。

CGO_LDFLAGS, CGO_LDFLAGS_ALLOW, CGO_LDFLAGS_DISALLOW:类似于CGO_CFLAGS、CGO_CFLAGS_ALLOW和CGO_CFLAGS_DISALLOW,但是用于连接器。

CXX:用于C++代码的命令。

FC:用于Fortran代码的命令。

PKG_CONFIG:pkg-config工具的路径。

三、计算机体系结构相关的环境变量

GOARM:如果设置了GOARCH=arm,那么将把Go代码编译为ARM架构CPU的指令。GOARM合法的值有5,6或7。

GO386:如果设置了GOARCH=386,那么GO386用于指示如何实现浮点指令。GO386合法的值有sse2(默认)或softfloat。

GOAMD64:如果设置了GOARCH=amd64,那么将把Go代码编译为64位CPU架构的指令。GOAMD64合法的值有v1(默认),v2,v3或v4。

GOMIPS:如果设置了GOARCH=mips或mipsle,那么GOMIPS用于指示使用哪一种浮点指令。GOMIPS合法的值有hardfloat(默认)或softfloat。

GOMIPS64:如果设置了GOARCH=mips64或mips64le,那么GOMIPS64用于指示使用哪一种浮点指令。GOMIPS64合法的值有hardfloat(默认)或softfloat。

GOPPC64:如果设置了GOARCH=ppc64或ppc64le,那么GOPPC64用于指示使用哪一种ISA(指令集架构)。GOPPC64合法的值有power8(默认)或power9。

GOWASM:如果设置了GOARCH=wasm,那么可以使用一个半角逗号分隔值的列表,列出要使用的WebAssembly特性。GOWASM合法的值有satconv或signext。

四、特殊目的的环境变量

GCCGOTOOLDIR:gccgo工具所在目录的路径,例如cgo,取决于gccgo是如何配置的。

GOEXPERIMENT:一个半角逗号分隔列表,元素值是要启用或禁用的工具链的实验性功能。可用实验性功能的列表可能随时间任意变化。有关当前有效值,请参阅src/internal/goexperiment/flags.go。警告:此变量是为Go工具链本身的开发和测试提供的。不支持超出该用途的使用。

GOROOT_FINAL:指出Go安装目录的路径,当Go的安装路径和构建路径不同时。在栈跟踪信息中的Go内建库的文件名将从GOROOT的值被改写为GOROOT_FINAL的值。

GO_EXTLINK_ENABLED:指示连接器是否使用外部链接模式,当cgo使用-linkmode=auto选项来链接代码时。值为0表示禁用外部链接模式,值为1表示启用。

GIT_ALLOW_PROTOCOL:由Git定义。允许与git fetch/clone一起使用的以冒号分隔的方案列表。如果设置了,任何未明确提及的方案都将被“go get”认为是不安全的。因为变量是由Git定义的,所以不能通过go-env-w设置该环境变量的默认值。

五、其他可从“go env”获得,但不能从环境中读取的信息

GOEXE:可执行文件的后缀名,在Windows里是”.exe”,在其他操作系统里没有后缀名。

GOGCCFLAGS:提供给CC命令的以空格分隔的参数列表。

GOHOSTARCH:Go工具链二进制文件的体系结构(GOARCH)。

GOHOSTOS:Go工具链二进制文件的操作系统(GOOS)。

GOMOD:在Go项目所在目录或子目录下执行go env,可在输出中看到GOMOD的值是当前主模块的go.mod文件的绝对路径。如果启用了模块模式,但还没有写出go.mod文件,则GOMOD的值将为os.DevNull(在类Unix系统上为“/dev/null”,在Windows上为“NUL”)。如果禁用模块模式,GOMOD将为空字符串。

GOTOOLDIR:go工具(编译器,文档等)安装目录的路径。

GOVERSION:当前安装和使用的Go的版本,也可从runtime.Version获取到。

六、go env命令的用法和功能

$ go help env
usage: go env [-json] [-u] [-w] [var ...]

用法:go env [-json] [-u] [-w] [var …]

该命令输出Go环境变量信息。

默认情况下,env将信息打印为shell脚本(在Windows上,为批处理文件)的语法格式。如果给定一个或多个变量名作为参数,env会在每一行中打印每个变量的值。

-json标志表示以JSON格式打印输出Go环境变量信息,而不是以shell脚本(在Windows上,为批处理文件)的格式。

-u标志需要一个或多个变量名作为参数,并取消设置这些环境变量的默认值(如果其中一个已通过go env -w设置了值的话)。

-w标志需要一个或多个形式为NAME=VALUE的参数,并将环境变量NAME的当前值更改为给定值。

如何限制go程序能使用的CPU核数?

一、在编译阶段(go build)做不到限制go程序能使用的CPU核数

因为在编译阶段(go build):

  • 不知道程序将运行在哪台机器
  • 不知道有多少 CPU、是否在容器中
  • Go 编译产物是 通用二进制,不绑定运行环境

所以 不存在编译期的 CPU 限制选项。

编译参数:

  • -gcflags
  • -ldflags
  • GOARCH / GOOS

都不能限制 CPU 核数。

二、官方 & 推荐的运行时方式(进程内)

1 环境变量(最常用)

GOMAXPROCS=4 ./app

限制4个CPU核数,等价于代码:runtime.GOMAXPROCS(4)

无需改代码

进程启动时生效

Go 1.5+ 支持

Go 1.21+ 默认会自动感知容器 CPU 限额

2 代码里设置

runtime.GOMAXPROCS(4)

只能影响 Go 调度器

不限制 OS 线程的创建(那是另一回事)。

三、操作系统 / 容器层(更“硬”的限制)

1 Docker / Kubernetes(强烈推荐)

Docker:

docker run --cpus=2 my-go-app

Kubernetes:

resources:
  limits:
    cpu: "2"

Go runtime 会:

  • 看到 cgroup 限制
  • 自动设置 GOMAXPROCS = 2(Go 1.21+)

2 Linux taskset(CPU 亲和性)

taskset -c 0,1 ./app

限制进程只能跑在 CPU 0、1

对所有语言生效

Go runtime 会“被动服从”

3 cgroups(底层方式)

echo 200000 > cpu.cfs_quota_us
echo 100000 > cpu.cfs_period_us

容器本质用的就是这种方式

最底层、最硬核

同时开启10万个goroutine最少占用多少内存?

我们来一步步拆解实际能达到的最小内存占用。

1. 每个 goroutine 的核心内存组成(最小情况)

部分大小(字节)说明
goroutine 结构体 (g)≈ 300–400 字节包含调度信息、指针、状态等(精确值随版本小幅波动)
初始栈(stack)2 KiB = 2048 字节当前绝大多数平台的最小初始栈(_StackMin)
其他运行时开销≈ 100–300 字节包含 defer 链表指针、panic 记录、gc bitmap 标记位等
单 goroutine 理论最低≈ 2.4–2.8 KiB最干净的空循环场景下实际能看到的下限

关键点:初始栈就是 2 KiB(不是 2KB 有时被误写成 2048 字节),这是 Go 1.4 以来长期保持的值(少数提案讨论过改成 4 KiB,但截至 2026 年初主流版本仍为 2 KiB)。

2. 10 万个这样的 goroutine 最少占用多少?

计算两种典型现实值:

场景每协程估算10 万协程总计备注
最理想情况(接近理论下限)2.4 KiB240–260 MiB极干净、无额外分配、无 hot/cold 分离、无 PGO、无动态栈调整
更现实的干净空转场景≈ 3–4 KiB300–420 MiB包含少量运行时元数据、GC 扫描位、栈 guard page 对齐等
带 fmt.Println 的版本5–10 KiB+500 MiB – 1 GiB+因为 println 涉及缓冲、反射、字符串常量等,会把栈撑大甚至 grow 一次

结论(最少占用):

不断输出 “hello world” 的 10 万个 goroutine,最小能做到 ≈ 240–280 MiB

(前提是使用最简代码、不带任何缓冲、用 print 而不是 fmt、关闭 race detector、纯 amd64/linux 环境)

3. 最简测试代码(尽量接近最小内存)

package main

import (
    "runtime"
    "time"
)

func main() {
    for i := 0; i < 100_000; i++ {
        go func() {
            for {
                println("hello world")   // 用内置 println 比 fmt 省内存
                // time.Sleep(time.Millisecond)   // 注释掉会更“空转”
            }
        }()
    }

    // 让主协程不退出
    print("created 100k goroutines, RSS ≈ ? \n")
    runtime.GC()
    time.Sleep(30 * time.Second)
}

编译运行后用以下方式观察(最接近“最小”值):

# RSS(常驻内存)通常最接近你关心的值
watch -n 1 "ps -o pid,rss,cmd -p $(pgrep -f your-binary) | tail -1"

# 或者用 pprof 查看更精确的 /memory/classes/heap/stacks:bytes
go tool pprof http://localhost:6060/debug/pprof/heap

4. 实际观测到的典型范围

  • 纯 for { println(“hello world”) }:通常 320–480 MiB
  • 如果把 println 去掉,只 for {}:可降到 240–320 MiB
  • 如果改成 for { time.Sleep(time.Second) }:更接近 250–300 MiB

总结一句话:

10 万个只是不停输出 “hello world” 的 goroutine,最少能压到大约 240–280 MiB 左右(理想干净场景下),现实干净代码一般落在 300–450 MiB 区间。

复杂度守恒定律:复杂度只会转移不会消失

复杂度只会转移不会消失。

现实世界中的业务的复杂度是守恒的,不是说你软件代码的设计模式用得好就能解决业务的复杂度(在软件层面,解决业务问题的是算法和数据结构,而不是软件设计,软件设计得好只是能方便代码复用、提高运维效率罢了)。

真正能减少软件层面的业务复杂度的是,高效的管理及精简业务的流程。

软件不能解决管理问题,只能在流程上提高效率。因为软件只是工具,需要人去使用、去执行。企图开发一个软件来解决管理问题的人,是本末倒置,是懒,正确的思路应该是:管理制度及其流程已经设计好了,开发一个软件来提高执行流程的效率。

Ubuntu 24安装最新版的Go语言开发环境的方法

Ubuntu 24.04(Noble Numbat)上安装 Go 语言有几种常见方式,2025-2026 年最推荐的方式是直接使用官方二进制包,这样可以拿到最新版本(目前通常是 1.24.x 或 1.25.x),而且最稳定、最容易升级。

下面给出目前最主流、最推荐的安装步骤:

推荐方式:官方二进制安装(最新版,强烈推荐)

1 打开终端,先清理旧版本(非常重要,避免冲突)

sudo rm -rf /usr/local/go

2 去官网查看最新版本(很重要!)

https://go.dev/dl

截至2026年1月,最新稳定版大概率是 go1.25.x 或更高。以 amd64 架构为例(绝大多数电脑都是这个),复制最新版下载链接。

示例(请替换成你看到的最新版):

# 进入下载目录(也可以随便哪个目录)
cd ~/Downloads

# 下载(把版本号改成最新的)
wget https://go.dev/dl/go1.25.6.linux-amd64.tar.gz

3 解压到 /usr/local(官方推荐位置)

sudo tar -C /usr/local -xzf go1.25.6.linux-amd64.tar.gz

4 把 Go 加到 PATH(永久生效):

# 打开配置文件(zsh 用 .zshrc,bash 用 .bashrc)
vim ~/.bashrc

在文件末尾加入这一行:

export PATH=$PATH:/usr/local/go/bin

也可以把go程序的默认安装目录(执行go install 模块名命令)$HOME/go/bin加入PATH环境变量。

保存退出后,立即生效:

source ~/.bashrc

5 验证安装是否成功

go version

应该看到类似输出:

go version go1.25.6 linux/amd64

再检查Go环境变量是否正常:

go env

其他可选的Go语言安装方式

1 sudo apt install golang-go # 从Ubuntu 默认仓库安装,但版本偏旧

2 PPA: longsleep/golang-backports # 版本比较新

3 sudo snap install go –classic # 版本比较新,snap启动稍慢,路径较奇怪

Tips

  • 想升级Go → 直接重复上面步骤,先删掉旧的 /usr/local/go,再下载新版覆盖即可。
  • 多版本共存 → 推荐使用 asdfmise 版本管理工具。
  • 公司/团队要求特定版本 → 也建议用 asdf/mise,而不是全局覆盖。