Go语言全局变量在CLI与HTTP服务间无法持久化问题问询
为什么两种操作下全局变量
tests的状态不共享? 先还原你的场景和代码:
你的Go代码如下:
package main import ( "fmt" "net/http" "os" "strconv" "github.com/go-chi/chi" ) var tests []string func main() { if len(os.Args[:]) > 1 { tests = append(tests, "test") fmt.Println(strconv.Itoa(len(tests)) + " tests") os.Exit(0) } r := chi.NewRouter() r.Get("/", func(w http.ResponseWriter, r *http.Request) { tests = append(tests, "test") fmt.Println(strconv.Itoa(len(tests)) + " tests") }) http.ListenAndServe(":8086", r) }
你遇到的现象是:
- 访问
localhost:8086时,每次刷新页面,tests的长度都会递增; - 执行
./test arg命令时,tests长度变为1,再次执行该命令,长度依然是1。
核心原因其实很直白:每个运行的程序实例都是一个独立的操作系统进程,进程之间的内存空间是完全隔离的。
拆解两种场景的区别:
启动HTTP服务的场景:
当你运行不带参数的./test时,程序会启动一个持续运行的进程(因为http.ListenAndServe是阻塞调用)。每次刷新页面,都是在同一个进程里处理HTTP请求,全局变量tests存在于这个进程的内存空间中,每次请求都会修改同一个切片,所以长度会持续递增。执行
./test arg的场景:
每次执行这个命令,操作系统都会启动一个全新的进程。这个进程启动后,会把全局变量tests初始化为空切片,执行append让长度变成1,输出后就调用os.Exit(0)退出进程。进程退出后,操作系统会回收它占用的所有内存,包括这个tests切片。下次再执行./test arg时,又是一个从零开始的新进程,tests会被重新初始化为空切片,所以每次输出都是1。
简单来说,这两个场景是完全独立的进程在各自的内存空间里操作,互相没有任何状态共享,自然不会互相影响。如果想要让不同的程序实例共享状态,你需要借助外部存储,比如文件、数据库、Redis这类工具,把状态存到进程之外的地方。
内容的提问来源于stack exchange,提问作者472084
相关产品推荐
相关产品推荐

