introduction
Ce problème apparaît dans le problème rencontré lors de l'écriture des projets, c'est-à-dire la référence circulaire du package. L'introduction du mécanisme Listener peut résoudre ce problème. En fait, cette solution peut également être étendue à d'autres langages.
résoudre
En fait, la description du problème est très simple, c'est-à-dire qu'il existe des références entre les deux packages. Bien entendu, la meilleure solution est de prendre en compte ce problème lors de la conception, afin d'éviter ce problème au stade de la conception, mais tout le monde ne le peut pas L'étape de conception semble si profonde, donc lorsque ce problème survient, nous avons besoin d'un mécanisme pour résoudre ce problème, en fait, c'est un mécanisme de rappel spécial.
package A
testA.go
func LoadServerConfig(filename string, cfg *Connect.ServerConfig) bool{
....
}
func init(){
Connect.RegisterRestServerListener(LoadServerConfig)
}
package B
testB.go
type ServerConfig struct{
...
}
type ServerListener func(filename string, cfg *ServerConfig) bool
var ServerListeners []ServerListener
func RegisterRestServerListener(l ServerListener) {
ServerListeners = append(ServerListeners, l)
}
Nous pouvons clairement voir que le package A contient le ServerConfig dans le package B, et le package B sera à nouveau utilisé LoadServerConfig
. A ce moment, une référence circulaire apparaîtra. La solution consiste à en introduire une ServerListeners
, init
qui est considérée LoadServerConfig
comme un appel de rappel dans la fonction du package A. RegisterRestServerListener
Mettez les ServerListeners dans les ServerListeners. Pour le moment, il n'est pas nécessaire d'appeler directement le package B dans le package B. Le rappel dans l' LoadServerConfig
appel direct ServerListeners
est OK, mais nous devons également introduire le A package où le package B doit être appelé, et import
ajoutez-le à la fin _
, ce qui signifie Exécuter les init
fonctions du package afin que les fonctions du package A puissent être liées au package B.
En fait, il existe une autre méthode, qui est la méthode dans [1], mais je pense personnellement qu'elles sont presque les mêmes. Je n'ai pas vraiment compris la signification du pointeur tournant. Je pensais avoir écrit un test simple code pour voir que le virage ne tourne pas, tout peut passer.
package test_cycle_a
import (
"fmt"
"hello/test_cycle_b"
)
func init() {
str := "hello world"
test_cycle_b.Test(str, rocketfunction)
}
func rocketfunction(str string) {
fmt.Println("hello : " ,str)
}
package test_cycle_b
import (
"fmt"
"strconv"
"unsafe"
)
type Callback func(str string)
var Fun Callback
func Test(str string, callback Callback) {
//pointer 转 string
straddress := &callback
strPiniter := fmt.Sprintf("%d", unsafe.Pointer(straddress))
fmt.Println("connection is", strPiniter)
//string 转 pointer
intPointer, _ := strconv.ParseInt(strPiniter, 10, 0)
var pointer *Callback
pointer = *(**Callback)(unsafe.Pointer(&intPointer))
(Callback)(*pointer)(str)
Fun = (Callback)(*pointer)
}
package main
import "hello/test_cycle_b"
import _ "hello/test_cycle_a"
func main(){
test_cycle_b.Fun("lizhaolong")
}
ouput:
connection is 824634925080
hello : hello world
hello : lizhaolong
Si nous package test_cycle_b
remplaçons la fonction Test par la fonction suivante:
func Test(str string, callback Callback) {
Fun = callback
return
}
Continuez à appeler la main
fonction ci-dessus , nous avons constaté qu'elle pouvait toujours s'exécuter avec succès, en fait, c'est la même chose que la première solution pour le moment.
En fait, il a été mentionné dans [1] d'utiliser la requête HTTP pour le résoudre.Je n'ai pas trouvé le contenu pertinent sur Internet. Mais pour l'instant, la première solution a très bien résolu notre problème. S'il existe d'autres meilleures solutions qui peuvent résoudre ce problème, vous pouvez laisser un message pour en discuter
référence: