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:
What is the '...' ?
What does ...interface{} mean?
Thank you very much
This isn't exactly specific to go, so unlike the other answerers I'll go the more general route.
On Variable Arguments (...)
... 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:
increase in memory consumption,
decrease in readability,
decrease in code security.
I'll leave it up to you to look up why from the resources above.
On the Empty Interface (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.
Now back to Go's Empty Interface
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.
A Quick Comparison with Other Languages
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);
The documentation directly answers to your question. Here is the link and the related part:
http://golang.org/doc/effective_go.html
The signature of Printf uses the type ...interface{} for its final argument to specify that an arbitrary number of parameters (of arbitrary type) can appear after the format.
func Printf(format string, v ...interface{}) (n int, err error) {
Within the function Printf, v acts like a variable of type []interface{} but if it is passed to another variadic function, it acts like a regular list of arguments. Here is the implementation of the function log.Println we used above. It passes its arguments directly to fmt.Sprintln for the actual formatting.
// 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)
}
We write ... after v in the nested call to Sprintln to tell the compiler to treat v as a list of arguments; otherwise it would just pass v as a single slice argument.
The Go documentation is pretty good and the Language specification is really well written and understandable. Why not have a look?
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 in your browser and looking for ... and interface{} will enlighten you.
Related
Is there a way to use the reflection libraries in Go to go from the name of a type to its Type representation?
I've got a library where the user needs to provide Type representations for some code generation. I know it must be possible (in a sense) because they can just create a variable of that type and call the TypeOf function, but is there a way to circumvent this and just get representation from the name?
The question is not quite explicit, it can be interpreted in 2 ways, to one of which the answer is no, not possible; and the other to which the answer is yes, it's possible.
At runtime
If the type name is provided as a string value, then at runtime it's not possible as types that are not referred to explicitly may not get compiled into the final executable binary (and thus obviously become unreachable, "unknown" at runtime). For details see Splitting client/server code. For possible workarounds see Call all functions with special prefix or suffix in Golang.
At "coding" time
If we're talking about "coding" time (source code writing / generating), then it's possible without creating / allocating a variable of the given type and calling reflect.TypeOf() and passing the variable.
You may start from the pointer to the type, and use a typed nil pointer value without allocation, and you can navigate from its reflect.Type descriptor to the descriptor of the base type (or element type) of the pointer using Type.Elem().
This is how it looks like:
t := reflect.TypeOf((*YourType)(nil)).Elem()
The type descriptor t above will be identical to t2 below:
var x YourType
t2 := reflect.TypeOf(x)
fmt.Println(t, t2)
fmt.Println(t == t2)
Output of the above application (try it on the Go Playground):
main.YourType main.YourType
true
In the Go language specification its said things which needs to be exported outside package must starts with capital letter. I am wondering how error interface is exposed outside and can be accessible anywhere even though it starts with small letter unlike other interfaces starts with capital letter like Stringer.
error is a builtin type just like int, bool, string etc. I guess you've never wondered why int is available despite starting with a lowecased letter.
Builtin types are predeclared identifiers, they are implicitly declared in the universe block and so available everywhere without any imports or qualifiers.
error is a special case, defined in the language spec:
The predeclared type error is defined as
type error interface {
Error() string
}
It is the conventional interface for representing an error condition, with the nil value representing no error. For instance, a function to read data from a file might be defined:
func Read(f *File, b []byte) (n int, err error)
As historical trivia, in a pre-release version of Go, it was part of a standard library package, but this lead to a dependency nightmare, so they made it a special case.
I've looked in the documentation and couldn't find this info.
Given a struct, is it possible to implement a method (say, func (k Koala) String() string) that will automatically be used by the fmt.Print family when printing a struct?
Maybe there's an interface somewhere, but I didn't find it.
Yes, it's called fmt.Stringer()
Stringer is implemented by any value that has a String method, which defines the “native” format for that value. The String method is used to print values passed as an operand to any format that accepts a string or to an unformatted printer such as Print.
type Stringer interface {
String() string
}
The *print* functions don't accept a Stringer() interface themselves because fmt.Println("foo") and fmt.Println(someStringer) are equally valid. I recommend you go through the print.go source code to see exactly how this works, but in brief the *print* functions:
accept an interface{};
check if it's a built-in type (e.g. string, int, etc.) and format it accordingly if it is;
check if the type has a .String() method and use that if it exists.
The precise logic is a bit more involved. As mentioned, I encourage you to go through the source code yourself. It's all just plain readable Go.
Why doesnt this give a compile error, is it a bug in golang or do I miss something?
intPadded := fmt.Sprintf("%09d", "i am a string" )
fmt.Println("bah" + intPadded)
when executed it gives
bah%!d(string=i am a string)
It's your bug. The compiler can only check that the fmt.Sprintf arguments have the proper type; all types implement the empty interface. Use the Go vet command.
func Sprintf
func Sprintf(format string, a ...interface{}) string
Sprintf formats according to a format specifier and returns the
resulting string.
Interface types
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.
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{}
Command vet
Vet examines Go source code and reports suspicious constructs, such as
Printf calls whose arguments do not align with the format string.
"If an invalid argument is given for a verb, such as providing a string to %d, the generated string will contain a description of the problem" per http://golang.org/pkg/fmt/
It doesn't give a compile-time error because there is no compile-time error. fmt.Sprintf() is defined as taking ...interface{} for its last argument, which is valid for any sequence of types. The checking is done only at runtime.
Ok, I have to admit, I don't really use Go very much at all, but I did just observe something that strikes me as odd for a language that strives for minimality and all that good stuff as Go does. I would be surprised if there isn't a legitimate rationale behind it, so that's what I'm looking for.
So when you have a method, you define it like this:
func (s *SomeStruct) Foo(x int) { }
but why have an extra parameter list just for the "receiver", as I think it's called? Would it not be a simpler and more elegant design to just do
func Foo(s *SomeStruct, x int) { }
and then have s.Foo(5) just be translated to a call to a function Foo(s, 5)?
Methods are fundamentally special and different from regular functions.
Methods must live in the same package as the receiver type.
Methods are used to satisfy interfaces.
Receiver parameters are the only parameters which may be overloaded.
When anonymous struct fields have methods, those methods are "inherited".
With your proposal, the line between a function and a method becomes very blurry and it's difficult to figure out how to resolve the above issues.
That said, I think it would be really interesting to design a language with multimethods and interfaces. However, that language would not be Go.
Your question correctly points out that any method is a function. However, the Go language needs to be able to explicitly distinguish between methods and functions. The reason for this is that methods have features that functions do not have. The choice of whether Foo is a function or a method needs to be made by the programmer.
Go's minimalism means that the language defines only a small set of keywords. The Go authors could have chosen a new keyword, such as method, to distinguish methods from functions:
method Foo(receiver *T, arg1 int) {} // 'Foo' is a method, not a function
Looking around the Go programming language, we can see that the philosophy is to reuse already existing keywords rather than to have a separate keyword for each occasion. The for keyword is a good example of this approach:
for {} // Infinite loop
for a>0 {a--} // A while-do loop
for i := range channel {} // Receive values from a channel
for i:=0; i<N; i++ {} // C-style for loop
The basic idea is that for the parser (and Go programmers) to distinguish the various types of for loops from each other, there is no need to introduce a new keyword if the options can be distinguished by the syntax of what comes after the for keyword: ; := range identifier ..., their sequential order, and their presence/absence.
The func keyword follows the same pattern. It can be used in multiple contexts:
function definitions: func f() {}
function types: type F func(int) int
method definitions: func (t T) SomeMethod() {}
closures: { ...; go func(){c<-1}(); ...}
From minimalism viewpoint, a single func keyword is both simpler and more elegant than having multiple keywords.
The extra parameter list just for the receiver
func (t *T) Foo(x int) {}
enables the parser to distinguish methods and functions:
func IDENTIFIER ... This is going to be a function
func ( ... This is going to be a method
Thus, the parser (as well as Go programmers) can make the distinction based on whether the func keyword is followed by an identifier or by (.
The proposed replacement is not semantically identical to the current state, i.e. it's not a syntactic change only. It will [attempt to] automagically create methods of any [local package] type that happens to be the first parameter of a function. Considering how fundamental method sets are wrt to Go's concept of automatic interface satisfaction rules, this will quite probably lead to a big big mess.
In short, I think such change to the Go language improves nothing while damaging a lot of it's nice features related to methods and interfaces.
Probably because go isn't Python.
Also, because a function declared this way is not a method.
You cannot declare a method outside the object package. So I guess the main rationale in the syntax difference between methods and functions is to be able to differentiate them.