Syntax of functions...unc (receiver) identifier(parameters) (returns) { code }

I have the following information for the syntax of functions: func (receiver) identifier(parameters) (returns) { code }

Since all of the following items are marked by paqrenthesis: (receiver) , (parameters) , and (returns); how do I distinguish them, or know which is which when I see them in a function?

2 Likes

By their position.

Also please keep in mind that while parenthesis around the receiver and the parameters are mandatory, while those around the returns are only necessary when you have a multi-value return.

3 Likes

I notice sometimes functions have no receiver. Will parameters always come after an identifier? and will returns, when they are present ( for it seems to me that I have seen functions that have no returns), always come after the parameters? Are there cases when a function has no parameters?

In this function: https://play.golang.org/p/AEbN6j-ClwC, which of the 3 items is (y int)?

In explaining the code just mentioned, the teacher states that “we pass x into here (foo), it gets assigned to y”

I don’t understand this concept: it gets assigned to y

1 Like

It’s the arguments/parameters.

A receiver is in fact optional (but if it’s there parens are mandatory), as well as returns.

Parameters can be empty, but the parents need to be there. Just look at the main function in the same example you posted.

2 Likes

Parents?

1 Like

It’s a rule by its way of writing and with the first word func indicates that line is a function. Hence, a function must carry:

func (receiver)* name(parameters) (return)* {
    ...
}

* = optional

yes. It’s a rule, something like thumb is always facing toward your chest; pinky is facing away from body.

value return are optional. If exists, the return keyword must be inside the code respecting the output. Otherwise, it serves as an instruction to exit the function.

the parameter of the foo function takes in y, an integer. When main calls foo(x), it jumps into function foo. Since the input is x, it is being passed in as y when the execution enters foo function. This is known as “Pass by Value”.

1 Like

Should have been “parens”, mobile virtual keyboards autocorrect kicking in. And “parens” is just short for parentheses.

3 Likes

Same here. It’s so hard to reply this forum on mobile.

1 Like

Helpful

Requires study. My brain rebels, but I will silence it![quote=“hollowaykeanho, post:6, topic:15656”]

"When main calls foo(x),it jumps into function foo. "…these words really help!

Thanks!!!

1 Like

I thought that might be the case. So now, I will examine what you said again.

So,foo is the identifier. And if there were a receiver, it would come before the word “foo”.

1 Like

One easy way to understand is injecting debug messages before and after lines. Consider the following modified codes:

package main

import (
	"fmt"
)

func liner(functionName string, format string, a ...interface{}) {
	info := fmt.Sprintf(format, a...)
	fmt.Printf("[%s] %v\n", functionName, info)
}

func main() {
	liner("main", "debug line before define x")
	x := 2
	liner("main", "debug line before calling foo, x=%v", x)
	foo(x)
	liner("main", "debug line after foo, x=%v", x)
	fmt.Println(x)
	liner("main", "debug line after foo, after print, x=%v", x)
}

func foo(y int) {
	liner("foo", "debug line enters foo. y=%v", y)
	fmt.Println(y)
	liner("foo", "debug line, after print y, y=%v", y)
	y = 43
	liner("foo", "debug line, after set y, y=%v", y)
	fmt.Println(y)
	liner("foo", "debug line, end foo, y=%v", y)
}

Output with mixed-up liner:

[main] debug line before define x
[main] debug line before calling foo, x=2
[foo] debug line enters foo. y=2
2
[foo] debug line, after print y, y=2
[foo] debug line, after set y, y=43
43
[foo] debug line, end foo, y=43
[main] debug line after foo, x=2
2
[main] debug line after foo, after print, x=2

The main function is indicated by [main] tag while foo function indicated by [foo] tag.

Notice that at the first line of [foo] tag after the cpu enters the function, y is the same as x instead of 0. This is what it meant by your lecturer, the value was passed in from x to y.

Due to the nature of “Passed by Value”, when [main] resumes back after [foo] exited, x is still back to 2 instead of 43, like how you modified it inside foo function. This essentially means that the function clones the value into y instead of modifying x directly.

NOTE:

You can only do this liner experiment when not dealing with concurrency. Otherwise, it’s pointless
and incomprehensible. You need a different tool for that.

1 Like

I don’t know what that is. How could I discover that on my own?

Is it possible to run this on my own? How?

2 Likes

It’s just a simple function I built with fmt. You can check them out by reading the documentations (fmt package - fmt - Go Packages) or start with hunting new tools with Google.

Yes. It’s just an idea for you to test your hypothesis.

1 Like

@cherilexvold1974 have you done the Tour of Go? It’s a good place to start.
https://tour.golang.org/

2 Likes

Yes, she has. As far as I understood her, she did the tour several times, and she also refered to it in her questions.

2 Likes

Would you explain this, piece by piece?

Do the same with this, please.

1 Like

Sure.

This function parts of input: functionName of course, it’s just a name. As for format and a, they are what we called variadic function’s parameters where you can put as many parameters into a without altering the code. a in this case, is a slice.

The objective is basically to print a statement, like your fmt.Printf(...). The only difference here is I added it to prepend the function name.

The function first process the messages (format and a) using fmt.Sprintf(...), where it output into a string (saved into info) instead of printing out to the console. Then, I use fmt.Printf(...) to prepend the functionName in front of the message.

With the new liner(...) printing function, I can easily print statements everywhere.

So when I call liner(...), I provided the function name manually (because apparently can complicates the codes), and the message I want to print out. So, I pass in:

  1. main, which will pass into functionName variable.
  2. debug line before define x, which will pass into format.
  3. Since I don’t have 3rd variable, the variadic parameter a, is empty.
1 Like

Explicit argument indexes:

In Printf, Sprintf, and Fprintf, the default behavior is for each formatting verb to format successive arguments passed in the call. However, the notation [n] immediately before the verb indicates that the nth one-indexed argument is to be formatted instead. The same notation before a ‘*’ for a width or precision selects the argument index holding the value. After processing a bracketed expression [n], subsequent verbs will use arguments n+1, n+2, etc. unless otherwise directed.

For example,

fmt.Sprintf(“%[2]d %[1]d\n”, 11, 22)

the notation [n] immediately before the verb
before? fmt. ? because fmt. is what I see before Sprintf.
Is Sprintf the verb?
Or possibly %? or d?

1 Like

Wow, that’s one way to explain it.

I think it meant by the subsequent items. So for Printf, Sprintf, Fprintf, Errorf or any printout ends with f, you can specify the format of you string (format successive arguments?). Then, the rest of arguments are optional. For explanation wise, I still prefer simple version: fmt package - fmt - Go Packages

The %??? is actually called verb. The process of using *****f is called string formatting. There are many types of verbs available for use as shown in Go by Example: String Formatting.

The position of the verb is corresponding to the subsequent arguments. This meant by, say for example, name and money fills in according to the positions of the verbs.

                  name                    money
                   🡣                       🡣
fmt.Printf("DEBUG: %s, the return value is %d.\n", name, money)

Be careful though, using string formatting on the fly (especially with %v or Go specialized %#v) without careful consideration may create impact if you’re working on time-sensitive project. Otherwise, feel free to use it at your debugging convenience.

1 Like

Thank you.
At your suggestion, I’m beginning to study this helpful link.

Printf formats according to a format specifier and writes to standard output. It returns the number of bytes written and any write error encountered.

What is a format specifier?
What is write error?

My teacher thus far has used Printf to show a type of a particular item in a code. How does that illustrate the above definition?

2 Likes