大佬教程收集整理的这篇文章主要介绍了Golang:函数类型的奇怪行为,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
首先,这是我的(非常简化的)代码:
package main import ( "log" "time" ) type Parser struct { callBACk CallBACk callBACkSet chan bool test int } func NewParser() Parser { p := Parser{} p.test = 100 p.callBACkSet = make(chan bool) return p } func (p *Parser) SetCallBACk(newCallBACk CallBACk) { log.Println("=> SET CALLBACK: ",newCallBACk) p.test = 100 p.callBACk = newCallBACk log.Println("=> SETTinG CALLBACK DONE") p.callBACkSet <- true } func (p *Parser) StartParsing() { go p.parse() } func (p *Parser) parse() { cb := <-p.callBACkSet _ = cb log.Println("Verify CallBACk: ",p.callBACk) log.Println("Verify Test Variable: ",p.test) funcDone := make(chan bool) go func() { time.Sleep(3 * time.Second) // Some io-Operation here funcDone <- true }() _ = <-funcDone } type CallBACk func(messagE) type messagE int type Dialog struct { Parser Parser } func CreateDialog() (Dialog,error) { d := Dialog{} d.Parser = NewParser() d.Parser.StartParsing() return d,nil } func (d *Dialog) Onmessage(callBACk CallBACk) { log.Println("dialog.onmessage: ",callBACk) time.Sleep(3 * time.Second) // This sleep is just to prove the synchronization. It Could be removed. d.Parser.SetCallBACk(callBACk) } func main() { dialog,_ := CreateDialog() dialog.onmessage(func(m messagE){ log.Println("message: ",m) }) time.Sleep(5 * time.Second) // Not clean but just to await all of the output }
现在最大的问题是:为什么p.callBACk< nil>在p.parse而p.test不是,虽然这两个是在同一时间设置的?
应该使用通道p.callBACkSet来同步这些东西?!
在https://play.golang.org/p/14vn5Tie5Y处完全可运行的示例
我尝试用更简单的@L_556_4@main函数.我怀疑该错误是在Dialog结构中的某个地方.当我绕过它的使用时,我无法重现这个问题:
func main() { p := NewParser() p.StartParsing() p.SetCallBACk(func (m messagE) { log.Println("message: ",m) }) time.Sleep(5 * time.Second) // Not clean but just to await all of the output }
其余代码保持不变.这里修改(工作)版本的另一个可玩的例子:https://play.golang.org/p/0Y0nKbfcrv
当按值返回Dialog实例时,在createDialog中创建的原始Parser实例将丢失.
原始的Parser正在解析,并在记录时收到回调.
func CreateDialog() (Dialog,error) { d := Dialog{} d.Parser = NewParser() d.Parser.StartParsing() // <-- this instance is parsing return d,nil } func main() { dialog,_ := CreateDialog() // dialog.Parser <-- this is Now a new instance which is NOT parsing dialog.onmessage(func(m messagE){ log.Println("message: ",m) }) }
因此,要修复它,您可以执行以下三种操作之一:
1)在main中调用StartParsing.
func main() { dialog,_ := CreateDialog() dialog.Parser.StartParsing(); dialog.onmessage(func(m messagE){ log.Println("message: ",m) }) }
2)将Parser存储为Dialog中的指针:
func NewParser() *Parser { p := &Parser{} p.test = 100 p.callBACkSet = make(chan bool) return p } type Dialog struct { Parser *Parser }
3)从CreateDialog返回Dialog作为指针:
func CreateDialog() (*Dialog,error) { d := &dialog{} d.Parser = NewParser() d.Parser.StartParsing() return d,nil }
那应该解决它.
以上是大佬教程为你收集整理的Golang:函数类型的奇怪行为全部内容,希望文章能够帮你解决Golang:函数类型的奇怪行为所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。