<p>Hi all,</p>
<p>I am working on a small side project to learn go and I have hit an issue that hours of Googling and trying have made no impact on for me.</p>
<p>I am storing records in mongodb via <code>mgo</code>, which works fine.
I can pull records from mongo and send JSON perfectly.</p>
<p>However when I try to convert the data from mongo back into concrete types I am "missing" data that implements the "Alert" interface.</p>
<pre><code>package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/sns"
mgo "gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
type Alert interface {
Send(message string) error
}
type EndPoint struct {
Name string `json:"name" bson:"name"`
URI string `json:"uri" bson:"uri"`
Method string `json:"method" bson:"method"`
IgnoreSSL bool `json:"ignoreSsl" bson:"ignoreSsl"`
CheckInterval string `json:"checkInterval" bson:"checkInterval"`
LastStatus bool `json:"lastStatus" bson:"lastStatus"`
Headers http.Header `json:"headers" bson:"headers"`
Alerts []Alert `json:"alerts" bson:"alerts"`
}
type ConsoleAlert struct {
Type string `json:"type" bson:"type"`
}
func (ca ConsoleAlert) Send(message string) error {
log.Println(message)
return nil
}
type SNSAlert struct {
Type string `json:"type" bson:"type"`
Region string `json:"region" bson:"region"`
Key string `json:"key" bson:"key"`
Secret string `json:"secret" bson:"secret"`
TopicARN string `json:"topic_arn" bson:"topic_arn"`
}
func getSession(sa SNSAlert) (*session.Session, error) {
sess, err := session.NewSession(&aws.Config{
Region: aws.String(sa.Region),
Credentials: credentials.NewStaticCredentials(sa.Key, sa.Secret, ""),
})
if err != nil {
return &session.Session{}, err
}
return sess, nil
}
func (sa SNSAlert) Send(message string) error {
sess, err := getSession(sa)
if err != nil {
return err
}
svc := sns.New(sess)
params := &sns.PublishInput{
Message: aws.String(message),
TopicArn: aws.String(sa.TopicARN),
}
_, err = svc.Publish(params)
if err != nil {
return err
}
return nil
}
func main() {
session, err := mgo.Dial("localhost")
if err != nil {
panic(err)
}
defer session.Close()
DB := session.DB("mogon")
COL := DB.C("serverstest")
var bsonEPs []bson.M
err = COL.Find(bson.M{}).All(&bsonEPs)
if err != nil {
fmt.Println(err)
}
jsonResp, merr := json.Marshal(bsonEPs)
if merr != nil {
fmt.Println(err)
}
// We can get the data just fine as JSON
fmt.Printf("\nJSON DATA\n")
fmt.Println(string(jsonResp))
var endpoints []interface{}
json.Unmarshal(jsonResp, &endpoints)
fmt.Printf("\nSTRUCT DATA\n")
fmt.Println(endpoints)
// mgo can't Find into a slice of EndPoints
var bsonEPsAttempt = make([]EndPoint, 10)
err = COL.Find(bson.M{}).All(&bsonEPsAttempt)
if err != nil {
fmt.Println(err)
}
fmt.Println(bsonEPsAttempt)
}
</code></pre>
<p>Below is the console output when trying to get EndPoints</p>
<pre><code>JSON DATA
[{"_id":"5a0e42ab26d6291543f2128b","alerts":[{"type":"console"},{"key":"AWS KEY","region":"us-east-1","secret":"AWS SECRET","topic_arn":"arn:aws:sns:us-east-1:424242:alert","type":"sns"}],"checkInterval":"14s","headers":{"authKey":["password"]},"ignoreSsl":false,"lastStatus":false,"method":"GET","name":"myserver","uri":"https://myapp.com/check"}]
STRUCT DATA
[map[alerts:[map[type:console] map[key:AWS KEY region:us-east-1 secret:AWS SECRET topic_arn:arn:aws:sns:us-east-1:424242:alert type:sns]] headers:map[authKey:[password]] lastStatus:false method:GET uri:https://myapp.com/check _id:5a0e42ab26d6291543f2128b checkInterval:14s ignoreSsl:false name:myserver]]
[]EndPoint FAIL
reflect.Set: value of type bson.M is not assignable to type alerts.Alert
[]
</code></pre>
<p>How can I reliably create an EndPoint?</p>
<hr/>**评论:**<br/><br/>Kraigius: <pre><p>Umm..you didn't post the struct for alerts.Alert and can you post a minimal repro case?</p></pre>xandout: <pre><p>I have edited the code above, <code>alerts.Alert</code> is now <code>Alert</code></p></pre>Kraigius: <pre><p>Thanks.
I admit that I didn't try your code but I have a better understanding of it now. I found one thread on stackoverflow that seems to suggest that it's not possible without a workaround but I'll keep looking.</p>
<p><a href="https://stackoverflow.com/questions/26039580/how-to-use-interface-type-as-a-model-in-mgo-go" rel="nofollow">https://stackoverflow.com/questions/26039580/how-to-use-interface-type-as-a-model-in-mgo-go</a></p>
<p><strong>edit</strong>: <a href="https://stackoverflow.com/questions/23581884/unable-to-assert-type-string-from-interface" rel="nofollow">related?</a></p></pre>xandout: <pre><p>Ended up with a less than elegant solution involving a switch and json marshalling.</p>
<p>Thanks for the tips</p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传