I am referring to the source of func Printf on http://golang.org/pkg/log/
func Printf(format string, v ...interface{})
Printf calls Output to print to the standard logger. Arguments are handled in the manner of fmt.Printf.
I have two questions:
Thank you very much
This isn't exactly specific to go, so unlike the other answerers I'll go the more general route.
...
)...
here, called "ellipsis", indicates the function can receive a variable number of arguments, often referred to as varargs (or var-args, or other spellings). This is called a variadic function.
It simply means that, according to the following signature:
func Printf(format string, v ...interface{}) (n int, err error) {}
Printf
will expect a first argument of type string
, and then between 0 and N arguments of type interface{}
. More on that type in the next section.
While the ability to supply any number of arguments can seem very handy, and without going into too much details here for risk of going off-topic, it comes with a few caveats depending on the implementation in the language:
I'll leave it up to you to look up why from the resources above.
interface{}
)This syntax bit is a bit more Go-specific, but the hint is in the name: interface
.
An interface (or closer to Go's paradigm, a protocol), is a type that defines a contract for other objects to comply to. According to this Wikipedia article on interfaces in computing (emphasis in bold mine and corrections in italics mine):
In object-oriented languages, **the term "interface" is often used to define an abstract type that contains no data, but exposes behaviors defined as methods. A class having all the methods corresponding to that interface is said to implement that interface. Furthermore, a class can [in some languages]) implement multiple interfaces, and hence can be of different types at the same time.
An interface is hence a type definition; anywhere an object can be exchanged (in a function or method call) the type of the object to be exchanged can be defined in terms of an interface instead of a specific class. This allows later code to use the same function exchanging different object types; _[aiming to be]_ generic and reusable.
Go is a strongly typed language, with several built-in types, including Interface Types, which they describe as gollows in the current (1.1) language specifications:
An interface type specifies a method set called its interface. A variable of interface type can store a value of any type with a method set that is any superset of the interface. Such a type is said to implement the interface.
Futher down, you are introduced to the construct you see in Printf
's signature, interface{}
(emphasis in bold mine):
A type implements any interface comprising any subset of its methods and may therefore implement several distinct interfaces. For instance, all types implement the empty interface:
interface{}
This basically means that any type an be represented as the "empty interface", and thus that Printf
can accept variables of any type for these varargs.
Historically, the name printf
comes from the C function and from the binary of the same name, printf
meaning "print formatted", though there were variadic print functions in earlier languages, and variadic functions are used for many other scenarios. However, printf
is often considered the prime example of such a use. It's signature in C is:
int printf(const char *format, ...);
As a result of their practicality, varargs and printf
's familiar face show up in most languages...
In Java, printf
exists under multiple forms, notably from the PrintStream
class:
public PrintStream printf(String format, Object... args)
Some other langauges do not bother with specifying variable arguments and make it implicit, for instance in JavaScript, the arguments
special variable within a function allows to access any arguments passed to a function, whether they match the prototype or not.
The console.log()
method would be an example similar to printf
, with the following pseudo-signature expanded for clarity (but actually simply using arguments
):
console.log(obj1 [, obj2, ..., objN);
console.log(msg [, subst1, ..., substN);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With