go - 在 Goroutine 中更新值

标签 go

我目前正在从事一个学习 Golang 的个人项目,但是当我开始研究 Goroutines 时遇到了一些问题,我认为有些概念我没有正确理解。简而言之,我的代码有一个带有接收器函数“循环”的结构,它在无限循环中每 10 秒执行一次处理,直到程序终止,它已经可以工作了。现在我想添加一个简单的 Web 服务器,我需要能够在循环运行时更新结构内的一些数据,这是我用来测试案例的问题的抽象:

package main

import (
    "fmt"
    "net/http"

    "../thing"
)

var Thing1 thing.Thing

func main() {
    Thing1 := thing.NewThing("thing1")
    //This is the loop that is always running
    go Thing1.Loop()
    http.HandleFunc("/", HelloServer)
    http.ListenAndServe(":8080", nil)
}

func HelloServer(w http.ResponseWriter, r *http.Request) {
    if r.URL.Path != "/" {
        http.Error(w, "404 Not found", http.StatusNotFound)
        return
    }
    switch r.Method {
    case "GET":
        http.ServeFile(w, r, "index.html")
    case "POST":
        if err := r.ParseForm(); err != nil {
            fmt.Fprintf(w, "There was an error with the form: %v", err)
            return
        }
        fmt.Println("In handler: " + r.FormValue("fData"))
        Thing1.UpdateData(r.FormValue("fData"))
        http.ServeFile(w, r, "index.html")
    default:
        http.Error(w, "405 Method not allowed", http.StatusMethodNotAllowed)
    }

}
package thing

import (
    "fmt"
    "time"
)

type Thing struct {
    ID   string
    data string
}

func NewThing(id string) Thing {
    return Thing{ID: id}
}

func (t *Thing) Loop() {
    for {
        now := time.Now().Format("15:04:05")
        fmt.Println(t.ID + " starts at " + now)
        fmt.Println(t.ID + " Data: " + t.data)
        time.Sleep(time.Second * 10)
    }
}

func (t *Thing) UpdateData(g string) {
    t.data = g
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Test</title>
</head>
<body>
    <p>Test control panel</p>
    <form method="POST" action="/">
        <label>Data</label><input type="text" name="fData" value="">
        <input type="submit" value="submit">
    </form>
</body>
</html>

基本上,当我按下提交按钮时,我想更新 struct Things1 中的“数据”变量,这应该在循环内打印数据变量时反射(reflect)出来,但它不起作用,数据变量总是打印为空的。我不知道我做错了什么,但我认为我缺少一些关于 goroutine 的基本概念。
任何建议将不胜感激。

最佳答案

在您的 main你开始:

Thing1 := thing.NewThing("thing1")

这定义了一个名为 Thing1 的新局部变量。 ,就好像你写过:
var Thing1 Thing

然后将变量设置为 thing.NewThing 的结果:
Thing1 = thing.NewThing("thing1")

同时你的功能HelloServer没有定义任何名为 Thing1 的新变量,但确实使用了外部(包)范围 Thing1 — 一个不同的结构实例,ID = "" (空字符串)和数据 = "" .当您调用 Thing1.UpdateData(r.FormValue("fData")) ,这将传递这个空的地址 Thing1UpdateData接收器功能。此未命名 Thing1对象更新其数据,而您的循环使用 Thing1其 ID 为 "thing1" .

这很容易解决:只是不要创建新的 Thing1主要。但是,作为 JimB noted in a comment ,您也没有将数据更新与数据访问同步。如果您要通过共享进行通信,则需要某种锁定。

(Go encourages sharing by communicating, rather than communicating by sharing. 不过,这需要不同的思维方式。)

关于go - 在 Goroutine 中更新值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61648255/

相关文章:

go - 为什么 go 函数的定义不同?

go - 从不同的包导入原始文件会导致 'missing method protoreflect'

docker - 无法成功构建基于 Go 的 Docker 镜像

javascript - golang 中的 pubsub 替代方案

testing - 是否可以动态运行基准测试?

go - 编译器如何区分哪个模块(库)仅用于测试?

go - worker 循环中使用多WG的正确方法是吗?

go - 使用Iris将HTTP转发到https

amazon-web-services - Go & Docker : I'm able to run a go web server when using stdlib, 当我使用自定义包时发生错误

go - 关闭终端中的回显 - Golang