20

I have the following code:

type FWriter struct {
    WriteF func(p []byte) (n int,err error)
}

func (self *FWriter) Write(p []byte) (n int, err error) {
    return self.WriteF(p)
}

func MyWriteFunction(p []byte) (n int, err error) { 
    // this function implements the Writer interface but is not named "Write"
    fmt.Print("%v",p)
    return len(p),nil
}

MyFWriter := new(FWriter)
MyFWriter.WriteF = MyWriteFunction
// I want to use MyWriteFunction with io.Copy
io.Copy(MyFWriter,os.Stdin)

What I am trying to do is to create a Writer interface to wrap MyWriteFunction because it is not named "Write" and I can't use it with anything that requires a "Writer" interface.

This code won't work as it complains:

method MyWriterFunction is not an expression, must be called

What am I doing wrong here? How can I set WriteF to be MyWriteFunction?

Note: I simplified this problem as much as I can and in reality I have a struct which has MyWriteFunction AND a normal Write function so it gets a little bit complicated... (Also if there is a better way to solve this problem of mine then I'll be glad to hear it!)

Thanks!!


EDIT: I have notice my typo and fixed it (MyWriterFunction --> MyWriteFunction).

I think I over-simplified the question in a manner that mislead you of my original intent. Following the Anonymous comment and peterSO kind comments I have re-created the error to better demonstrate my problem:

package main

import (
    "fmt"
    "io"
    "strings"
)

type ProxyWrite interface {
    Write(p []byte) (n int, err error)
    SpecialWrite(p []byte) (n int, err error)
}

type Implementer struct {
    counter int
}

func (self Implementer) Write(p []byte) (n int, err error) {
    fmt.Print("Normal write: %v", p)
    return len(p),nil
}

func (self Implementer) SpecialWrite(p []byte) (n int, err error) {
    fmt.Print("Normal write: %v\n", p)
    fmt.Println("And something else")
    self.counter += 1
    return len(p),nil
}


type WriteFunc func(p []byte) (n int, err error)

func (wf WriteFunc) Write(p []byte) (n int, err error) {
    return wf(p)
}

func main() {
    Proxies := make(map[int]ProxyWrite,2)
    Proxies[1] = new(Implementer)
    Proxies[2] = new(Implementer)

    /* runs and uses the Write method normally */
    io.Copy(Proxies[1], strings.NewReader("Hello world"))
    /* gets ./main.go:45: method Proxies[1].SpecialWrite is not an expression, must be called */
    io.Copy(WriteFunc(Proxies[1].SpecialWrite), strings.NewReader("Hello world"))
}

I hope it clarifies what I meant to present on the first attempt.

Any thoughts?

bad_coder
  • 11,289
  • 20
  • 44
  • 72
user340495
  • 321
  • 1
  • 4
  • 11
  • 2
    What version of go are you using? Methods as values don't appear until 1.1. And this code works fine on the playground... http://play.golang.org/p/AmRi_fujPw – Paul Hankin Dec 22 '13 at 16:18

2 Answers2

19

There's a typo in your code, but wrapping the func into a struct is unnecessary anyway. Instead, you can just define a WriteFunc type that wraps a function, and that you can define a Write method on. Here's a full example.

package main

import (
    "fmt"
    "io"
    "strings"
)

type WriteFunc func(p []byte) (n int, err error)

func (wf WriteFunc) Write(p []byte) (n int, err error) {
    return wf(p)
}

func myWrite(p []byte) (n int, err error) {
    fmt.Print("%v", p)
    return len(p), nil
}

func main() {
    io.Copy(WriteFunc(myWrite), strings.NewReader("Hello world"))
}
Paul Hankin
  • 54,811
  • 11
  • 92
  • 118
  • Hi, this answer is very nice and works well. I have edited the question to better explain what I originally meant. if you would mind taking a look that would be awesome. thanks! – user340495 Dec 22 '13 at 16:08
7

Fix MyWriterFunction/MyWriteFunction typo. For example,

package main

import (
    "fmt"
    "io"
    "os"
)

type FWriter struct {
    WriteF func(p []byte) (n int, err error)
}

func (self *FWriter) Write(p []byte) (n int, err error) {
    return self.WriteF(p)
}

func MyWriteFunction(p []byte) (n int, err error) {
    // this function implements the Writer interface but is not named "Write"
    fmt.Print("%v", p)
    return len(p), nil
}

func main() {
    MyFWriter := new(FWriter)
    MyFWriter.WriteF = MyWriteFunction
    // I want to use MyWriteFunction with io.Copy
    io.Copy(MyFWriter, os.Stdin)
}
peterSO
  • 158,998
  • 31
  • 281
  • 276
  • hey, Thanks for the kind answer, it indeed fixed the presented problem, but I have now fixed my question to better describe the problem, Thanks for the kind answer. – user340495 Dec 22 '13 at 16:06