48580


`io.Discard` の
[ソースコード](https://github.com/golang/go/blob/master/src/io/ioutil/ioutil.go#L122)
を見ていて疑問点が２点あります。

**Q1.**

Goの基本的な文法に関する質問になってしまいますが、以下は何を意図しているのでしょうか。

[code]

    // devNull implements ReaderFrom as an optimization so io.Copy to
    // ioutil.Discard can avoid doing unnecessary work.
    var _ io.ReaderFrom = devNull(0)
    
[/code]

コード内のコメントから、`devNull` が `io.Copy`
で使われる場合に備えて「`io.ReaderFrom`インタフェースを実装している」ことを宣言しているのだろうとは思うのですが、一体どういう理屈で上記がインタフェースを実装していることの宣言になるのでしょうか（そういう文法なのだと言われるとそれまでなのですが…）。

**Q2.**

以下のように `WriteString` 関数が定義されていますが、

[code]

    func (devNull) WriteString(s string) (int, error) {
        return len(s), nil
    }
    
[/code]

そもそも `io.Discard` は `ioutil` パッケージに `io.Writer` 型の変数として宣言されているため、

[code]

    // Discard is an io.Writer on which all Write calls succeed
    // without doing anything.
    var Discard io.Writer = devNull(0)
    
[/code]

例えば以下のように呼び出すことはできません。

[code]

    ioutil.Discard.WriteString("hoge")
    // ビルドエラー：
    // ioutil.Discard.WriteString undefined 
    // (type io.Writer has no field or method WriteString)
    
[/code]

一体なんのために存在しているのでしょうか。


CC BY-SA 4.0
2018-09-20T02:00:40.783
48570
2018-09-21T06:43:26.013
2018-09-21T06:43:26.013
3054
19759
question
go
使用しない変数をインターフェース型で宣言する意味と、io.Discard に関する質問


自己回答です。（metropolisさんのコメントより）

**A1.**

`devNull` が `io.ReaderFrom` インタフェースを実装していることを、コンパイル時にチェックさせることが目的。

型が `io.ReaderFrom` である何らかの変数を宣言して、それに `devNull` を代入することができるのであれば、`devNull` は
`io.ReaderFrom`
インタフェースを実装している、ということになる。また「なんらかの変数」は宣言後に使用しないので、ブランク識別子（アンダースコア）にしている。チェックするだけなので、この行を削除してもコンパイルできるし動作も変わらない。

**A2.**

同パッケージの `stringWriter` インタフェースの実装。  
`stringWriter` インタフェースは、`io.WriteString` 関数や `io.multiWriter.WriteString`
関数の中で型アサーションがokであれば委譲される。

例えば以下の時、内部では `Discard` の `WriteString` 関数が使われる。

[code]

    io.WriteString(ioutil.Discard, "hogehoge fugafuga")
    
[/code]


CC BY-SA 4.0
2018-09-20T06:26:00.320
48580
2018-09-20T06:26:00.320
19759
48570
answer