英文:
Pointer within a custom structure
问题
最近,我接触到了《Go编程蓝图》一书中的以下源代码。
type googleGeometry struct {
*googleLocation `json:"location"`
}
type googleLocation struct {
Lat float64 `json:"lat"`
Lng float64 `json:"lng"`
}
我不明白的是为什么 googleGeometry 结构体使用指针而不是字面量,并且这样声明的原因是什么?
我原本期望的声明是下面这样的:
type googleGeometry struct {
gl googleLocation `json:"location"`
}
英文:
Recently, I got exposed to following source code from "Go Programming Blueprints" book.
type googleGeometry stuct {
*googleLocation `json:"location"`
}
type googleLocation struct {
Lat float64 `json:"lat"`
Lng float64 `json:"lng"`
}
What I don't understand is why googleGeometry structure uses pointer instead of literal, and what is the reason behind such declaration?
I would expect below declaration instead of a pointer.
type googleGeometry stuct {
gl googleLocation `json:"location"`
}
答案1
得分: 2
我猜这是因为location
可能为null
,或者根本不存在。这种情况可以用指针表示。因为如果是字面值,lat
和lng
总是会有默认值。请看这个例子:为什么要用指针?
而这个例子是使用值类型而不是引用类型:值类型总是有默认值
英文:
I suppose it is because location
can be null
or would be absent at all.
Such cases can be represented with pointers. Because if it would be literal you will always have default values for lat
and lng
.
Please take a look on this example: Why pointer?
And this with a value type instead of reference: Value types always have default values
答案2
得分: 1
主要原因是JSON(反)序列化。如果您想将JSON解组为结构体,并验证文档中是否存在某些属性,使用指针是一种方便的方式。由于解组器将缺失的字段设置为nil
,因此可以方便地验证缺失的字段。
以下代码将打印:missing location attribute
func main() {
doc := []byte("{}") // 缺少 location 成员的 JSON
var geometry googleGeometry
json.Unmarshal(doc, &geometry)
if geometry.googleLocation == nil {
fmt.Println("missing location attribute")
} else {
fmt.Println("location attribute unmarshalled correctly")
}
}
参考:https://play.golang.org/p/hTj5HvI-AE
英文:
The main reason is JSON (de)serialization. If you want to unmarshal JSON into a struct and validate if certain attributes are present in the document using a pointer is a convenient way. Since the unmarshaller will leave missing fields nil
.
The following code code will print: missing location attribute
func main() {
doc := []byte("{}") // json that misses a location member
var geometry googleGeometry
json.Unmarshal(doc, &geometry)
if geometry.googleLocation == nil {
fmt.Println("missing location attribute")
} else {
fmt.Println("location attribute unmarshalled correctly")
}
}
答案3
得分: 0
googleGeometry
嵌入了一个指向googleLocation
的指针。它本质上是一个无名字段,这样Lat
和Lng
字段就可以像顶级字段一样访问。
为什么要使用
type googleGeometry struct {
*googleLocation `json:"location"`
}
而不是
type googleGeometry struct {
googleLocation `json:"location"`
}
?
我认为他们在这里做出了错误的决定。指针是可空的,所以如果你这样做:
g := googleGeometry{}
fmt.Println(g.Lat)
你将会得到一个空引用恐慌。如果嵌入一个非指针结构体,字段将自动初始化为零值。
英文:
googleGeometry
embeds a pointer to a googleLocation
. It is essentially an unnamed field so that the Lat
and Lng
fields are accessible as if they were top level fields.
Why use
type googleGeometry stuct {
*googleLocation `json:"location"`
}
instead of
type googleGeometry stuct {
googleLocation `json:"location"`
}
?
I think they made the wrong call here. The pointer is nillable so if you do:
g := googleGeometry{}
fmt.Println(g.Lat)
you will get a nil reference panic. If you embed a non-pointer struct, the fields will be automatically initialized to zeros.
答案4
得分: 0
我不确定整个问题的上下文,但是当一个指针嵌入在结构体中时,即使以值传递的方式传递类型为googleGeometry
的变量,嵌入的googleLocation
指针仍然指向与初始变量相同的内存地址(因为地址只是被复制了)。因此,尽管原始结构体是按值传递的,但原始变量和复制的变量仍共享相同的嵌入指针。这可能是预期的行为。
英文:
I'm not sure about the entire context of the question, however when a pointer is embedded inside the struct, even when the variable of type googleGeometry
is passed by value the embedded googleLocation
pointer still points to the same memory address as the initial variable (as the address is simply copied). Therefore although the original struct is passed by value both original and the copied variables share the same embedded pointer. That might be the intended behaviour.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论