Recap - Contact Book
Part of the Object Oriented Programming section of Coddy's GO journey — lesson 18 of 107.
Challenge
EasyLet's build a contact book system that brings together custom types, nested structs, struct tags, and zero values—all the concepts you've mastered in this chapter.
You'll organize your code across two files:
contact.go: Define your contact book data model with meaningful custom types and proper JSON formatting:- Create custom types
PhoneandEmailbased onstringto make your code self-documenting - Define an
Addressstruct withStreet,City, andCountryfields, each with appropriate JSON tags - Define a
Contactstruct containingName(string),Phone(your Phone type),Email(your Email type), andAddress(nested struct). Use JSON tags wherephoneandemailshould be omitted if empty
- Create custom types
main.go: Read contact information from input, create a Contact instance, and output it as formatted JSON. Some contacts may have incomplete information—let zero values andomitemptyhandle those gracefully.
The following inputs will be provided:
- Line 1: Contact name
- Line 2: Phone number (may be empty)
- Line 3: Email address (may be empty)
- Line 4: Street address
- Line 5: City
- Line 6: Country
Use json.MarshalIndent with two spaces for indentation. Print the resulting JSON string.
For example, if given a contact with name Alice Smith, no phone, email alice@example.com, street 123 Main St, city Boston, and country USA, your output should look like:
{
"name": "Alice Smith",
"email": "alice@example.com",
"address": {
"street": "123 Main St",
"city": "Boston",
"country": "USA"
}
}Notice how the phone field doesn't appear at all since it was empty—that's your omitempty tag at work!
Try it yourself
package main
import (
"bufio"
"encoding/json"
"fmt"
"os"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Read name
scanner.Scan()
name := scanner.Text()
// Read phone (may be empty)
scanner.Scan()
phone := scanner.Text()
// Read email (may be empty)
scanner.Scan()
email := scanner.Text()
// Read street
scanner.Scan()
street := scanner.Text()
// Read city
scanner.Scan()
city := scanner.Text()
// Read country
scanner.Scan()
country := scanner.Text()
// TODO: Create a Contact instance using the input values
// Use your custom types Phone and Email for the respective fields
// Create the nested Address struct with street, city, and country
// TODO: Use json.MarshalIndent to convert the contact to JSON
// Use "" as prefix and " " (two spaces) as indent
// TODO: Print the JSON string
_ = name
_ = phone
_ = email
_ = street
_ = city
_ = country
}
All lessons in Object Oriented Programming
1Fundamentals of Go OOP
External FilesGo Workspace & ModulesPackages & ImportsExported vs Unexported NamesIntroduction to OOP in GoStructs as ClassesDefining Methods on StructsPointer vs Value ReceiversStruct InitializationConstructor FunctionsRecap - Simple Calculator4Interfaces
Introduction to InterfacesImplicit ImplementationInterface as ContractEmpty Interface (any)Type AssertionType SwitchInterface CompositionStringer & Error InterfacesRecap - Shape Calculator7Encapsulation
Exported vs Unexported FieldsPackage-Level EncapsulationGetter & Setter MethodsInformation Hiding in GoRecap - Student Records10Generics (Go 1.18+)
Introduction to GenericsType ParametersType ConstraintsGeneric StructsGeneric Methods WorkaroundRecap - Generic Collection2Types & Structs Deep Dive
Basic & Composite TypesCustom Type DefinitionsStruct TagsAnonymous StructsNested StructsZero Values & DefaultsRecap - Contact Book5Composition Over Inheritance
Why Go Has No InheritanceStruct Embedding BasicsMethod PromotionEmbedding Multiple StructsEmbedding vs AggregationShadowing Embedded MethodsRecap - Employee Hierarchy8Error Handling & OOP
The error InterfaceCustom Error TypesError Wrapping (fmt.Errorf)Sentinel Errorserrors.Is() and errors.As()Panic, Defer, and RecoverRecap - File Parser3Pointers & Memory
Pointer Basics in GoPointers to StructsPass by Value vs ReferenceThe new() FunctionGarbage Collection in GoRecap - Linked List Builder6Polymorphism in Go
Polymorphism via InterfacesDuck Typing in GoInterface Satisfaction RulesPolymorphic CollectionsDependency InjectionRecap - Payment Processor9Concurrency & OOP
Goroutines BasicsChannels & CommunicationBuffered vs Unbuffered ChanSelect Statementsync.Mutex & sync.RWMutexsync.WaitGroupThread-Safe Struct DesignRecap - Worker Pool