go - go 什么时候使用 & 或不使用?
问题描述
我很困惑在声明变量时是否使用&
with go 并使用结构初始化
假设我们有一个结构包装器
type HttpResult struct {
Status int32 `json:"status"`
Msg string `json:"msg"`
Data interface{} `json:"data,omitempty"`
}
和一个定义用户模型的结构
type OmUser struct {
Id primitive.ObjectID `json:"id" bson:"_id,omitempty"`
Name string `json:"name"`
Password string `json:"password"`
Email string `json:"email"`
}
以下声明似乎给出了相同的结果:
myOmUser := OmUser{ //note no & sign here
Name: "Tony",
Password: "mypass",
Email: "tony@foo.com"
}
httpResult := &HttpResult{
Status: 0,
Msg: "ok",
Data: myOmUser,
}
js, _ := json.Marshal(httpResult)
fmt.Println(js)
或者
myOmUser := &OmUser{ //note the & sign
Name: "Tony",
Password: "mypass",
Email: "tony@foo.com"
}
httpResult := &HttpResult{
Status: 0,
Msg: "ok",
Data: myOmUser,
}
js, _ := json.Marshal(httpResult)
fmt.Println(js)
那么,何时使用&
,为什么?
解决方案
在您的特定示例中,它没有任何区别。
但是当我们看一个使用json.Unmarshal()
它的例子时,会更有意义:
jsonBlob := []byte(`{"id": "1", "name": "bob", "password": "pass", "email", "hi@me.com"}`)
var newOmUser OmUser
err := json.Unmarshal(jsonBlob, &newOmUser)
if err != nil {
panic(err)
}
这里我们事先声明了变量,然后我们使用 将&
指向该变量的指针传递给Unmarshal
函数。
这意味着该Unmarshal
函数可以访问并更新该变量,即使它是在函数外部声明的。
如果没有&
,该Unmarshal
函数将获得newOmUser
变量的副本,并且它将保留newOmUser
我们声明为空的原始变量。
当谈到指针时,我的一般经验法则是:
除非必须,否则不要使用它们。
如果您需要使用任何解组功能,您将需要它们。还有许多其他功能可以使用它们。
这是一个快速练习,可以帮助我更多地了解指针:
func uppercase(s string) {
s = strings.ToUpper(s)
fmt.Println(s)
}
// Same as the uppercase() function, but works with a pointer.
func uppercasePointer(s *string) {
*s = strings.ToUpper(*s)
fmt.Println(*s)
}
name := "bob"
uppercase(name) // prints 'BOB'
fmt.Println(name) // prints 'bob' - our variable was not changed
name2 := "bobpointer"
uppercasePointer(&name2) // prints 'BOBPOINTER'
fmt.Println(name2) // prints 'BOBPOINTER' - our variable was changed
当我们调用uppercase(name)
函数时,go 会复制name
变量并将其发送给uppercase
函数。
无论函数对它收到的副本做什么,都会保留在函数中。我们在函数外部声明的原始变量没有改变。
当我们调用uppercasePointer(&name2)
函数时,我们正在发送一个指向name2
我们声明的变量的指针。
该函数可以使用该指针来访问并更新name2
我们之前声明的变量。
一开始你可能看不到指针的意义,但是随着你继续使用 go,你会发现它们帮助我们解决了一些复杂的问题。
推荐阅读
- c++ - 下划线 QTextEdit C++ 中的特定行
- android - 这些是功能需求的例子吗?
- unit-testing - 模拟具有链式方法的 SDK 客户端
- sed - 在 LINUX/BASH 中首次出现特定模式之前插入文件内容
- java - 如何获取内部子值 Firebase?
- sed - sed 变量增量
- javascript - 材质组件web组件mwc-按钮上传文件
- python - 创建 Python 管道以转换数据
- dpdk - 如何修复 dpdk 构建错误:“需要 isa 选项 -m32 -mssse3”
- css - 在 Visual Studio 2019 中编辑 CSS 文件时,有没有办法查看类是否是媒体查询的一部分?