Golang中全局变量的工作原理解析

Golang中全局变量的工作原理解析 我在一个包中创建了一个全局变量并存储了值。

现在我创建了另一个应用程序并存储了值,在打印值之前我调用了睡眠函数10秒,然后打印它。

与此同时,我在另一个终端中再次调用了相同的应用程序,但移除了睡眠并更改了全局变量中存储的值。

但后来我发现两个应用程序都打印了我发送的值(不同的值)。但据我所知,当全局值被更改时应该会受到影响。

我不知道是我的理解有误还是Go就是这样工作的。有人能帮忙解释一下吗?

谢谢。

7 回复

您也可以将此变量传递到需要它的地方,没有必要将其设为全局变量。

更多关于Golang中全局变量的工作原理解析的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


正如geosoft1所说,我需要在全局变量中存储驱动程序创建的语句句柄,并在其他函数中使用它。

既然两个应用程序运行在不同的处理器上,全局变量是不同的这一点我明白了。假设有人想要访问另一个应用程序存储的值,他能够访问到吗?

无论如何,使用全局变量都不是个好主意,你为什么需要它们呢?全局并不意味着你可以从另一个应用程序访问它,它们不共享内存。希望我理解正确了。

全局变量并不意味着在整个机器范围内都是全局的。它们在进程地址空间内才是全局的。

func main() {
    fmt.Println("hello world")
}

acim:

为什么需要它们?

在某些特定情况下全局变量是有用的。我认为一些常见的场景是数据库操作或处理模板时。此外,我见过在并发编程中使用受保护的全局映射(而非通道)的情况。不过,我还没确定这是否是一种好的实践方式。

你观察到的行为是正确的,这与 Go 语言中全局变量的作用域和工作原理有关。在 Go 中,全局变量是在包级别定义的变量,但每个独立的 Go 应用程序(即每个独立的进程)都拥有自己独立的内存空间。因此,在一个进程中修改全局变量不会影响另一个进程中的全局变量值。

原理解析:

  • 全局变量的作用域:在 Go 中,全局变量仅在定义它的包内可见,并且其生命周期与应用程序(进程)的生命周期相同。每个进程启动时,都会初始化自己的全局变量副本。
  • 进程隔离:操作系统为每个运行的应用程序分配独立的内存空间。因此,即使两个应用程序使用相同的代码和全局变量名,它们也是完全隔离的实例,互不影响。

示例代码说明:

假设你有一个包 mypackage 定义了全局变量:

文件:mypackage/mypackage.go

package mypackage

var GlobalValue string = "initial"

然后,你创建了两个独立的应用程序(例如,两个不同的 main 包),它们都导入了 mypackage

应用程序 1:app1.go

package main

import (
	"fmt"
	"time"
	"mypackage"
)

func main() {
	mypackage.GlobalValue = "value_from_app1"
	time.Sleep(10 * time.Second) // 睡眠 10 秒
	fmt.Println("App1 - GlobalValue:", mypackage.GlobalValue)
}

应用程序 2:app2.go

package main

import (
	"fmt"
	"mypackage"
)

func main() {
	mypackage.GlobalValue = "value_from_app2"
	fmt.Println("App2 - GlobalValue:", mypackage.GlobalValue)
}

运行结果:

  • 如果你先运行 app1,它会在睡眠期间被挂起。然后,在另一个终端中运行 app2app2 会立即输出 "App2 - GlobalValue: value_from_app2"
  • app1 睡眠结束后,它会输出 "App1 - GlobalValue: value_from_app1"
  • 两个应用程序输出不同的值,因为它们是独立的进程,各自维护 GlobalValue 的副本。

总结:

Go 中的全局变量是进程级别的,不跨进程共享。如果你需要在多个进程间共享数据,可以考虑使用外部存储(如数据库、文件系统)或进程间通信(IPC)机制,例如网络套接字、共享内存或消息队列。在单个进程内,如果你有多个 goroutine,全局变量可以被共享,但需要同步机制(如互斥锁)来避免数据竞争。

回到顶部