web-dev-qa-db-ja.com

構造体の一部としてのGolang関数ポインター

私は次のコードを持っています:

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)

私がやろうとしているのは、MyWriteFunctionをラップするWriterインターフェースを作成することです。これは、「Write」という名前ではなく、「Writer」インターフェースを必要とするものでは使用できないためです。

このコードは文句を言うと機能しません:

メソッドMyWriterFunctionは式ではないため、呼び出す必要があります

ここで何が悪いのですか? WriteFMyWriteFunctionに設定するにはどうすればよいですか?

注:私はこの問題をできる限り簡略化しましたが、実際にはMyWriteFunctionと通常の書き込み関数を含む構造体があるため、少し複雑になります...(より良い方法がある場合も私のこの問題を解決したら、私はそれを聞いてうれしいです!)

ありがとう!!


編集:タイプミスに気づき、修正しました(MyWriterFunction-> MyWriteFunction)。

私は元の意図を誤解させるような方法で質問を単純化しすぎたと思います。匿名コメントとpeterSO親切なコメントに続いて、問題をより明確に示すためにエラーを再現しました。

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"))
}

私が最初の試みで提示するつもりだったことを明確にしたいと思います。

何かご意見は?

17
user340495

コードにタイプミスがありますが、関数を構造体にラップすることはとにかく不要です。代わりに、関数をラップするWriteFunc型を定義するだけで、Writeメソッドを定義できます。ここに完全な例があります。

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"))
}
19
Paul Hankin

MyWriterFunction/MyWriteFunction typoを修正します。例えば、

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)
}
6
peterSO