Anonymous functions...https://play.golang.org/p/wTKHFo8ryvQ

https://play.golang.org/p/wTKHFo8ryvQ

Sorry I pushed the button before I was finished. in the above code, are all the functions anonymous? Or, which ones are?

I’m also reading the Language Specification.

https://golang.org/ref/spec#Function_literals

In" func(a, b int, z float64) bool { return ab < int(z) }", is "(a, b int, z float64) bool { return ab < int(z) }" the function body?

These are anonymous:

func() {
		fmt.Println("Anonymous func ran")
	}()

	func(x int) {
		fmt.Println("The meaning of life:", x)
	}(42)

On the other hand, foo is not and neither are Println, a function from the package fmt, and main, also a named function, as they all have an identifier. Functions are anonymous when they are declared without an identifier.

No, the body are the statements that compose the function, i.e., what’s in between the opening and closing brackets of the function. That is:

return ab < int(z)

Thanks! So are scope and body synonymous?

No, they are not. Consider this example which is explained through its comments:

func myFunc() {
	//This is the beginning of the body.
	//It's also the beginning of the function scope which we'll call FSC.
	a := 1
	fmt.Println(a) //This will print 1.
	{
		//This is still the body of the function.
		//This is also the beginning of an inner scope which we'll call ISC1.
		//We can redeclare a here and it'll shadow the outer one AFTER we redeclare it, but can access the original a BEFORE.
		fmt.Println(a) //Still prints 1.
		a := 2         //Now it shadows the original a while we are in this scope.
		b := 3         //Variable b is declared in this scope only, so it can't be used outside it, even though this is part of the function body.
		fmt.Println(a) //Now it prints 2.
		fmt.Println(b) //This prints 3.
		//Here scope ISC1 ends.
	}
        //Still, as everything in the function, this is part of its body.
	//Here we can't access b, so calling fmt.Println(b) wouldn't compile. Try it by uncommenting the next line.
	//fmt.Println(b)
	{
		//This is still the body of the function.
		//This is also the beginning of another inner scope which we'll call ISC2.
		//Here a is still 1, as the redeclaration was only visible in scope ISC1.
		fmt.Println(a) //Still prints 1.
		//Again, here we can't access b as it's not declared in this scope or on the outer FSC one.
		//So here calling fmt.Println(b) wouldn't compile. Try it by uncommenting the next line.
		//fmt.Println(b)
		//Here scope ISC2 ends.
	}
	//As expected, a is still 1 and b doesn't exist here.
	fmt.Println(a) //Still prints 1.
	//fmt.Println(b)
	//Now both the function scope FSC and the body end.
}

You can try it at the playground here: https://play.golang.org/p/BdVEwlZ6OJk.

So the function body is every statement contained in the function, i.e., between the brackets, which is effectively a scope too. But function body and scope are not the same, as you may have many scopes in a function body, and there are scopes that are bigger than function bodies as well (for example, you may declare variables in the package scope that are visible to all functions on that package). There are more scopes than those also, such as file scope or local scopes belonging to control flows (if, for, etc.) and so on. You can read more about scopes here: https://go101.org/article/blocks-and-scopes.html.

Now, this may be too much right now, but you should at least read a bit about these concepts so you can begin differentiating them to move forwards.

2 Likes

Working on the above…
“it’ll shadow the outer one AFTER we redeclare it”
I don’t know what this means. Specifically, “shadows”

VERY interesting! And helpful!

It means that the a variable we declared in the outer scope is accessible in the inner scope so long as we don’t redeclare it, and we are able to redeclare it (instead of just assigning to it) because we are in a local inner scope, just as we can redeclare global variables in our local function scopes.

So, once we declare the inner a variable, it’ll have effectively shadowed the outer a name in that scope, meaning that it’ll be only local to that scope, you’ll lose visibility on the outer one, and any changes to it will remain local. The latter is the reason why after the inner scope finishes, if we print the value of a we still see the original outer scope value of 1, as the inner declaration was shadowing the original one and thus didn’t affect it.

1 Like

Got it! Thank you SO MUCH! Really turns a light on, and I love learning.

Very interesting article and I have bookmarked it.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.