我目前正在从事一个学习 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"))
,这将传递这个空的地址 Thing1
到UpdateData
接收器功能。此未命名 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/