在结构中设置一个值失败。

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

Setting a value in structure fails

问题

我在结构体中设置了值,但是没有生效。方法是按顺序调用的,而不是并行调用的。这是使用golang编写的代码,我忘了提醒你了。

如果我将代码更改为在"start"方法中设置值(而不是"init"方法),它可以正常工作;但是在"init"方法中设置值会失败。对我来说看起来非常奇怪。

以下是代码:

  1. package main
  2. import (
  3. "log"
  4. "net/http"
  5. "time"
  6. )
  7. type tServer struct {
  8. ipAddress string
  9. port string
  10. server http.Server
  11. }
  12. var server tServer
  13. func main() {
  14. server.ipAddress = "0.0.0.0"
  15. server.port = "12345"
  16. server.init()
  17. server.start()
  18. time.Sleep(time.Second * 5)
  19. }
  20. func (srv tServer) init() {
  21. srv.server.Addr = srv.ipAddress + ":" + srv.port
  22. log.Println("srv.server.Addr=", srv.server.Addr) ////////////////////
  23. }
  24. func (srv tServer) start() {
  25. log.Println("srv.server.Addr=", srv.server.Addr) ////////////////////
  26. go srv.startServerRoutine()
  27. }
  28. func (srv tServer) startServerRoutine() {
  29. log.Println("Server started at", srv.server.Addr) //
  30. err := srv.server.ListenAndServe()
  31. if err != nil {
  32. log.Println("Server Error:", err) //
  33. return
  34. }
  35. }

这是控制台输出:

  1. 2017/04/18 19:43:07 srv.server.Addr= 0.0.0.0:12345
  2. 2017/04/18 19:43:07 srv.server.Addr=
  3. 2017/04/18 19:43:07 Server started at
  4. 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.

  1. package main
  2. import (
  3. "log"
  4. "net/http"
  5. "time"
  6. )
  7. type tServer struct {
  8. ipAddress string
  9. port string
  10. server http.Server
  11. }
  12. var server tServer
  13. func main() {
  14. server.ipAddress = "0.0.0.0"
  15. server.port = "12345"
  16. server.init()
  17. server.start()
  18. time.Sleep(time.Second * 5)
  19. }
  20. func (srv tServer) init() {
  21. srv.server.Addr = srv.ipAddress + ":" + srv.port
  22. log.Println("srv.server.Addr=", srv.server.Addr) ////////////////////
  23. }
  24. func (srv tServer) start() {
  25. log.Println("srv.server.Addr=", srv.server.Addr) ////////////////////
  26. go srv.startServerRoutine()
  27. }
  28. func (srv tServer) startServerRoutine() {
  29. log.Println("Server started at", srv.server.Addr) //
  30. err := srv.server.ListenAndServe()
  31. if err != nil {
  32. log.Println("Server Error:", err) //
  33. return
  34. }
  35. }

Here is the console:

  1. 2017/04/18 19:43:07 srv.server.Addr= 0.0.0.0:12345
  2. 2017/04/18 19:43:07 srv.server.Addr=
  3. 2017/04/18 19:43:07 Server started at
  4. 2017/04/18 19:43:07 Server Error: listen tcp :80: bind: permission denied

答案1

得分: 4

这是由于方法的原型:

  1. func (srv tServer) init()
  2. // ^^^ 复制值

所以:

  1. server.init() // 更新自己的 server 副本,
  2. // 副本在 init() 返回后被丢弃
  3. server.start() // 使用自己的 server 副本

你需要通过指针将 srv 传递给方法:

  1. func (srv *tServer) init()

在这种情况下,init()start() 调用将在同一个 tServer 结构的副本上工作,并共享其字段中的值。

英文:

This is due to prototype of methods:

  1. func (srv tServer) init()
  2. // ^^^ copies values

so:

  1. server.init() // updates its own copy of server,
  2. // copy gets disposed after init() returns
  3. server.start() // uses its own copy of server

You need to pass srv by pointer to methods:

  1. 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":

  1. type Server struct {
  2. Addr string // TCP address to listen on, ":http" if empty
  3. }

你在init()函数中直接设置了srv.server.Addr,但这不是正确使用http.Server类型的方式。

也许你的意思是这样做:

  1. func (srv tServer) startServerRoutine() {
  2. log.Println("Server started at", srv.ipAddress + ":" + srv.port)
  3. err := srv.server.ListenAndServe(srv.ipAddress + ":" + srv.port)
  4. if err != nil {
  5. log.Println("Server Error:", err)
  6. return
  7. }
  8. }
英文:

If you look at the docs for http.Server you will see that a blank value is possible, and means ":http":

  1. type Server struct {
  2. 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:

  1. func (srv tServer) startServerRoutine() {
  2. log.Println("Server started at", srv.ipAddress + ":" + srv.port) //
  3. err := srv.server.ListenAndServe(srv.ipAddress + ":" + srv.port)
  4. if err != nil {
  5. log.Println("Server Error:", err) //
  6. return
  7. }
  8. }

huangapple
  • 本文由 发表于 2017年4月19日 00:56:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/43478050.html
匿名

发表评论

匿名网友

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

确定