为什么Golang中的函数是指针?

huangapple go评论76阅读模式
英文:

Why functions in Golang are pointers

问题

在Go语言中,我们可以将所有数据类型分为两组。

Int、Float、Array、Strucs - 值类型
Slice、Map、Func、Interface - 指针类型

我理解为什么Slice和Map是指针类型。例如,你可以在不同的函数中向map中添加更多的值:

func main() {
    m := make(map[string]string)
    updateMap(m)
    fmt.Println(m)
}

func updateMap(m map[string]string) {
    m["1"] = "1"
    m["2"] = "2"
    m["3"] = "3"
    m["4"] = "4"
}

Slice可以简单地进行更新:

func main() {
    s := make([]int, 2)
    s[0] = 0
    s[1] = 0

    updateSlice(s)
    fmt.Println(s)
}

func updateSlice(s []int) {
    s[0] = 1
    s[1] = 1
}

但是为什么函数需要是指针呢?

我无法覆盖它:

func main() {
    f := func() {
        fmt.Println("Hello, 世界")
    }

    update(f)
    f()
}

func update(f func()) {
    f = func() {
        fmt.Println(2)
    }
}

所以,我真的很困惑为什么它应该是一个指针,为什么它不能只是一个值?

我有一个假设,这与函数的内存管理有关。我认为,如果函数不是指针,我们就无法像这样做:

func main() {
    s := 2
    x := func() {
        s = 3
    }
    updateFunc(x)
    fmt.Println(s)
}

func updateFunc(f func()) {
    f()
}
英文:

In the GoLang we can divide all data types into two groups.

Int, Float, Array, Strucs - value types
Slice, Map, Func, Interface - pointer types.

I understand why Slice and Map are pointers. For example you can add more values into the map in the different function:

func main() {
	m := make(map[string]string)
	updateMap(m)
	fmt.Println(m)
}

func updateMap(m map[string]string) {
	m["1"] = "1"
	m["2"] = "2"
	m["3"] = "3"
	m["4"] = "4"
}

Slice you can simply update:

func main() {
   s := make([]int, 2)
   s[0] = 0
   s[1] = 0

   updateSlice(s)
   fmt.Println(s)
}

func updateSlice(s []int) {
   s[0] = 1
   s[1] = 1
}

**But what is the reason for func to be a pointer? **

I can't overwrite it:


func main() {
 f := func() {
  fmt.Println("Hello, 世界")
 }

 update(f)
 f()

}

func update(f func()) {
 f = func() {
  fmt.Println(2)
 }
}


So, i really confused why it should be a pointer, why it can't be just an value?

I have an assumption, that this is related to memory managment of the functions.
IMHO, if funcs wount be a pinters, we could not do like this:

func main() {
   s := 2
   x := func() {
      s = 3
   }
   updateFunc(x)
   fmt.Println(s)
}

func updateFunc(f func()) {
   f()
}

答案1

得分: 3

函数、切片、映射和接口都不是指针。指针可以被解引用,但其他类型都不能。切片和映射是包含指针的数据结构,仅此而已。

你的updateMapupdateSlice函数与update(f func())无效的类比,因为它们没有对参数进行赋值。你可以尝试以下方式:

func updateSlice(s []int) {
   s = []int{}
}

在Go中,所有参数都是按值传递的:

> 在[函数值和参数]被评估之后,调用的参数按值传递给函数,被调用的函数开始执行。

英文:

Functions are not pointers and neither are slices, maps, nor interfaces. Pointers can be dereferenced, but none of the other types can be. Slices and maps are data structures that contain pointers, that's all.

Your updateMap and updateSlice functions are invalid analogies to update(f func()) because they don't assign to the argument. Try for instance:

func updateSlice(s []int) {
   s = []int{}
}

In Go, all arguments are passed by value:

> After [the function value and arguments] are evaluated, the parameters of the call are passed by value to the function and the called function begins execution.

huangapple
  • 本文由 发表于 2022年12月27日 19:35:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/74928753.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定