小智 21
任何数据类型的有用性取决于要解决的问题以及用于解决问题的方法.如果数据类型不适合问题,那么它根本不适合问题 - 而且它没有更多的东西.
Go编程语言(以及大多数其他编程语言)基于程序员可用于构建新数据类型的简单规则.其中一些规则是:
*T:创建一个新的数据类型,它是指向T的指针[10]T:Ts的数组struct { t T; u U ... }:包含T作为组分的结构程序员可以通过编写这些简单的规则来创建复杂的数据类型.可能的数据类型总数超过了有用数据类型的数量.显然,存在(并且必须存在)根本没用的数据类型.这只是构建新数据类型的规则很简单这一事实的自然结果.
类型**T属于不太可能出现在程序中的类型.可写的*****T事实并不意味着这种类型必须非常有用.
最后,你的问题的答案:
该类型**T通常出现在我们希望将类型值的用户重定向T到另一个类型值的上下文中T,但由于某种原因,我们无法访问该值的所有用户或查找用户将花费太多时间:
T(出于某种原因)T通过指针访问该值T到另一个值在这种情况下,使用**T是自然的,因为它允许我们在O(1)中实现第3步:
type User_of_T struct {
Value **T
}
// Redirect all users of a particular value of type T
// to another value of type T.
func (u *User_of_T) Redirect(t *T) {
*(u.Value) = t
}
Run Code Online (Sandbox Code Playgroud)
OCy*_*ril 10
当您将指针传递给函数时,函数会获取它的副本.因此,为给定指针分配新值不会导致将其分配给原始指针:
type Smartphone struct {
name string
}
type Geek struct {
smartphone *Smartphone
}
func replaceByNG(s **Smartphone) {
*s = &Smartphone{"Galaxy Nexus"}
}
func replaceByIPhone(s *Smartphone) {
s = &Smartphone{"IPhone 4S"}
}
func main() {
geek := Geek{&Smartphone{"Nexus S"}}
println(geek.smartphone.name)
replaceByIPhone(geek.smartphone)
println(geek.smartphone.name)
replaceByNG(&geek.smartphone)
println(geek.smartphone.name)
}
Run Code Online (Sandbox Code Playgroud)
输出是:
Nexus S
Nexus S
Galaxy Nexus
Run Code Online (Sandbox Code Playgroud)
在 C 中,指向指针的指针是很常见的。例如:
char** argv可能是这里最突出的例子)然而,在 Go 中,指向指针的指针非常少见。不是通过指针访问数组,而是有一个切片类型(它也在内部存储一个指针)。因此,您仍然可以通过在 Go 中使用切片来获得相同类型的间接访问,但您通常不会看到像**int这里这样的东西。
然而,第二个例子可能仍然适用于 Go 程序。假设您有一个函数,它应该能够更改作为参数传递的指针。在这种情况下,您必须传递一个指向该指针的指针,以便您可以更改原始指针。这在 C 中极为常见,因为函数只能返回一个值(通常是某种错误代码),如果您想返回一个额外的指针,则必须使用指向该指针的指针作为输出参数。然而,Go 中的函数可以返回多个值,因此指向指针的指针的出现也很少见。但它们可能仍然有用,并且在某些情况下可能会导致更好的 API。
例如,atomic.StorePointer函数可能是标准库中指向指针的指针的那些罕见但隐藏得很好的用例之一。
| 归档时间: |
|
| 查看次数: |
7315 次 |
| 最近记录: |