Let's take a look at how a Go program works. We'll use The Go Playground for this. You need to have a package main inside of your program. Inside package main, you will have func main
and func main is where your program runs. It can do lots of things, but func main
is the entrypoint to your program, and also the exitpoint of your program. So when you leave func main()
your program is over.
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello, playground")
}
So, you need package main
and that is a keyword. How would you know that is a keyword? You can check the Golang Spec. Go to the language specification, and check out Lexical Elements where you can see the Keywords. There aren't that many
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var
But you can see package
, import
, and func
So, to reiterate, we have our package declaration; in this case package main
. We have are importing the "fmt"
package from the standard Go library, and then in our func main()
we are calling the Println
function from the fmt
package.
Often we will import other packages from the standard library, or from third parties. You can write the import as a one-liner, i.e.
import "fmt"
When we are importing multiple packages, it's more idiomatic to use parentheses:
import (
"fmt"
)
If I want to read the documentation about a Go package, in this case the fmt
package, I can go to golang.org, click on documents scroll down to package documentation, then scroll down to fmt. You can also go to godoc.org, ior in this case godoc.org/fmt. Some other examples are [godoc.org/het/http)(http://godoc.org/net/http), godoc.og/html/template, etc.
OK, so we're looking at the godoc.org/fmt documentation. If we look down, you can see the index. This is often the first place I go. Everything with a capital first letter is exported from the package, or it's visible from outside the package.
We don't say public/private in Go. Those words come with baggage from other languages. We say Exported/Not Exported, Visible/Not Visible outside the package. If it starts with a capital letter, that means it's visible outside the package.
We're using fmt.Println
from the fmt
package. Let's look at the documentation for fmt.Println.
func Println(a ...interface{}) (n int, err error)
"Println formats using the default formats for its operands and writes to standard output. Spaces are always added between operands and a newline is appended. It returns the number of bytes written and any write error encountered."
Generally speaking in Go, you're always going to do something with a returns, but sometimes you don't have to, and what the rule is for when you do and when you don't, I'm not totally clear. With Println
, I've always seen it used without capturing the int and the err.
If we wanted to catch the int and the err, we could say
package main
import (
"fmt"
)
func main() {
n, err := fmt.Println("Hello, playground")
fmt.Println(n, err)
}
but then you might think, now we have to do something with what is returned, so
package main
import (
"fmt"
)
func main() {
n, err := fmt.Println("Hello, playground")
n2, err2 := fmt.Println(n, err)
}
which is probably why we don't usually see capturing the int and the err, because it could lead to an infinite loop of capturing errors.
Another way you can get rid of things which are being returned, is you can just throw them into the void. Go is all about not wasting effort and having clean code.
One of the ways to avoid code pollution is to not have variables that you do not use. So in this case, if we say we have n2, and err2, but we're not using it, and try running it, it will throw an error.
package main
import (
"fmt"
)
func main() {
n, err := fmt.Println("Hello, playground")
_, _ := fmt.Println(n, err)
}
This says tmp/sandbox214796246/main.go:9: no new variables on left side of :=
Which is saying we're not declaring new variables on line 9, so we can just use the equals sign (we'll learn about the short declaration in a moment), and it compiles and runs.
package main
import (
"fmt"
)
func main() {
n, err := fmt.Println("Hello, playground")
_, _ = fmt.Println(n, err)
}
This prints out
Hello, playground
18 <nil>
This printed out "Hello, playground" and it printed out my n, with is the number of bytes (18) and the err, which is nil
.
To recap, from package fmt
we have used the Println
function. This takes a variadic parameter of any type. We'll learn about interfaces later on. When you see the triple dots and then the type, that means you can take an unlimited number of this type. This type right here interface{}
is the empty interface. Everything implements the empty interface, so you can put as many values as you want in here and just separate them by commas, and fmt.Println
will just print them out.
So, if we wanted to, we could keep adding more variables
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello, playground", 42, "something else", true)
}
and it will keep printing them out.
So that is Println
from the package fmt
. We had some exposure to reading documentation. The main take away you should get from this video is that every program in go starts in package main, and it starts in func main. So package main needs to have func main.
func main is the entrypoint to your program, and when it exists your program is over. We use this dot notation where we have package.Identifier
The identifier can be for a variable, a constant, or a function. Any identifier for a variable, constant or function that starts with a capital is exported or visible from outside the package. Println
starts with a capital, so we can access that. This takes a variadic parameter, which is the triple dots, and that just means it can accept any number of arguments, in this case of type of an emtpy interface interface{}
, which can be any type. We comma separate them.
We will look at format printing in the next video.