I'm writing a document generator. There is a DocumentItem interface - this is part of the document.
type DocumentItem interface {
compose() string
}
For example, a document consists of paragraphs and tables.
type Paragraph struct {
text string
}
type Table struct{}
The Paragraph and Table types correspond to the DocumentItem interface.
func (p *Paragraph) compose() string {
return ""
}
func (t *Table) compose() string {
return ""
}
The Document type contains the content []*DocumentItem field.
type Document struct {
content []*DocumentItem
}
I'm looking for a way that would allow NewParagraph() and NewTable() functions to create the necessary data types and add them to the content field.
func (d *Document) NewParagraph() *Paragraph {
p := Paragraph{}
d.content = append(d.content, &p)
return &p
}
func (d *Document) NewTable() *Table {
t := Table{}
d.content = append(d.content, &t)
return &t
}
I use an slice of interface pointers in order to be able to modify the data in the corresponding variables after they are included in the document.
func (p *Paragraph) SetText(text string) {
p.text = text
}
func main() {
d := Document{}
p := d.NewParagraph()
p.SetText("lalala")
t := d.NewTable()
// ...
}
But I get compiler errors:
cannot use &p (type *Paragraph) as type *DocumentItem in append
cannot use &t (type *Table) as type *DocumentItem in append
If I cast the types to an DocumentItem interface, I will lose access to specific functions, which in the case of one type may differ from the other. For example, add text to a paragraph and add a row of cells and then add text to cell for the table.
Is it possible at all?
Full example at https://play.golang.org/p/uJfKs5tJ98
Don't use pointer to interface, only a slice of interfaces:
content []DocumentItem
If the dynamic value wrapped in the interface value is a pointer, you lose nothing, you will be able to modify the pointed object.
This was the only thing that had to be changed. To verify, I added printing at the end:
fmt.Printf("%+v", p)
Output (try it on the Go Playground):
&{text:lalala}
Related
Say I have two structs that define a linked list:
....
....
type node struct {
item interface{}
next *node
}
type LinkedList struct {
first *node
N int
}
...
...
and I want to compare the value of the type of the underlying node, say, in a find function where we check if k == node.item such that:
func (l *LinkedList) find (key interface{}) bool {
result := false
if !l.isEmpty() {
for x:= l.first; x != nil; x = x.next {
if x.item == key {
result = true
break
}
}
return result
}
this will not work for the expected find function because the underlying types are different, hence the func will always return false. We can confirm this upon reflecting the type:
fmt.Println(reflect.TypeOf(key), reflect.TypeOf(x.item))
>>> string, *main.node
Tried workarounds?
I've tried asserting the type but alas this does not work and panics
tmp := x.item.(string)
>>>panic: interface conversion: interface {} is *main.node, not string
This case is the same for using fmt.Sprintf(x.item)
I'm a bit stumped as to where to go from here. Is there a way to do this?
Inserting item to linked list
The following snippet should clarify how insertion is handled
func (l *LinkedList) insertFirst(item interface{}) {
var first *node = new(node)
oldfirst := l.first
first.item = item
first.next = oldfirst
l.first = first
l.N++
}
.....
//which gets called somewhere like
var n *node = new(node)
n.item = item
l.insertFirst(n)
.....wait no theres the error!
----------
burak-serdar you are 100% correct that I am inserting the node in the node!
The interface comparison in find() is a valid comparison and it will work if the type of the key and the type of the value stored in the node are the same. However, evidence points to you adding a node in place of a value.
Here is the simplified code of a cache. Suppose Container placed in a package, so it don't know about Member.
While I wanna store instances of Member in Container, So I store an empty instance of Member in Container as outerType.
In the Container->GetMysql, I fill a new variable by test values (but, in real world, It fill by data of database, dynamically).
then in the function Put, I store data in items as Cache for next uses. In the Get I get the data stored in the items.
Before this every thing is fine. My problem is where i want to convert result of Get to type of Member m = res.(Member) . How Can I convert it to an instance of Member
I found many question about this subject, but none of them solved my problem
For more detail: I want the Get return data with its pointer of where it stored in items. So if I get some variable of same member, an change in one are shown in others
package main
import (
"fmt"
"reflect"
)
type Member struct {
Id int
Name string
Credit int
Age int
}
type Container struct {
outerType interface{}
items map[string]*interface{}
}
func (cls *Container)GetMysql(s string, a int64) interface{}{
obj := reflect.New(reflect.TypeOf(cls.outerType))
elem := obj.Elem()
//elem := reflect.ValueOf(o).Elem()
if elem.Kind() == reflect.Struct {
f := elem.FieldByName("Name")
f.SetString(s)
f = elem.FieldByName("Credit")
f.SetInt(a)
}
return obj.Interface()
}
func (cls *Container)Get(value string) *interface{}{
return cls.items[value]
}
func (cls *Container)Put(value string, a int64) {
res := cls.GetMysql(value, a)
cls.items[value] = &res
}
func main() {
c := Container{outerType:Member{}}
c.items = make(map[string]*interface{})
c.Put("Jack", 500)
res := c.Get("Jack")
fmt.Println(*res)
m := &Member{}
m = res.(Member) // Here is the problem. How to convert ?
fmt.Println(m)
}
You should hardly ever use pointer to interface. My advice is to never use it, when you'll need it, you'll know.
Instead if you need a pointer to something (so you can have the same pointer at multiple places, and so modifying the pointed value somewhere, it will have effect on the others), "wrap the pointer" in the interface value.
So first modify the items field so that it stores interface{} values instead of pointers:
items map[string]interface{}
This means no restriction: you can pass and store pointers, that's not a problem.
Next modify Get() to return interface{}:
func (cls *Container) Get(value string) interface{}{
return cls.items[value]
}
And also in Put(), don't take the address of an interface{}:
func (cls *Container) Put(value string, a int64) {
res := cls.GetMysql(value, a)
cls.items[value] = res
}
And you have to type-assert *Member from the values returned by Get().
And now testing it:
c := Container{outerType: Member{}}
c.items = make(map[string]interface{})
c.Put("Jack", 500)
res := c.Get("Jack")
fmt.Println(res)
m := res.(*Member) // Here is the problem. How to convert ?
fmt.Println(m)
Output (try it on the Go Playground):
&{0 Jack 500 0}
&{0 Jack 500 0}
Now if you would modify a field of m:
m.Credit = 11
And then get the value form the cache:
fmt.Println(c.Get("Jack"))
We'll see the modified value, even though we did not call Put() (try it on the Go Playground):
&{0 Jack 11 0}
Is there any way to set an interface field using reflect? When i tried to set it, it paniced saying that the value is non addressable.
type A interface{...}
func CreateA(name string) A {...}
type B struct {
field A
should A
mirror A
}
// normal way of initializing
var b = B{
field: CreateA("field"),
should: CreateA("should"),
mirror: CreateA("mirror"),
}
func MirrorField(b *B) {
t := reflect.TypeOf(b)
v := reflect.ValueOf(b)
for i := 0; i < t.NumField(); i++ {
setTo = CreateA(t.Field(1).Name)
fieldVal := v.Field(i)
fieldVal.Set(reflect.ValueOf(setTo))
}
}
// what i want is something like
var b = &B{}
MirrorField(b)
Interfaces don't have fields, they only define a method set of the value they contain. When reflecting on an interface, you can extract the value with Value.Elem().
You also can't Set unexported fields. You need to capitalize the field names in your B type. When iterating over the fields, use Value.CanSet() to test if they are settable. CanSet() will also return false is the value isn't addressable, or the value is still in an interface.
A working example of your code:
http://play.golang.org/p/Mf1HENRSny
I have an issue using this statement
m.Post(Model, binding.Form(Wish), func(wish Wish, r render.Render, db *mgo.Database) {
This worked fine if I use the struct define inside the prog like
m.Post(Model, binding.Form(Wish1{}) , func(wish Wish1, r render.Render, db *mgo.Database) {
but I need this to be an independent package.
I get "Wish is not a type" wish is the return of the binding function.
This worked with a primary Type struct. I am passing the strut as a interface{}
I am using GO with Martini.Classic() It is really complicated for me to change Martini or Binding package. Any suggestions.
This is the all code
package chlistpkg
import (
"github.com/codegangsta/martini"
"github.com/codegangsta/martini-contrib/binding"
"github.com/codegangsta/martini-contrib/render"
"labix.org/v2/mgo"
"time"
"fmt"
"html/template"
"reflect"
"adminStruct"
)
just to show the struct that I need to pass as to routine Doall
type Wish1 struct {
Name string `form:"name"`
Description string `form:"description"`
AnyDate time.Time `form:"anydate"`
Active bool `form:"active"`
Number int `form:"number"`
NumDec float32 `form:"numDec"`
}
DB Returns a martini.Handler
func DB() martini.Handler {
session, err := mgo.Dial("mongodb://localhost")
if err != nil {
panic(err)
}
return func(c martini.Context) {
s := session.Clone()
c.Map(s.DB("advent2"))
defer s.Close()
c.Next()
}
}
GetAll returns all Wishes in the database
func GetAll(db *mgo.Database, entList interface{}) interface{} {
db.C("wishes").Find(nil).All(entList)
fmt.Println("GettAll entList =", entList)
return entList
}
func Doall(Model string, Wish interface{}, Wish2 interface{}, Wishlist interface{} ) {
m := martini.Classic()
fmt.Println ("martini.Classic =", m)
m.Use(martini.Static("images")) // serve from the "images" directory as well
m.Use(render.Renderer(render.Options{
Directory: "templates",
Layout: "layout",
}))
m.Use(DB())
m.Get(Model, func(r render.Render, db *mgo.Database) {
r.HTML(200, "lista4", GetAll(db, Wishlist))
})
binding does not take a pointer. I have to pass the struct by reference on "Wish"
the issue is the return on "wish Wish" I got an error Wish is not a type
at compilation time
m.Post(Model, binding.Form(Wish), func(wish Wish, r render.Render, db *mgo.Database) {
fmt.Println("Input wish =", wish)
db.C("wishes").Insert(wish)
r.HTML(200, "lista4", GetAll(db, Wishlist))
})
m.Run()
Thanks in advance
Luis
The reason you are getting an error is that you have called your type Wish1 (with a numerical 1) but you are referring to the Wish type (which does not exist!) in your code.
Change your struct to be:
// Note: "Wish", not "Wish1"
type Wish struct {
Name string `form:"name"`
Description string `form:"description"`
AnyDate time.Time `form:"anydate"`
Active bool `form:"active"`
Number int `form:"number"`
NumDec float32 `form:"numDec"`
}
If you want to put your type into another package (tip: don't overdo the sub-packages), then it will need to become a pkgname.Wish as names are fully qualified.
Added
After a second look, you're also messing things up here:
func Doall(Model string, Wish interface{}, Wish2 interface{}, Wishlist interface{} ) {
m := martini.Classic()
fmt.Println ("martini.Classic =", m)
m.Use(martini.Static("images")) // serve from the "images" directory as well
Your parameter list needs to provide a name for each type; you can't pass Wish interface{} as a parameter as Wish is a type, not a variable name.
You should either:
func DoAll(model string, wish interface{}, wish2 interface{}, wishList interface{}) { ... }
Or, better still, stop using interface{} like this and write:
func DoAll(model string, wishList []Wish, wishes... Wish) { ... }
However, your DoAll function does not seem to be referenced elsewhere, and is creating its own Martini instance. I highly suggest thinking about why things are "split out" like this if you're just starting out. Keep it simple - e.g.
func main() {
m := martini.Classic()
m.Use(martini.Static("images"))
m.Use(DB())
m.Use(render.Renderer(render.Options{...}))
// No need for an anonymous function, which just adds clutter
m.Get("/wishes/all", GetAllWishes)
// Same goes for here
m.Post("/wishes/new", PostWish)
m.Run()
}
PS: I've fixed the formatting of your code, as it has a lot of unnecessary spacing before/after parenthesis. Make sure to use gofmt, which is included with the Go install and can be hooked into most popular editors.
I want to extend the regexp from the Go standard library to be able to define my own methods. I use the following struct:
type RichRegexp struct {
*regexp.Regexp
}
As you can see, this struct contains nothing but the wrapped regexp.Regexp. So I wonder whether I could replace this with a simple type declaration like this:
type RichRegexp regexp.Regexp
But how should I write the following func then?
func Compile(expression string) (*RichRegexp, error) {
regex, err := regexp.Compile(expression)
if err != nil {
return nil, err
}
return &RichRegexp{regex}, nil // How to do this?
}
I tried to convert regexp.Regexp to my RichRegexp but it didn't compile. What is the general pattern to return a custom type which wraps a underlying type?
You can use a conversion, but in this case it is necessary, that your type definition is not a pointer:
type MyRegexp *regexp.Regexp // Doesn't work
This is backed by the spec:
The receiver type must be of the form T or *T where T is a type name.
The type denoted by T is called the receiver base type; it must not be
a pointer or interface type and it must be declared in the same
package as the method. The method is said to be bound to the base type
and the method name is visible only within selectors for that type.
However, you can do this:
type MyRegexp regexp.Regexp
As you're handling values now, you can do the following:
x := regexp.MustCompile(".*")
y := MyRegexp(*x)
And you have your own regexp type.
Full code at play: http://play.golang.org/p/OWNdA2FinN
As a general pattern, I would would say:
If it's unlikely to change and you don't need to store arbitrary values, use
a type conversion.
If you need to store values along with your embedded type, use a struct.
If your code is likely to change and needs to support large varieties of things,
define an interface and don't use embedding / type conversion.
package main
import (
"regexp"
)
type RichRegexp regexp.Regexp
func Compile(expression string) (*RichRegexp, error) {
regex, err := regexp.Compile(expression)
if err != nil {
return nil, err
}
return (*RichRegexp)(regex), nil
}
func main() {
Compile("foo")
}
Also here: http://play.golang.org/p/cgpi8z2CfF