I'm trying to hold a function that will return new instances of a type implementing a particular interface in a struct. Here's a stripped down example:
package main
type Adder interface {
Add(Adder)
Val() int
}
type NewAdder func() Adder
type number int
type NewHolder struct {
newFunc NewAdder
}
func (me *number)Add(it Adder) {
*me += number(it.Val())
}
func (me *number)Val() int {
return int(*me)
}
func newAdder() *number {
return (*number)(new(int))
}
func main() {
var holder NewHolder
holder.newFunc = NewAdder(newAdder)
}
When I try to compile it, it says cannot convert newAdder (type func() *number) to type NewAdder. So what's the go-like way to accomplish my goal?
Here's a Python example of what I'm trying to do, just for reference:
class NewStuffMaker(object):
def __init__(self, new):
self.new = new
def make_new():
return []
obj = NewStuffMaker(make_new)
new_lst = obj.new()
Ideally, I'd like to be able to hold a bunch of these functions (or structs containing the functions and some other data) in a slice. Is that an unreasonable thing to do?
package main
type Adder interface {
Add(Adder)
Val() int
}
type FuncAdder func() Adder
type Holder struct {
FuncAdder
SomeOtherData string
}
type number int
func (n *number) Add(a Adder) {
*n += number(a.Val())
}
func (n *number) Val() int {
return int(*n)
}
func NumberAdder() Adder {
return Adder(new(number))
}
func main() {
var holders []Holder
var holder Holder
holder.FuncAdder = NumberAdder
holder.SomeOtherData = "SomeOtherData"
holders = append(holders, holder)
}
Related
Is there anyway to make a map of function pointers, but functions that take recievers? I know how to do it with regular functions:
package main
func someFunc(x int) int {
return x
}
func main() {
m := make(map[string]func(int)int, 0)
m["1"] = someFunc
print(m["1"](56))
}
But can you do that with functions that take recievers? Something like this (though I've tried this and it doesn't work):
package main
type someStruct struct {
x int
}
func (s someStruct) someFunc() int {
return s.x
}
func main() {
m := make(map[string](someStruct)func()int, 0)
s := someStruct{56}
m["1"] = someFunc
print(s.m["1"]())
}
An obvious work around is to just pass the struct as a parameter, but that's a little dirtier than I would have liked
You can do that using Method Expressions:
https://golang.org/ref/spec#Method_expressions
The call is a bit different, since the method expression takes the receiver as the first argument.
Here's your example modified:
package main
type someStruct struct {
x int
}
func (s someStruct) someFunc() int {
return s.x
}
func main() {
m := make(map[string]func(someStruct)int, 0)
s := someStruct{56}
m["1"] = (someStruct).someFunc
print(m["1"](s))
}
And here's a Go playground for you to test it:
https://play.golang.org/p/PLi5A9of-U
I have an interface named Being, which requires two methods SetValue(v int) and GetValue() int. Then I have a base class Animal implementing it, and further a subclass Cat inherited from Animal.
Following is the code (Go Playground):
package main
import (
"fmt"
)
type Being interface {
SetValue(v int)
GetValue() int
}
type Animal struct {
value int
}
type Cat struct {
Animal
}
func (a Animal) SetValue(v int) {
a.value = v
}
func (a Animal) GetValue() int {
return a.value
}
func MakeCat() Being {
return Cat{}
}
func main() {
cat := MakeCat()
cat.SetValue(1)
fmt.Println(cat.GetValue())
}
However, the output is 0, rather than 1.
If I slightly modify the code to this (Go Playground):
package main
import (
"fmt"
)
type Being interface {
SetValue(v int)
GetValue() int
}
type Animal struct {
value int
}
type Cat struct {
Animal
}
//Change the receiver to a pointer
func (a *Animal) SetValue(v int) {
a.value = v
}
func (a Animal) GetValue() int {
return a.value
}
//Return the pointer
func MakeCat() Being {
cat := Cat{}
return &cat
}
func main() {
cat := MakeCat()
cat.SetValue(1)
fmt.Println(cat.GetValue())
}
where the modifications are marked by comments, the code behaves correctly, and output 1.
I cannot think of the reason of such phenomena, could anyone help?
Is it possible to generate an interface or method set of a struct at runtime with reflection?
For example:
type S struct {
a int
}
func (s *S) Fn(b int) int {
return s.a + b
}
type I interface {
Fn(a int) int
}
func main() {
var x I = &S{a: 5}
fmt.Printf("%#v\n", x.Fn)
fmt.Printf("%#v\n", reflect.TypeOf(x).Method(0))
var y I
y.Fn = x.Fn // This fails, but I want to set y.Fn at runtime.
fmt.Printf("%#v\n", reflect.TypeOf(y).Method(0))
}
https://play.golang.org/p/agH2fQ4tZ_
To clarify, I'm trying to build a middleware library so interface I contains the http handlers and I want to wrap each hander with some sort of req/response logging so I need to return a new interface I where each function in new Interface I wraps the original + some logging.
Here's how to handle this for interfaces I and J.
type I interface { Fn1(a int) int }
type J interface { Fn2(a int) int }
type Y struct { // Y implements I by calling fn
fn func(a int) int
}
func (y Y) Fn1(a int) int { return y.fn(a) }
type Z struct { // Z implements J by calling fn
fn func(a int) int
}
func (z Z) Fn2(a int) int { return y.fn(a) }
var y I = Y{fn: x.Fn}
var z J = Z{fn: x.Fn}
There's no need to use reflection.
playground example
type FuncPtr func(int) int
func Foo(i int) { return i * i }
type Events struct {
SomeFunc FuncPtr
}
type Top struct {
events Events
}
func (self *Top) initEvents() {
// This change works within this function, but
// doesn't stick around after this method returns.
self.events.SomeFunc = Foo
}
func main() {
var t := Top{}
t.initEvents()
t.events.SomeFunc == nil // True: Change in initEvents() doesn't stick
}
How can I make the change inside initEvents() method persist? That is, I want to change the value of the function reference Top::Events::SomeFunc within the initEvents() method and for that change to stick once the initEvents() method returns.
The code you have works with some minor corrections to make it compileable.
There's no package declaration at the top
You're not specifying an integer return type for your function Foo
I've included a full example of the code below for convenience and if you want to run this yourself you can do it at: https://play.golang.org/p/Ngu8FFiGrI
package main
import(
"fmt"
)
type FuncPtr func(int) int
func Foo(i int) int {
return i*i
}
type Events struct {
SomeFunc FuncPtr
}
type Top struct {
events Events
}
func (self *Top) initEvents() {
// This change works within this function, but
// doesn't stick around after this method returns.
self.events.SomeFunc = Foo
}
func main() {
var t = Top{}
t.initEvents()
if t.events.SomeFunc == nil {
fmt.Println("SomeFunc not set")
}
fmt.Println("6^2 =",t.events.SomeFunc(6))
}
I have following code in Go:
type Foo struct { Id int }
type Bar struct { Id int }
func getIdsFoo(foos []Foo) {
ids = make([]int, len(foos))
// iterate and get all ids to ids array
}
func getIdsBar(bars []Bar) {
ids = make([]int, len(bars))
// iterate and get all ids to ids array
}
Is there a clever way to create a function getIds([]Idable) that can take any struct that have method GetId() implemented?
type Identifiable interface {
GetId() int
}
func GatherIds(ys []Identifiable) []int {
xs := make([]int, 0, len(ys))
for _, i := range ys {
xs = append(xs, i.GetId())
}
return xs
}
sort uses a design patter that might help you.
Create a function that works on an slice-like interface. Then create new types based off of a slice of your concrete types.
Hopefully, the code is more clear than my description. http://play.golang.org/p/TL6yxZZUWT
type IdGetter interface {
GetId(i int) int
Len() int
}
func GetIds(ig IdGetter) []int {
ids := make([]int, ig.Len())
for i := range ids {
ids[i] = ig.GetId(i)
}
return ids
}
type Foo struct{ Id int }
type Bar struct{ Id int }
type FooIdGetter []Foo
func (f FooIdGetter) GetId(i int) int {
return f[i].Id
}
func (f FooIdGetter) Len() int {
return len(f)
}
type BarIdGetter []Bar
func (b BarIdGetter) GetId(i int) int {
return b[i].Id
}
func (b BarIdGetter) Len() int {
return len(b)
}
func main() {
var f = []Foo{{5}, {6}, {7}}
var b = []Bar{{10}, {11}, {12}}
fmt.Println("foo ids:", GetIds(FooIdGetter(f)))
fmt.Println("bar ids:", GetIds(BarIdGetter(b)))
}
There is still a bit more boilerplate than is pleasant, (Go generics... someday). It's greatest advantage is that new methods do not need to be added to Foo, Bar, or any future type you may need to work with.