结构字段还原

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

Struct field reverts

问题

我正在玩一下Go语言,但在进行一些测试时发现了一个奇怪的情况。

我在一个结构体中使用方法将一个变量发送到另一个应该改变字段的方法中,但当我在最后检查时,该字段又回到了初始值,这让我感到困惑。

func (this TVManager) sendMessage(message string) {
    fmt.Println("5", this.connector)
    payload := map[string]string {
        "id": "0",
        "type": "request",
        "uri": "ssap://system.notifications/createToast",
        "payload": "{'message': 'This is a message'}"}
    this.connector.sendCommand(payload)
    fmt.Println("4", this.connector)
}

这是我正在测试的方法,它调用了连接器的sendCommand方法。

func (this MockConnector) sendCommand(payload map[string]string) {
    fmt.Println("0", this)
    this.last_command = payload
    this.value = true
    fmt.Println("0", this)
}

在我使用的模拟对象中,它只是改变了这个结构体字段的值。

manager.sendMessage("This is a message")

fmt.Println("1", connector)
assert.Equal(t, expected, connector.last_command, "Command should be equal")

但是当我检查时,它又回到了初始值。我设置了一些打印语句来尝试跟踪这些值,它们按预期更改了值,但然后又恢复了。

1 {false map[]}
5 {false map[]}
0 {false map[]}
0 {true map[uri:ssap://system.notifications/createToast payload:{'message': 'This is a message'} id:0 type:request]}
4 {false map[]}
1 {false map[]}
--- FAIL: TestTVManagerSendsNotificationDownToConnector (0.00s)

这只是我正在学习Go语言时编写的一个小程序,所以我非常感谢任何人能给我提供帮助。

英文:

I'm playing with Go a bit but found this weird situation while doing some tests.

I'm using method in a struct to send a variable to another method that should change a field, but when I check it at the end, the field goes back to the first value, which has me confused.

func (this TVManager) sendMessage(message string) {
    fmt.Println("5", this.connector)
    payload := map[string]string {
	   "id": "0",
	   "type": "request",
	   "uri": "ssap://system.notifications/createToast",
	   "payload": "{'message': 'This is a message'}"}
    this.connector.sendCommand(payload)
    fmt.Println("4", this.connector)
}

This is the method I'm testing, it calls sendCommand of connector.

func (this MockConnector) sendCommand(payload map[string]string) {
    fmt.Println("0", this)
    this.last_command = payload
    this.value = true
    fmt.Println("0", this)
}

Which in the mock object I'm using is simply changing the value of this struct fields.

	manager.sendMessage("This is a message")

fmt.Println("1", connector)
assert.Equal(t, expected, connector.last_command, "Command should be equal")

But when I check it, it goes back to internal. I set some prints to try an d track the values and they change the values as expected, but then it reverts.

 1 {false map[]}
 5 {false map[]}
 0 {false map[]}
 0 {true map[uri:ssap://system.notifications/createToast payload:{'message': 'This is a message'} id:0 type:request]}
 4 {false map[]}
 1 {false map[]}
 --- FAIL: TestTVManagerSendsNotificationDownToConnector (0.00s)

This is just a small program I'm going over to learn some Go, so I appreciate any help anybody could give me.

答案1

得分: 2

你正在通过值传递结构体。只要你不修改结构体,这样做是可以的,但如果你修改了结构体,实际上只是修改了一个副本。为了使其工作,你需要使用指向需要修改的结构体的指针。

不要使用:

func (this MockConnector) sendCommand(payload map[string]string)

而要使用:

func (this *MockConnector) sendCommand(payload map[string]string)

此外,在Go语言中使用this(或self)作为接收器名称被认为是不好的做法,因为接收器与其他语言中的this指针/引用不是同一概念。

另一个最佳实践是,如果给定类型的一个方法需要指针接收器,那么该类型的所有方法都应该有指针接收器。这样无论值是指针还是非指针,方法集都保持一致。

有关更多信息,请参阅方法集,以及这些 FAQ 答案

英文:

You are passing the structures by value. This works fine so long as you are not modifying the structure, but if you do modify it you are actually only modifying a copy. To make this work you need to use pointers to the structures you need to modify.

Instead of:

func (this MockConnector) sendCommand(payload map[string]string)

Use:

func (this *MockConnector) sendCommand(payload map[string]string)

Also, it is considered a bad idea to use this (or self) as a receiver name in Go, as a receiver is not the same thing as a this pointer/reference in other languages.

Another best practice, is if one method for a given type needs a pointer receiver, all methods for that type should have pointer receivers. This is so that the method set remains consistent no matter if the value is a pointer or not.

See method sets, and these FAQ answers for more information.

huangapple
  • 本文由 发表于 2017年8月25日 12:08:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/45874311.html
匿名

发表评论

匿名网友

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

确定