Hands-on Exercise #9 A “callback” is when

I am well aware that I am far below most people on this site, in fact, it’s very possible that I’m the lowest. However, I am committed to learning
go so I often need your help.

The instructions: " For this exercise,* pass a func into a func as an argument"

My attempt to do the exercise before I watched the video and saw the teacher’s solution. https://play.golang.org/p/WMXMg6qn2N9

My idea was, and I have no idea where this idea came from, was to add 42 to each of these numbers: 1, 2, 3, 4, 5, 6, 7, 8, 9

Question #1 Will my idea follow the teacher’s instruction?

Question #2 If so, what did I do wrong?

Question #3 If not, I’d still be interested in knowing how to complete the task in my idea. And I will study the teacher’s solution more intently.

By the way, this is the teacher’s solution. [ https://play.golang.org/p/0yGYPKh1y7

I’m dismayed that answering my questions probably requires much patience for those who come to my aid, but I receive solace when I remember that “patience is a virtue”.

Hi Cherolyn,

Out of curiosity, are you working through a course authored by Todd McLeod? I recognise this exercise.

In regards to the exercise, the requirement is that you have a function that takes another function as an argument.

So, first up let’s create a function.

func doSomething() { 

}

So, we have a function called doSomething which ironically currently does nothing. In order to be able to pass a function as an argument, we need to define that between the parentheses. We can do that like this:

func doSomething(something func()) {

}

So, we’re telling Go that the function doSomething expects another function to be passed as an argument. For the sake of simplicity the function that we pass into doSomething doesn’t return anything or take any arguments itself.

Now we know that whenever doSomething is called we’ll have an argument something which is also a function, we can again for the sake of simplicity just call it.

func doSomething(something func()) {
    something() // we can call this because we know it's always a function
}

What this means is that, whenever we call doSomething passing another function as an argument, the doSomething function will immediately call the function you gave it.

In order to test this we can create another function that does nothing but print out a string.

function somethingToDo() {
    fmt.Println("We're doing something cool!")
}

Because the function doesn’t take any arguments or return anything, we can use it as the argument for the doSomething function. Like this:

doSomething(somethingToDo)

and if everything went to plan, you should see in the logs

We're doing something cool!

The above example can be found here: https://play.golang.org/p/JcaUTxVcZEj


Now, let’s try and apply the above to what you’re trying to achieve.

My idea was, and I have no idea where this idea came from, was to add 42 to each of these numbers: 1, 2, 3, 4, 5, 6, 7, 8, 9

First up, let’s create a function that takes a number as an argument and returns that number plus 42.

func add42(number int) int {
    return number + 42;
}

The above function takes a given integer number and returns number + 42. We define number of type int as an argument to the function and tell Go that we expect add42 to return an int by adding it as the return type after the parentheses.

For example, if we were to now call add42 on the number 10 and print out the value using fmt.Println we would get 52.

fmt.Println(add42(10)) // 52

So, now we have a function that does something useful, we now need to create another function that will take an array of integers and a function and call the function on each of the integers in the array and return the subsequently returned values.

In the context of your idea, we’ll create a function that we pass []int{ 1, 2, 3, 4, 5, 6, 7, 8, 9 } and the add42 function and expect to get an array back containing: int[]{ 43, 44, 45, 46, 47, 48, 49, 50, 51 }.

// numbers = an array of input numbers 1, 2, 3, 4...
//
// add is a function argument for a function that takes an integer as
// an argument and returns an integer. We'll be passing the add42 function here.
//
// []int is the return type which is `numbers` with 42 added to each. 
func add42ToAll(numbers []int, add func(int) int) []int {

    // create an array to hold our new numbers
    newNumbers := []int{}

    // loop over the numbers input array
    for _, number := range numbers {
        
        // for each `number` in the numbers array, add the value returned from
        // add (add42) to the `newNumbers` array.
        newNumbers = append(newNumbers, add(number))
    }

    // return our newNumbers
    return newNumbers
}

If we then call the add42ToAll function with []int{ 1, 2, 3, 4, 5, 6, 7, 8, 9 } and passing add42 as the add function argument, we should get what we want.

Here’s an example of the above in practice: https://play.golang.org/p/zdxMejCL0OM

I hope this was helpful and it’s great to see that you’re learning Go!

Yes, I am taking a course by Todd McLeod.
I enjoy your humor.
Thanks for your clear demonstration of passing a function as an argument.
I have a question and I’m not quite sure how to ask it. Here goes.
When you include a “box” like

func add42(number int) int {
    return number + 42;
}

am I simply to read that information? or am I to put it on the Playground. And if it’s the second option, how do I do that? copy and Paste?
Another question. Is there a name that designates the area on The Go Playground above or before func main()?
I don’t know when “Information”, like functions, declarations, etc. are supposed to go there or after func main()
I’m sure I sound like an imbecile
I think understanding is dawning.

Haha! I thought so, that’s a great course, I would recommend it to anybody who wants to learn Go.

When I include a box, I do so to isolate a small code snippet, hopefully make it easier to understand outside of the noise of the rest of the code.

It’s helpful to do this so you can breakdown the various components of the code and analyse them in isolation.

It will always be valid Go, so in theory yes you could definitely copy and paste those snippets into the Go Playground and it should run perfectly fine.

I try to always include a link to a working example for reference.

Another question. Is there a name that designates the area on The Go Playground above or before func main()?

In the Playground it shouldn’t make a difference where you define functions whether it be above or below the main function.

For example, this works fine:

package main

import (
	"fmt"
)

func doSomethingElse() {
	fmt.Println("Doing Something Else!");
}

func main() {
	doSomething()
	doSomethingElse()
}

func doSomething() {
	fmt.Println("Doing Something!")
}

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

I hope this was helpful.

1 Like

Before I read the reply above, since my time is limited, I have a question about the teacher’s solution. The teacher said that this:

return xi[0] + xi[len(xi)-1]

returns the first item and the last . Possibly because my time is so limited, I can’t figure out why.

Just carved out some extra time.
Thanks for the recommendation. Todd is an intelligent, caring man and he throws in some refreshing humor.
The links are helpful!
https://play.golang.org/p/c7sYmpnWD33
Thanks for this. It is helpful!
I love it when I come to understanding!

1 Like

Keep at it, your tenacity is refreshing. :slight_smile:

2 Likes

Hi Cherolyn,

Sorry! I’ve only just seen this.

Before I read the reply above, since my time is limited, I have a question about the teacher’s solution. The teacher said that this…

As you say, the following will return the first element in the xi slice plus the last element in the slice. For reference this is the slice used in the example []int{1, 2, 3, 4, 5, 6}.

return xi[0] + xi[len(xi)-1] // 1 + 6

So, if you want to access an element of a slice you can do so using the corresponding index. For example if you wanted to get the first element of the xi slice you would do: xi[0] remembering that slices are indexed from 0, so 0 would be the first element and 1 the second and so on and so forth…

The first part of the return statement which is xi[0] would equal 1 as in the slice above we can see that the first element is the number 1.

Then there’s a + symbol, which is literally addition because we’re working with a slice of integers. Followed by this:

xi[len(xi) - 1]

Which might look strange, but it can be broken down. So, as we did when getting the first element of the slice we’re simply asking for a specific index, which in this case is whatever len(xi) - 1 evaluates to.

The len function is responsible for returning the length of a given slice. For example if we were to call len on the xi slice we would get 6 as expected, because there are 6 integers in the slice. However, as I mentioned previously slice indexes start at 0, so if we did xi[6] we would actually get an error because the indexes of the slice are actually 0-5 not 1-6. This is why we minus 1 from the value returned from len(xi).

So, in theory what xi[len(xi) - 1] is actually doing is xi[5], but we’re using len to determine what the final element in the slice is because the length of the slice is dynamic and could change.

1 Like

Got it! Thanks!!!

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

Yes it IS helpful !! Thanks !!

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