Book and User Structs
Part of the Object Oriented Programming section of Coddy's GO journey — lesson 99 of 107.
Challenge
EasyLet's build the core data models for our Library Management System! You'll create the foundational structs that represent books and library members, complete with constructor functions that initialize them with sensible defaults.
You'll organize your code across three files:
book.go: Define yourBookstruct with fields forID,Title,Author,ISBN, andAvailable(boolean). Create aNewBookconstructor function that takes the ID, title, author, and ISBN as parameters and returns a pointer to a new Book. New books should always start as available. Add anInfo()method that returns the book's details in the format:[ID] "Title" by Author (ISBN: [isbn]) - Available: [true/false]user.go: Define yourUserstruct with fields forID,Name,Email, andBorrowedBooks(a slice of strings to store book IDs). Create aNewUserconstructor that takes ID, name, and email, returning a pointer to a new User with an empty borrowed books list. Add anInfo()method that returns:Member: [Name] ([Email]) - Books borrowed: [count]main.go: Bring your models together by creating books and users from input, then displaying their information.Read the number of books, then for each book read its ID, title, author, and ISBN on separate lines. Next, read the number of users, and for each user read their ID, name, and email on separate lines.
Print each book's info on its own line, followed by each user's info on its own line.
The following inputs will be provided:
- Number of books
- For each book: ID, title, author, ISBN (each on separate lines)
- Number of users
- For each user: ID, name, email (each on separate lines)
For example, given:
2
B001
The Go Programming Language
Alan Donovan
978-0134190440
B002
Clean Code
Robert Martin
978-0132350884
1
U001
Alice Smith
alice@library.comYour output should be:
[B001] "The Go Programming Language" by Alan Donovan (ISBN: 978-0134190440) - Available: true
[B002] "Clean Code" by Robert Martin (ISBN: 978-0132350884) - Available: true
Member: Alice Smith (alice@library.com) - Books borrowed: 0And given:
1
B100
Design Patterns
Gang of Four
978-0201633610
2
U001
Bob Jones
bob@email.com
U002
Carol White
carol@email.comYour output should be:
[B100] "Design Patterns" by Gang of Four (ISBN: 978-0201633610) - Available: true
Member: Bob Jones (bob@email.com) - Books borrowed: 0
Member: Carol White (carol@email.com) - Books borrowed: 0Notice how the constructors handle default values—books start available and users start with zero borrowed books. This pattern of using constructor functions to ensure proper initialization is fundamental to building reliable systems!
Try it yourself
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Read number of books
numBooksStr, _ := reader.ReadString('\n')
numBooks, _ := strconv.Atoi(strings.TrimSpace(numBooksStr))
// TODO: Create a slice to store books
// Read each book's details
for i := 0; i < numBooks; i++ {
id, _ := reader.ReadString('\n')
id = strings.TrimSpace(id)
title, _ := reader.ReadString('\n')
title = strings.TrimSpace(title)
author, _ := reader.ReadString('\n')
author = strings.TrimSpace(author)
isbn, _ := reader.ReadString('\n')
isbn = strings.TrimSpace(isbn)
// TODO: Create a new book using NewBook constructor and add to slice
}
// Read number of users
numUsersStr, _ := reader.ReadString('\n')
numUsers, _ := strconv.Atoi(strings.TrimSpace(numUsersStr))
// TODO: Create a slice to store users
// Read each user's details
for i := 0; i < numUsers; i++ {
id, _ := reader.ReadString('\n')
id = strings.TrimSpace(id)
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
email, _ := reader.ReadString('\n')
email = strings.TrimSpace(email)
// TODO: Create a new user using NewUser constructor and add to slice
}
// TODO: Print each book's info using the Info() method
// TODO: Print each user's info using the Info() method
fmt.Println() // Placeholder - remove when implementing
}
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 Pool12Advanced OOP Concepts
Functional Options PatternBuilder Pattern in GoMethod ChainingType Aliases vs DefinitionsReflection BasicsCode Generation Overview15Project: Library Management
Project Overview & StructureBook and User Structs