Structs and functions


(Cherolyn Lexvold) #1

Compare the teacher’s code https://play.golang.org/p/AKrvuxF0wMK

to my code https://play.golang.org/p/11zv6VD--y7

What did I do wrong?
What does “undefined” mean in the error message?
What am I to do?


(Ignacio Gómez) #2

You didn’t define the person type, that’s why it’s undefined (the original code defines the person type in lines 7-10). The error is pretty clear in this case. Anyway, just rename the clients type to person, or embed a clients in the verification type instead of a person.


(Cherolyn Lexvold) #3

What you said got me to see what I did. I solved it this way: https://play.golang.org/p/1piUGZ06vdr


(Cherolyn Lexvold) #4

I’M attempting to add some if clauses.
https://play.golang.org/p/4p14PYiHLUv
I need help :thinking:


(Ignacio Gómez) #5

There are a bunch of errors there involving several things. I think you need to start resolving them by carefully reading and understanding the error messages. You’ll never be comfortable dealing with errors if we fix them all for you, and these aren’t particularly obscure.


(Cherolyn Lexvold) #6

But I don’t understand why the function body is missing. Isn’t this the function body?

“func main()” Ok, I solved that problem by putting “}” after "func main()

Now I’m here: https://play.golang.org/p/0JQCbmJekcc and the error says that age is undefined. Yet I thought I defined it here: “age int”


(Cherolyn Lexvold) #7

Whoops, “{”


(Ignacio Gómez) #8

You defined it as a field of the type clients which is embedded in the type verification. So think about it, why would calling age inside the method scream undefined? What difference do you see with this line?

fmt.Println("V", s.first, s.age, s.occupation)

Also, about the function body missing: Go has strict formatting rules, which among other things dictate that (except for one liners) functions are defined like this:

func yourFunc() {
  // code
}

That means that this (or whatever else doesn’t conform to the correct format) is not valid:

func yourFunc()
{
  //wrong
}

On another note, you are creating some weird and unnecessary scopes there. If you fix your main function by adding { and }, then you’ll be left with these:

func main() {
//function scope
	{
        //first inner scope
		sa1 := verification{
			clients: clients{
				"Terry",
				25,
				"forklift",
			},
			verified: true,
		}
		{
            //second inner scope
			sa2 := verification{
				clients: clients{
					"Kevin",
					17,
					"student",
				},
				verified: false,
			}
			fmt.Println(sa1)
			fmt.Println(sa2)
			sa1.status()
			sa2.status()

		}
        //this would throw an error, as sa2 is declared in the second inner scope and isn't visibible to the first inner scope
       fmt.Println(sa2)
	}
    //this would throw an error, as sa1 is declared in the first inner scope and isn't visibible to the function scope
    fmt.Println(sa1)
}

As the comments state, there are 3 scopes: the function one and two nested inner ones. Also, the comments show how the visibility of your variables works in these scopes. As you see, brackets by themselves may create scopes, they don’t need to be part of an if, function, etc. So be careful when using them.


(Cherolyn Lexvold) #9

“method scream” ?
“What difference do you see with this line?” Difference from what?
Are you saying here…“func yourFunc()
{
//wrong
}” that “{” can’t be on a different line in the code than “func yourFunc() {”


(Ignacio Gómez) #10

I just meant that the compiler will tell you there’s an error, in this case that age is undefined.

What’s the difference between the code you posted on the line that throws an error and the one I wrote in my reply?

Exactly.


(Cherolyn Lexvold) #11

Not sure what you mean by visible.


(Ignacio Gómez) #12

It means that it hasn’t been declared and thus can’t be used in that scope. As an example, if you declare a local variable in a function, it may only be used or is only visible in that function, so other functions can’t mention it:

func f() {
  a := 1
  fmt.Println(a)
}

func g() {
  fmt.Println(a) //This won't work, a is not visible in this scope.
}

Well, as I mentioned, brackets create scopes, so this applies for them too. Thus, this doesn’t work either:

func someFunc(){
...
  {
    a := 1
    fmt.Println(a) //This works.
  }
  fmt.Println(a) //This doesn't work, a is not visible here.
}

(Cherolyn Lexvold) #13

Thanks. It’s getting clearer.


(Cherolyn Lexvold) #14

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

This runs, but it is not accomplishing my goal, to have the program look at the age, and if it’s under 18, to write …

I guess I’m not clear on what I want here. I’m wanting the program to determine whether or not a client is verified by whether he is 18 or over, or not verified if he is under 18


(Ignacio Gómez) #15

Again, I don’t get why you are creating all those scopes, they aren’t necessary.

I refactored your code a bit to remove those scopes and “verify” if a “client” is under 18: https://play.golang.org/p/96V_0VnqglS


(Cherolyn Lexvold) #16

I’m just exploring.
https://play.golang.org/p/96V_0VnqglS
This looks very interesting, and I am studying it. I think I have learned by now that “ageStr” is a random name, or is there any significance to the “Str” part.
Is “c.age” also random?
Something, from what follows, looks significant about “c.”
“%s is a %s, is %d and so %s.\n” This looks interesting, although I’m not sure what it means.
I did learn from goDoc that %s is “the uninterpreted bytes of the string or slice”

If you would like to explain further, I would be very interested. I might have dug myself in a bit of a hole here, so if you think we should abandon this until I am further along in my studies, go ahead


(Ignacio Gómez) #17

It’s “random” in the sense that you can choose any other name for the identifier. In this case I called it ageStr because it’s a string that holds information concerning the age and wanted to make clear the difference between the age field of the client struct and this string.

Random in what sense? Are you asking if c is random? In that case, Go encourages short names for receivers, so naming the receiver with the struct’s first letter is common.

Those are format verbs, they control how things are formatted when printing them. Take a look at this for more details: https://golang.org/pkg/fmt/.


(Inanc Gumus) #18

I think it’s not idiomatic to use the types in the names. It could be: verified or result or res instead of ageStr.


(Ignacio Gómez) #19

I was just being clear about the distinction, but you’re right, that isn’t idiomatic and it could’ve been named better. Thanks.