Convert from channel to channel of type that implements interface in GO
I am working on a problem that requires me to write a Go utility that can take a Go channel with a type that implements an interface and write to it. Right now if I know the type of the Go channel I can perform the writes to the channel without a problem. I make a new item of the appropriate type and send it on the channel.
The problem occurs when I try to generalize this to any channel that implements the interface needed to make the new item. If I can make a converter that converts from my internal type "logFile" to the given channel's type using the interface "hasLog" to "SetLog" ensuring the internal field "Log" of the logFile and the struct that is passed on the channel are identical, this problem would be solved. However, since I cannot convert between a channel logFile and a channel any, or a channel hasLog, I can't make and send to the channel that is passed in even after the new item is created to be sent. Since the channel sent is not a channel logFile, or a channel hasLog, but instead a channel of type that implements hasLog, we can't do the conversion.
currently it works something like what is below.
type hasLog interface {
setLog([]*string)
getLog() []*string
}
// logFile this is a struct we use to send the log information.
// this is used for channeling support.
type logFile struct {
Log []*string `json:",omitempty"`
}
// getLog this returns the log as sent by the logFile.
// this is used for channeling support.
func (r logFile) GetLog() []*string {
return r.Log
}
// setLog this will set the log of the logFile.
// this is used for channeling support.
func (r logFile) SetLog(log []*string) {
r.Log = make([]*string, 3)
r.Log[0] = log[0]
r.Log[1] = log[1]
r.Log[2] = log[2]
}
func sendChannelInfo(r RsvFile) {
if hasChannel() {
logChannelMutex.Lock()
defer logChannelMutex.Unlock()
logChannel[getGID()] <- r
}
}
// logSingle logs a formatted message sent to the appropriate place
func logSingle(level Level, message string, values ...interface{}) {
var r logFile
r.Log = make([]*string, 3)
var logs = make([]*string, 3)
//generate the logs
r.SetLog(logs)
sendChannelInfo(r)
}
// SetChannel lets us set up a pipe between a channel that receives our channeled messages and our logger.
func SetChannel(receiver interface{}) {
GID := getGID()
sender := ChannelHandle(receiver)
if receiver != nil {
logChannel[GID] = sender
return
}
}
func ChannelHandle(receiver interface{}) chan RsvFile {
sender := make(chan RsvFile)
go convertChannel(sender, receiver)
return sender
}
func convertChannel[T any](sender <-chan RsvFile, receiver T) {
for {
item := <-sender
channelType := reflect.ValueOf(receiver).Type().Elem()
var new = reflect.New(channelType).Elem().Interface()
log := item.GetLog()
println(len(log))
input := make([]reflect.Value, 1)
input[0] = reflect.ValueOf(log)
reflect.ValueOf(new).MethodByName("SetLog").Call(input)
receiver <- new
}
}
Is there a way to send to the channel provided by "SetChannel" by converting my internal type to the arbitrary other type so long as data structure implements "hasLog"?
Aucun commentaire:
Enregistrer un commentaire