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.
Related
Note: I'm editing this question to a concrete example of why I want to do this, which is why some of the answers might no longer make sense in context.
I am writing a bit of code that passes data from an input. The data is in the form of tags that have an identifier of what kind of data they contain and then the data.
Unfortunately I have no control over the input and don't know in advance what tags will be in it, one might be an int another might be a string, yet another might be an array of ints.
The problem arises when I need to handle all tags like the same type, for instance if I have a slice of tags, of a function that either accepts or returns a tag.
The solutions I have so far seen to this is to define the slices/functions with an empty interface which would allow me to do so, however that is kinda undesirable as it would not tell anything to other people using the package about what types are expected and also kinda defies the point of having a typed language in the first place.
Interfaces does however seem to be the solution here, and i would love to have a Tag interface to pass around, that does require though that I define methods on them, and there are really no methods they need.
My current solution looks like this
type Tag interface{
implementTag()
}
type TagInt int
func (tag TagInt) implementTag() {}
type TagString string
func (tag TagInt) implementTag() {}
While this does indeed work and solves my problem, having to define dummy methods just for that feels very wrong.
So my question sums up in this: Are there any way that I can define that something is a Tag without having to define dummy methods?
And now want to make a slice that can hold both t1 and t2 but nothing else.
You cannot do that. Sorry.
What I would do in your scenario is accept any type in the parameters with an empty interface then use a type assertion inside to confirm that it's the type that you want.
if t1, ok := interfaceInput.(t1); !ok{
// handle it being the wrong type here
return
}
Also if you want the tight coupling between a data type and it's method, namely an object, what's so wrong with having it be a method of the object?
You can use []interface{} for a "slice of any type" but then it's up to you to use type assertions and/or type switches to discover the actual runtime types of that slice's members.
Learn more about empty interfaces in the Tour of Go
And now want to make a slice that can hold both t1 and t2 but nothing
else.
This is quite an unusual requirement and you're unlikely to need this in Go. But you could also do your own discriminated union with:
type item struct {
typeSelector int
t1Value t1
t2Value t2
}
And then use []item, checking typeSelector at runtime to see which value is populated.
Alternatively you could even use *t1 and *t2 and have nil signify "no value in this field".
I started using Golang recently and stumbled across a problem:
I have two structs, human and alien, which are both based on the creature struct. I want to initialize one of them based on the value of the isAlien boolean inside of an if-statement.
Using the human := human{} notation or the alien equivalent inside the if blocks to initialize, the instances aren't accessible from outside of the if-statement.
On the other hand, the usual solution of declaring the type and the name of the variable before the if-statement and initializing the variable inside the if-statement doesn't work, because there two are different types:
var h human //use human or alien here?
if isAlien {
h = alien{} //Error: incompatible types
} else {
h = human{}
}
//same when swapping human with alien at the declaration
I know that I could just declare both types before the if-statement but that solution doesn't seem elegant to me.
Is there some obvious solution that I'm missing here?
As you noted, the problem is clearly represented by this statement:
var h human //use human or alien here?
If you plan to use that h variable there after creating the objects, then the type of h must be one that can accept either a human or alien as a value.
The way to do this in Go is by using an ìnterface that both alien and human can fulfil.
So you should declare an interface like:
type subject interface {
// you should list all functions that you plan to use on "h" afterwards
// both "human" and "alien" must implement those functions
}
Then:
var h subject
Will do the trick.
So, I'm going to go out on a limb and say you're probably thinking about this the wrong way.
The first question that occurs to me looking at your example is: what's the return type of this function? In other words, what signature do you need h to be? If alien has an embedded struct creature (which seems to be the inheritance pattern you're trying to follow), and you return a human from your function after declaring h to be a creature, anything that consumes your function will only know that it's dealing with a creature, so there's no point in declaring it a human or an alien in the first place.
I suspect that what you really want to be doing is moving away from concrete structs here and instead using interfaces. In that world, you'd have a creature interface, and both human and alien would satisfy the creature interface. You wouldn't necessarily know which one you were dealing with downstream, but you'd be able to reliably call creature methods and the appropriate human or alien implementation would be invoked.
How to have a variable whose type is a variable type?
What do I mean by that? I have a python and java background. In both languages I can do things like assigning a class name to variable.
#Python
class A:
def __init__(self):
self.a = "Some Value"
# And asigning the class name to a variable
class_A = A
# And create instance from class A by using class_A
a = class_A()
Is there such a mechanism in go that allows me to do that? I couldn't know where to look at for such things in their documentation. Honestly, generally I don't know what these are called in programming languages.
For example I would like to be able to do:
// For example, what would be the type of myType?
var myType type = int
I will use this mechanism to take "type" arguments. For example:
func Infer(value interface{}, type gotype) {...}
Is there such a mechanism in go that allows me to do that?
The short answer is: No.
The long answer is: This sounds like an XY Problem, so depending on what you're actually trying to accomplish, there may be a way. Jump to the end to see where I address your specific use-case.
I suspect that if you want to store a data type in a variable, it's because you either want to compare some other variable's type against it, or perhaps you want to create a variable of this otherwise unknown type. These two scenarios can be accomplished in Go.
In the first case, just use a type switch:
switch someVar.(type) {
case string:
// Do stringy things
case int:
// Do inty things
}
Semantically, this looks a lot like assigning the type of someVar to the implicit switch comparison variable, then comparing against various types.
In the second case I mentioned, if you want to create a variable of an unknown type, this can be done in a round-about way using reflection:
type := reflect.TypeOf(someVar)
newVar := reflect.New(type).Interface()
Here newVar is now an interface{} that wraps a variable of the same type as someVar.
In your specific example:
I will use this mechanism to take "type" arguments. For example:
func Infer(value interface{}, type gotype) {...}
No, there's no way to do this. And it actually has much less to do with Go's variable support than it does with the fact that Go is compiled.
Variables are entirely a runtime concept. Function signatures (like all other types in Go) are fixed at compilation time. It's therefore impossible for runtime variables to affect the compilation stage. This is true in any compiled language, not a special feature (or lack thereof) in Go.
Is there such a mechanism in go that allows me to do that?
No there is not.
Use the empty interface:
var x, y interface{}
var a uint32
a = 255
x = int8(a)
y = uint8(a)
Playground example
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.
I am new to type safe, and can't figure out how to do following
package main
func test(){
print("In Test")
}
func main(){
a := "test"
a()
}
You might get better answers if you state what you're trying to achieve, as reflection is usually not the best way. But reflect will help if the functions are methods on a type (net/rpc is an example of this).
package main
import (
"fmt"
"reflect"
)
type T struct {}
func (T) Add(x, y int) int {
return x + y
}
func main() {
t := reflect.ValueOf(T{})
m := t.MethodByName("Add")
args := []reflect.Value{reflect.ValueOf(1), reflect.ValueOf(2)}
fmt.Println(m.Call(args)[0].Int())
}
If you were wondering how tools like godoc work, they parse the source rather than use reflection.
Edit: Playground version
A function can not be resolved from a string. However, you can assign a function to a variable.
a := test
a()
You can also put functions (assuming they all have the same signature) into a map:
var func_map := map[string]func() {
"test": test,
}
a := func_map["test"]
a()
Response to first comment by OP (too long to make another comment):
A function is not a "literal". "Literal" has a separate meaning.
Second, Go's runtime reflection does not have a lookup table mapping strings to functions. Even if it did, functions are not linked into the binary unless linked to by other code. Code only called in this method would not be in the binary.
Third, making a mapping manually is not that hard. It provides compile time type safety checks as well as security.
This is not something you should be doing in any language. It is like eval(), you really should not use it because it can be incredibly dangerous and cause unpredictable things to happen.
They don't all have the same signature
If they don't all have the same signature, how do you plan to call them? You could use the reflect package, but that is normally an indication that you are doing something wrong.
This is not a dynamic language and some things can not be done in Go. Although, they are mostly things you should not do in most languages anyways.
There's no way to dynamically look up a function by name, but I think it's worth mentioning why. Basically, the reason is so that the compiler and/or linker can eliminate unused functions.
Consider that if you were able to get a function by name, then every function in every imported package (recursively) would have to be linked into the final executable, even if it was never used, just in case someone wanted to look it up by name. People already complain about the large size of Go binaries, but this would cause them to be much larger still.