Zero values, not null
In PHP, a value you never set is null. Or it's undefined, PHP throws a warning, and then it's null. Half your career has been ??, isset() and ?->, and that's fine. It's how the language works.
Go takes a different line: every type has a zero value, and anything you declare without assigning starts there. Not null. Not undefined. Just the boring, usable default for that type.
| Type | Zero value | Roughly in PHP |
|---|---|---|
int, float64 |
0 |
(int) null |
string |
"" |
(string) null |
bool |
false |
(bool) null |
| struct | every field at its zero value | a DTO with defaults everywhere |
| pointer, slice, map, interface | nil |
null, finally |
A quick word on that struct row, since structs turn up in this lesson's examples. A struct is a named bundle of typed fields: think of a PHP class with only public typed properties and no methods, or an associative array whose keys are fixed and checked by the compiler.
type Config struct { Host string Port int Debug bool }
Config{} builds one with every field left at its zero value, Config{Port: 9000} sets just the fields you name, and cfg.Port reads a field (no ->, just a dot). That's all you need for now. Structs get proper lessons of their own in Units 2 and 3.
So var port int, the no-value form from 1.1, is 0 right now, with no warning. And Config{} is a perfectly valid config, with an empty host, port 0 and debug off. You can pass it around, compare it and print it.
Wait, Go has nil?
It does, but only for things that point at something: pointers, slices, maps, channels, functions and interfaces. You'll meet each of them in later units. A string can never be nil, and neither can an int. The compiler won't let you write if name == nil, which wipes out a whole category of "null where I expected a string" bugs.
Mind the gap
Zero can be a real value. Port 0, a discount of 0, false meaning "explicitly off". Go can't tell "never set" from "set to zero". When that difference matters, reach for a pointer (*int, where nil means unset, covered in 3.3), or the comma-ok idiom for maps (2.4).
PHP typed properties, for comparison
PHP 7.4+ got closer, then swerved. A typed property with no default isn't null, it's uninitialised, and reading it throws an Error. Go would just hand you 0. Check the Interchange tab: both versions are side by side.
Laravel corner
You're used to config('database.port', 5432), with the default supplied at read time, every time. Go code usually applies defaults once, when the config struct is built, and passes the finished struct around. That's exactly what the exercise asks you to write.
Recap
- Declared but unassigned means zero value:
0,"",false, ornilfor reference-y types. stringandintcan't benil. No??; you compare against the zero value.- When zero is a legitimate value, use a pointer or comma-ok to spot "unset".