Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Golang function pointer as a part of a struct

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?

like image 815
user340495 Avatar asked Dec 22 '13 11:12

user340495


People also ask

Can you have a function pointer in a struct?

Function pointers can be stored in variables, structs, unions, and arrays and passed to and from functions just like any other pointer type. They can also be called: a variable of type function pointer can be used in place of a function name.

Can a struct contain a function Golang?

Any real-world entity which has some set of properties or fields can be represented as a struct. As we know that in Go language function is also a user-defined type so, you are allowed to create a function field in the Go structure.

What is pointer to struct in Golang?

Pointers in Golang is also termed as the special variables. The variables are used to store some data at a particular memory address in the system. You can also use a pointer to a struct. A struct in Golang is a user-defined type which allows to group/combine items of possibly different types into a single type.


1 Answers

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"))
}
like image 62
Paul Hankin Avatar answered Oct 16 '22 12:10

Paul Hankin