gpt4 book ai didi

GoRoutines 并将结构传递给原始上下文

转载 作者:数据小太阳 更新时间:2023-10-29 03:11:55 25 4
gpt4 key购买 nike

我有一个配置,它定义了一些实例 (SomeConfigItems),每个实例都创建了一个 thing()。

那个东西是一个包含的包返回的结构,其中包含一个 Price (float64) 和一个嵌套结构。嵌套结构维护了一个交易图。

问题是我能够遍历 thing.Streams.Trades 并从我的 main() 的 for{} 循环中实时查看所有交易。我看不到更新的东西。价格,即使它有时在处理程序中设置。

我很难理解嵌套结构如何包含数据但不包含价格。我觉得好像我缺少一些关于范围、goroutines 或可能是新对象实例化指针的东西。

如有任何帮助,我将不胜感激,同时我会继续阅读。我已将代码缩减为看起来相关的内容。

main.go:

package main
import thing
var Things []thing.Handler

for _, name := range SomeConfigItems {
handler := thing.New(name)
Things = append(Things, handler)
}

for {
for _, t := range Things {
log.Info("Price: ", t.Price) // This is set to 0 every iteration, but I can actively data in thing.Streams.Trades
}
}

thing.go:

package thing
import streams

type Handler struct {
Name string
Price float64
Streams streams.Streams
}

func New(name string) (h Handler, err error) {
stream, err := streams.New(strings.ToLower(name))
h = Handler{
Name: name,
Price: "0.0"
Streams: stream,
}
go h.handler()
return h, err
}

func (bot *Handler) handler() {
var currentPrice float64
for {
currentPrice = external.GetPrice(bot.Name).Price // Validated that this returns a float64
bot.Price = currentPrice // Verified that this is updated immediately after in this context.
// Unable to see Price updated from outer context.
}
}

streams.go:

package streams

type Streams struct {
Trades
}

type State struct {
Price string `json:"p"`
Quantity string `json:"q"`
}

type Trades struct {
Trades map[float64]float64
TradeMutex sync.Mutex
Updates chan State
}

func New(name string) (s Streams, err error) {
p := newTradeStream(name)
s = Streams{
Trades: p,
}
return s, err
}

func newTradeStream(name string) (ts Trades) {
ts = Trades{}
ts.Trades = make(map[float64]float64, MaxDepth)
ts.Updates = make(chan State, 500)
// ... Other watchdog code
return ts
}

注意:

我在多个位置添加了一些调试日志记录。在 Bot Handler 中,价格被打印(成功),然后更新,然后再次打印(成功)——显示 handler() 函数中的 Price 设置没有差距。

当向 main() for{} 循环添加相同类型的调试时,我尝试设置一个递增计数器并分配 thing.Price 的值——在每个循环上打印 thing.Price 结果为 0,即使我在同一个循环中设置价格(并验证它是否已设置),它在下一次迭代中返回到 0。

这种行为就是为什么我认为我缺少一些非常基本的东西。

最佳答案

在 Go 中,参数按值传递给函数——这意味着函数得到的是值的副本,而不是对变量的引用。函数接收者也是如此,返回列表也是如此。

这不是最优雅的描述,但为了便于说明,我们称其为“功能墙”。如果以一种或另一种方式传递的值是一个指针,该函数仍会获得一个副本,但它是一个内存地址的副本,因此该指针可用于更改另一侧变量的值墙。如果它是引用类型,它在类型的实现中使用指针,那么对指向的事物的更改再次可以越过那堵墙。但除此之外,更改不会越过墙,这就是为什么许多 Go 函数被编写为返回值而不是仅仅修改值的原因之一。

这是一个可运行的例子:

package main

import (
"fmt"
)

type Car struct {
Color string
}

func (c Car) Change() { // c was passed by value, it's a copy
c.Color = "Red"
}

func main() {
ride := Car{"Blue"}
ride.Change()
fmt.Println(ride.Color)
}

打印“蓝色”

但有两个小变化:

func (c *Car) Change() {  // here
c.Color = "Red"
}

func main() {
ride := &Car{"Blue"} // and here
ride.Change()
fmt.Println(ride.Color)
}

现在它打印“红色”。结构不是引用类型。所以如果你想修改一个结构来越过墙壁而不使用返回列表来完成它,请使用指针。当然,这仅适用于通过参数、返回列表或接收者传递的值;而不是墙两侧范围内的变量;或修改引用类型背后的基础值。

另见 "Pointers Versus Values" in Effective Go , 和 "Go Data Structures"拉斯考克斯。

关于GoRoutines 并将结构传递给原始上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49267235/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com