英文:
Setting a value in structure fails
问题
我在结构体中设置了值,但是没有生效。方法是按顺序调用的,而不是并行调用的。这是使用golang编写的代码,我忘了提醒你了。
如果我将代码更改为在"start"方法中设置值(而不是"init"方法),它可以正常工作;但是在"init"方法中设置值会失败。对我来说看起来非常奇怪。
以下是代码:
package main
import (
"log"
"net/http"
"time"
)
type tServer struct {
ipAddress string
port string
server http.Server
}
var server tServer
func main() {
server.ipAddress = "0.0.0.0"
server.port = "12345"
server.init()
server.start()
time.Sleep(time.Second * 5)
}
func (srv tServer) init() {
srv.server.Addr = srv.ipAddress + ":" + srv.port
log.Println("srv.server.Addr=", srv.server.Addr) ////////////////////
}
func (srv tServer) start() {
log.Println("srv.server.Addr=", srv.server.Addr) ////////////////////
go srv.startServerRoutine()
}
func (srv tServer) startServerRoutine() {
log.Println("Server started at", srv.server.Addr) //
err := srv.server.ListenAndServe()
if err != nil {
log.Println("Server Error:", err) //
return
}
}
这是控制台输出:
2017/04/18 19:43:07 srv.server.Addr= 0.0.0.0:12345
2017/04/18 19:43:07 srv.server.Addr=
2017/04/18 19:43:07 Server started at
2017/04/18 19:43:07 Server Error: listen tcp :80: bind: permission denied
请注意,根据你的代码,我无法提供关于为什么在"init"方法中设置值失败的具体原因。但是,根据输出结果,可以看出在"start"方法中设置值是有效的,而在"init"方法中设置值则失败了。
英文:
I set the value in the structure, but it is not set. The methods are called consequently, not in parallel. How can that be? This is golang, forgot to say.
If I change the code to set value in the "start" method (instead of "init" method), it works; but setting value in "init" method fails. Looks very strange to me.
package main
import (
"log"
"net/http"
"time"
)
type tServer struct {
ipAddress string
port string
server http.Server
}
var server tServer
func main() {
server.ipAddress = "0.0.0.0"
server.port = "12345"
server.init()
server.start()
time.Sleep(time.Second * 5)
}
func (srv tServer) init() {
srv.server.Addr = srv.ipAddress + ":" + srv.port
log.Println("srv.server.Addr=", srv.server.Addr) ////////////////////
}
func (srv tServer) start() {
log.Println("srv.server.Addr=", srv.server.Addr) ////////////////////
go srv.startServerRoutine()
}
func (srv tServer) startServerRoutine() {
log.Println("Server started at", srv.server.Addr) //
err := srv.server.ListenAndServe()
if err != nil {
log.Println("Server Error:", err) //
return
}
}
Here is the console:
2017/04/18 19:43:07 srv.server.Addr= 0.0.0.0:12345
2017/04/18 19:43:07 srv.server.Addr=
2017/04/18 19:43:07 Server started at
2017/04/18 19:43:07 Server Error: listen tcp :80: bind: permission denied
答案1
得分: 4
这是由于方法的原型:
func (srv tServer) init()
// ^^^ 复制值
所以:
server.init() // 更新自己的 server 副本,
// 副本在 init() 返回后被丢弃
server.start() // 使用自己的 server 副本
你需要通过指针将 srv
传递给方法:
func (srv *tServer) init()
在这种情况下,init()
和 start()
调用将在同一个 tServer
结构的副本上工作,并共享其字段中的值。
英文:
This is due to prototype of methods:
func (srv tServer) init()
// ^^^ copies values
so:
server.init() // updates its own copy of server,
// copy gets disposed after init() returns
server.start() // uses its own copy of server
You need to pass srv
by pointer to methods:
func (srv *tServer) init()
in that case both init()
and start()
calls will work on the same copy of tServer
structure and will share values in its fields.
答案2
得分: 1
如果你查看http.Server的文档,你会发现可以使用空值,表示":http":
type Server struct {
Addr string // TCP address to listen on, ":http" if empty
}
你在init()
函数中直接设置了srv.server.Addr
,但这不是正确使用http.Server
类型的方式。
也许你的意思是这样做:
func (srv tServer) startServerRoutine() {
log.Println("Server started at", srv.ipAddress + ":" + srv.port)
err := srv.server.ListenAndServe(srv.ipAddress + ":" + srv.port)
if err != nil {
log.Println("Server Error:", err)
return
}
}
英文:
If you look at the docs for http.Server you will see that a blank value is possible, and means ":http":
type Server struct {
Addr string // TCP address to listen on, ":http" if empty
You set srv.server.Addr
directly in init()
, but this is not the proper way to use the http.Server
type.
Perhaps you meant to do this:
func (srv tServer) startServerRoutine() {
log.Println("Server started at", srv.ipAddress + ":" + srv.port) //
err := srv.server.ListenAndServe(srv.ipAddress + ":" + srv.port)
if err != nil {
log.Println("Server Error:", err) //
return
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论