通过变量访问的Go函数

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

Go functions accessed through variables

问题

我刚开始学习Go语言,有些东西引起了我的注意。

像这样的函数:

delete(map, "Answer") // 用于映射
append(slice, 0) // 用于切片
len(slice), cap(slice) // 同样用于切片

等等。作为一个来自C语言类似语言的人,我想知道:

1)这些函数能否通过变量本身调用(例如 map.delete("Answer"))?

2)这是一种常见的做法(定义一个通用函数,让它自己确定类型和应该做什么),还是只适用于内置类型?例如,如果我定义了自己的类型,比如 MyCoolLinkedList,我应该在类型内部定义 lenappend 函数,并像这样调用它们:

list := new(MyCoolLinkedList)
list.len()

还是应该定义一个接收列表的函数,像这样:

len(list)
英文:

I am just starting to study Go and some things caught my attention.

Functions like:

delete(map, "Answer") // for maps
append(slice, 0) // for slices
len(slice), cap(slice) // again for slices

and so on. As someone coming from C like languages, I am wondering:

  1. Can these functions be called through the variable itself (as in map.delete("Answer"))?

  2. Is this a common practice (defining a generic function and let it figure out the type and what it should do), or is this just for the built in types. For example, if I would define my own type, like MyCoolLinkedList, should I define the len and append functions inside the type and have them called like

    list := new(MyCoolLinkedList)
    list.len()

or should I define a function that receives the list, like:

len(list)

答案1

得分: 2

1 - 你不能将内置方法“附加”到类型或值上,例如:

m := map[int]string{1: "one"}
m.delete(1)

这是一个编译时错误,你可以轻松验证

2 - Go语言没有泛型。但为了减轻“痛苦”,它提供了几个内置函数,可以接受不同类型的值。它们之所以是内置的,是因为由于缺乏泛型,它们需要编译器的帮助才能接受不同类型的值。有些函数还可以接受类型而不是表达式作为第一个参数(例如make([]int, 1)),这也是你无法创建的。内置函数没有标准的Go类型,它们只能出现在调用表达式中。

你不能创建接受不同类型值的这种函数。话虽如此,当你创建自己的类型并为其创建一个“函数”时,建议将其声明为方法,而不是辅助函数;因为如果“函数”操作的是你的具体类型,你无论如何都不能将其用于其他类型。

因此,将其声明为方法是有意义的,然后你可以更“优雅”地调用它,如:

value.Method()

作为方法也“计入”类型的方法集合,如果需要实现接口,这将很有用。例如,在你的MyCoolLinkedList中实现sort.Interface以对列表进行排序是有意义的,其中需要一个Len() int方法。

选择方法而不是辅助函数的另一个优点是,你的方法可以通过反射来使用。你可以使用reflect包列出和调用类型的方法,但不能对“仅仅”函数做同样的操作。

英文:

1 - You can't call builtin methods "attached" to types or values, e.g.

m := map[int]string{1: "one"}
m.delete(1)

is a compile time error which you can verify easily.

2 - Go doesn't have generics. But to ease the "pain", it provides several builtin functions which can accept values of different types. They are builtin because –as mentioned– due to the lack of generics, they need the help of the compiler to be able to accept values of different types. Some also accept a type instead of an expression as the first argument (e.g. make([]int, 1)) which is also something you can't create. Builtin functions do not have standard Go types, they can only appear in call expressions.

You can't create such functions that accept values of different types. Having said that, when you create your own type and you create a "function" for it, it is advisable to declare it as a method instead of a helper function; as if the "function" operates on your concrete type, you could not use it for other types anyway.

So it makes sense to declare it as a method, and then you can call it more "elegantly" like

value.Method()

Being a method also "counts" toward the method set of the type, should you need to implement an interface, e.g. in case of your MyCoolLinkedList it would make sense to implement sort.Interface to be able to sort the list, which requires a Len() int method for example.

Choosing a method over a helper function also has the advantage that your method will be available via reflection. You can list and call methods of a type using the reflect package, but you can't do the same with "just" functions.

huangapple
  • 本文由 发表于 2016年8月22日 15:37:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/39073756.html
匿名

发表评论

匿名网友

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

确定