6

http://golang.org/pkg/log/の func Printf のソースを参照しています。

func Printf(format string, v ...interface{})
Printf calls Output to print to the standard logger. Arguments are handled in the manner of fmt.Printf.

2 つの質問があります。

  1. 「...」とは何ですか?
  2. ...interface{} とはどういう意味ですか?

どうもありがとうございました

4

3 に答える 3

7

これは具体的な方法ではないので、他の回答者とは異なり、より一般的な方法を使用します。

可変引数について ( ...)

...ここでは、「省略記号」と呼ばれ、関数が可変数の引数を受け取ることができることを示します。これは、varargs (または var-args、または他のスペル) と呼ばれることがよくあります。これは可変個引数関数と呼ばれます。

次の署名によると、それは単に次のことを意味します。

func Printf(format string, v ...interface{}) (n int, err error) {}

Printftype の最初の引数が必要stringで、次に type の 0 から N 個の引数が必要ですinterface{}。そのタイプについては、次のセクションで詳しく説明します。

任意の数の引数を指定できる機能は非常に便利に思えますが、トピックから外れるリスクがあるため、ここではあまり詳細には触れませんが、言語の実装によってはいくつかの注意事項があります。

  • メモリ消費量の増加、
  • 読みやすさの低下、
  • コードのセキュリティが低下します。

上記のリソースから理由を調べるのはあなたに任せます。

空のインターフェイス ( interface{})

この構文ビットはもう少し Go 固有ですが、ヒントは名前にあります: interface.

インターフェイス (または Go のパラダイムに近いプロトコル) は、他のオブジェクトが準拠するための契約を定義する型です。コンピューティングのインターフェイスに関するこのウィキペディアの記事によると(太字は強調、斜体は修正):

オブジェクト指向言語では、**「インターフェース」という用語は、データを含まないが、メソッドとして定義された動作を公開する抽象型を定義するためによく使用されます。そのインターフェースに対応するすべてのメソッドを持つクラスは、そのインターフェースを実装すると言われています。さらに、クラスは[一部の言語では])複数のインターフェイスを実装できるため、同時に異なる型になる可能性があります。

したがって、インターフェースは型定義です。(関数またはメソッド呼び出しで)オブジェクトを交換できる場所ならどこでも、交換するオブジェクトの型を、特定の class ではなく、インターフェイスの観点から定義できます。これにより、後のコードで異なるオブジェクト タイプを交換する同じ関数を使用できます。_[なりたい]_ 一般的で再利用可能。

Go の Empty Interface に戻ります。

Go は強く型付けされた言語であり、現在の (1.1) 言語仕様では gollows として記述されているInterface Typesを含むいくつかの組み込み型があります。

インターフェイス タイプは、そのインターフェイスと呼ばれるメソッド セットを指定します。インターフェイス型の変数は、インターフェイスの任意のスーパーセットであるメソッド セットを持つ任意の型の値を格納できます。このようなタイプは、インターフェースを実装すると言われています。

Printfさらに下に、の署名に見られる構造を紹介しますinterface{}(私の太字は強調):

型は、そのメソッドの任意のサブセットを含む任意のインターフェイスを実装するため、いくつかの異なるインターフェイスを実装できます。たとえば、すべての型は空のインターフェイスを実装します

interface{}

これは基本的に、任意の型を「空のインターフェイス」として表すことがPrintfできるため、これらの varargs に対して任意の型の変数を受け入れることができることを意味します。


他の言語との簡単な比較

歴史的に、名前printfは C 関数と同じ名前のバイナリに由来し、printf「フォーマットされた印刷」を意味しますが、初期の言語には可変個引数の出力関数があり、可変個引数関数は他の多くのシナリオで使用されます。ただし、printfそのような用途の代表的な例と見なされることがよくあります。Cでの署名は次のとおりです。

int printf(const char *format, ...);

その実用性の結果として、varargs とprintfのおなじみの顔がほとんどの言語に現れます...

Java ではprintf、特にPrintStreamクラスから、複数の形式で存在します。

public PrintStream printf(String format, Object... args)

他の言語の中には、変数引数の指定を気にせず、それを暗黙的にするものがあります。たとえば、JavaScript では、arguments関数内の特別な変数により、プロトタイプと一致するかどうかに関係なく、関数に渡される任意の引数にアクセスできます。

メソッドはconsole.log()に似た例になりますがprintf、次の疑似署名はわかりやすくするために展開されています (ただし、実際には単純に を使用していますarguments)。

console.log(obj1 [, obj2, ..., objN);
console.log(msg [, subst1, ..., substN);
于 2013-09-05T07:47:21.547 に答える
4

ドキュメントはあなたの質問に直接答えます。リンクと関連部分は次のとおりです。

http://golang.org/doc/effective_go.html

Printf の署名は、最後の引数に型 ...interface{} を使用して、任意の数の (任意の型の) パラメーターをフォーマットの後に表示できることを指定します。

func Printf(format string, v ...interface{}) (n int, err error) {

関数 Printf 内では、v は []interface{} 型の変数のように機能しますが、別の可変引数関数に渡されると、通常の引数リストのように機能します。上記で使用した関数 log.Println の実装を次に示します。実際の書式設定のために、引数を fmt.Sprintln に直接渡します。

// Println prints to the standard logger in the manner of fmt.Println.
func Println(v ...interface{}) {
    std.Output(2, fmt.Sprintln(v...))  // Output takes parameters (int, string)
}

Sprintln のネストされた呼び出しで v の後に ... を記述して、コンパイラに v を引数のリストとして扱うように指示します。それ以外の場合は、単一のスライス引数として v を渡すだけです。

于 2013-09-05T06:39:16.790 に答える
3

Go のドキュメントは非常に優れており、言語仕様は非常によく書かれており、理解できます。見てみませんか?

http://golang.org/ref/spec#Function_types

http://golang.org/ref/spec#Passing_arguments_to_..._parameters

http://golang.org/ref/spec#Interface_types

ブラウザで Ctrl-F を探して、あなた...interface{}啓発します。

于 2013-09-05T07:25:17.563 に答える