Part 6 mini-project: Inventory System
This project uses the Part 6 chapters: structs, methods, pointers,
slices, maps, and a package with exported names. An Item
and an Inventory manage a bag of loot.
What to build
Two types in one package, inventory.
Item, one collectable thing:
NewItem(name, weight, value)returns a*Itemand an error. The name must not be empty, and the weight and the value must not be below 0.- Unexported fields:
name(string),weight(float64),value(int). Name()returns the name.Describe()returns a one-line summary, such assword (3.5kg, 50g).
Inventory, a container of items:
New()returns an empty inventory, as a*Inventory.- An unexported field:
items, a slice of*Item. Add(item)appends an item.Remove(name)removes the first item with that name, and returns it. It returnsnilif none matches.List()prints each item'sDescribe()on its own line, then a line of totals.TotalWeight()returns the sum of the weights.TotalValue()returns the sum of the values.Counts()returns amap[string]intfrom a name to the number of items with that name.
main.go is written for you. It:
- Makes a few items, and adds them to an inventory.
- Lists the inventory.
- Removes one item by name.
- Lists it again.
- Tries to remove an item that is not there, tries to make an item with a bad weight, and adds a second potion.
- Prints the counts, with the names sorted.
The finished program prints:
Inventory (3 items):
- sword (3.5kg, 50g)
- shield (5.0kg, 30g)
- potion (0.2kg, 5g)
Totals: 8.70kg, 85g
(removed sword)
Inventory (2 items):
- shield (5.0kg, 30g)
- potion (0.2kg, 5g)
Totals: 5.20kg, 35g
(no lantern to remove)
Error: item rock: weight -1.0 is below 0
Counts:
potion: 2
shield: 1
File layout
This project is a module with two packages, as in Part 5. Both
versions live under projects/05-inventory/:
starter/
go.mod
main.go
inventory/
inventory.go
finished/
go.mod
main.go
inventory/
inventory.go
To work on the starter, go into its folder and use
go run .:
cd projects/05-inventory/starter
go run .
To run the finished version:
cd projects/05-inventory/finished
go run .
The starter runs as it is. It prints placeholder lines.
main.go is finished, and the TODOs are all in
inventory/inventory.go. Run go vet ./... in
the same folder to check both packages.
Hints
inventoryis both the package name and the folder. The module is calledinventorysystem, so the import line is"inventorysystem/inventory".- The fields are lower case, so
maincannot change an item's weight. That is whyName()exists, and whymainwritesremoved.Name(). Itemvalues do not change, butInventoryvalues do, soAddandRemoveneed pointer receivers. The rules from Chapter 27 then give pointer receivers to the rest ofInventory. NoItemmethod changes it, so rule 3 would allow value receivers there. It has pointer receivers to matchNewItem, which returns a*Item. The slice holds*Item, so thatRemovecan returnnilwhen there is no match.Removewalksinv.itemswithrange, looking for a matchingname, then removes it with theappendline from Chapter 22. Assign the result back toinv.items.- Use
fmt.Printffor the totals line:" Totals: %.2fkg, %dg\n". Describereturns the string instead of printing it, so thatListcontrols how each line is displayed.fmt.Sprintfbuilds it.counts[item.name]++works on a missing key, because the zero value of an int is0, as in Chapter 23's word count.
What is fair game
Anything from Parts 2 to 6: variables, control flow, functions, errors, packages, slices, maps, structs, methods and pointers.
Done?
When the output of your go run . matches the one above,
you are done. The next project is the Monster Battle.