mirror of
https://github.com/bootdotdev/fcc-learn-golang-assets.git
synced 2025-12-18 03:01:16 +00:00
first
This commit is contained in:
29
course/11-pointers/exercises/1-pointers_intro/code.go
Normal file
29
course/11-pointers/exercises/1-pointers_intro/code.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Message struct {
|
||||
Recipient string
|
||||
Text string
|
||||
}
|
||||
|
||||
// Don't touch above this line
|
||||
|
||||
func sendMessage(m Message) {
|
||||
fmt.Printf("To: %v\n", &m.Recipient)
|
||||
fmt.Printf("Message: %v\n", &m.Text)
|
||||
}
|
||||
|
||||
// Don't touch below this line
|
||||
|
||||
func test(recipient string, text string) {
|
||||
m := Message{Recipient: recipient, Text: text}
|
||||
sendMessage(m)
|
||||
fmt.Println("=====================================")
|
||||
}
|
||||
|
||||
func main() {
|
||||
test("Lane", "Textio is getting better everyday!")
|
||||
test("Allan", "This pointer stuff is weird...")
|
||||
test("Tiffany", "What time will you be home for dinner?")
|
||||
}
|
||||
29
course/11-pointers/exercises/1-pointers_intro/complete.go
Normal file
29
course/11-pointers/exercises/1-pointers_intro/complete.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Message struct {
|
||||
Recipient string
|
||||
Text string
|
||||
}
|
||||
|
||||
// Don't touch above this line
|
||||
|
||||
func sendMessage(m Message) {
|
||||
fmt.Printf("To: %v\n", m.Recipient)
|
||||
fmt.Printf("Message: %v\n", m.Text)
|
||||
}
|
||||
|
||||
// Don't touch below this line
|
||||
|
||||
func test(recipient string, text string) {
|
||||
m := Message{Recipient: recipient, Text: text}
|
||||
sendMessage(m)
|
||||
fmt.Println("=====================================")
|
||||
}
|
||||
|
||||
func main() {
|
||||
test("Lane", "Textio is getting better everyday!")
|
||||
test("Allan", "This pointer stuff is weird...")
|
||||
test("Tiffany", "What time will you be home for dinner?")
|
||||
}
|
||||
9
course/11-pointers/exercises/1-pointers_intro/expected.txt
Executable file
9
course/11-pointers/exercises/1-pointers_intro/expected.txt
Executable file
@@ -0,0 +1,9 @@
|
||||
To: Lane
|
||||
Message: Textio is getting better everyday!
|
||||
=====================================
|
||||
To: Allan
|
||||
Message: This pointer stuff is weird...
|
||||
=====================================
|
||||
To: Tiffany
|
||||
Message: What time will you be home for dinner?
|
||||
=====================================
|
||||
33
course/11-pointers/exercises/1-pointers_intro/readme.md
Normal file
33
course/11-pointers/exercises/1-pointers_intro/readme.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Introduction to Pointers
|
||||
|
||||
As we have learned, a variable is a named location in memory that stores a value. We can manipulate the value of a variable by assigning a new value to it or by performing operations on it. When we assign a value to a variable, we are storing that value in a specific location in memory.
|
||||
|
||||
```go
|
||||
x := 42
|
||||
// "x" is the name of a location in memory. That location is storing the integer value of 42
|
||||
```
|
||||
|
||||
## A pointer is a variable
|
||||
|
||||
A pointer is a variable that stores the *memory address* of another variable. This means that a pointer "points to" the *location* of where the data is stored *NOT* the actual data itself.
|
||||
|
||||
The `*` syntax defines a pointer:
|
||||
|
||||
```go
|
||||
var p *int
|
||||
```
|
||||
|
||||
The `&` operator generates a pointer to its operand.
|
||||
|
||||
```go
|
||||
myString := "hello"
|
||||
myStringPtr = &myString
|
||||
```
|
||||
|
||||
## Why are pointers useful?
|
||||
|
||||
Pointers allow us to manipulate data in memory directly, without making copies or duplicating data. This can make programs more efficient and allow us to do things that would be difficult or impossible without them.
|
||||
|
||||
## Assignment
|
||||
|
||||
Fix the bug in the `sendMessage` function. It's *supposed* to print a nicely formatted message to the console containing an SMS's recipient and message body. However, it's not working as expected. Run the code and see what happens, then fix the bug.
|
||||
35
course/11-pointers/exercises/2-pointers_practice/code.go
Normal file
35
course/11-pointers/exercises/2-pointers_practice/code.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func removeProfanity(message *string) {
|
||||
// ?
|
||||
}
|
||||
|
||||
// don't touch below this line
|
||||
|
||||
func test(messages []string) {
|
||||
for _, message := range messages {
|
||||
removeProfanity(&message)
|
||||
fmt.Println(message)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
messages1 := []string{
|
||||
"well shoot, this is awful",
|
||||
"dang robots",
|
||||
"dang them to heck",
|
||||
}
|
||||
|
||||
messages2 := []string{
|
||||
"well shoot",
|
||||
"Allan is going straight to heck",
|
||||
"dang... that's a tough break",
|
||||
}
|
||||
|
||||
test(messages1)
|
||||
test(messages2)
|
||||
}
|
||||
40
course/11-pointers/exercises/2-pointers_practice/complete.go
Normal file
40
course/11-pointers/exercises/2-pointers_practice/complete.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func removeProfanity(message *string) {
|
||||
messageVal := *message
|
||||
messageVal = strings.ReplaceAll(messageVal, "dang", "****")
|
||||
messageVal = strings.ReplaceAll(messageVal, "shoot", "*****")
|
||||
messageVal = strings.ReplaceAll(messageVal, "heck", "****")
|
||||
*message = messageVal
|
||||
}
|
||||
|
||||
// don't touch below this line
|
||||
|
||||
func test(messages []string) {
|
||||
for _, message := range messages {
|
||||
removeProfanity(&message)
|
||||
fmt.Println(message)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
messages1 := []string{
|
||||
"well shoot, this is awful",
|
||||
"dang robots",
|
||||
"dang them to heck",
|
||||
}
|
||||
|
||||
messages2 := []string{
|
||||
"well shoot",
|
||||
"Allan is going straight to heck",
|
||||
"dang... that's a tough break",
|
||||
}
|
||||
|
||||
test(messages1)
|
||||
test(messages2)
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
well *****, this is awful
|
||||
**** robots
|
||||
**** them to ****
|
||||
well *****
|
||||
Allan is going straight to ****
|
||||
****... that's a tough break
|
||||
45
course/11-pointers/exercises/2-pointers_practice/readme.md
Normal file
45
course/11-pointers/exercises/2-pointers_practice/readme.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Pointers
|
||||
|
||||
Pointers hold the memory address of a value.
|
||||
|
||||
The `*` syntax defines a pointer:
|
||||
|
||||
```go
|
||||
var p *int
|
||||
```
|
||||
|
||||
A pointer's zero value is `nil`
|
||||
|
||||
The & operator generates a pointer to its operand.
|
||||
|
||||
```go
|
||||
myString := "hello"
|
||||
myStringPtr = &myString
|
||||
```
|
||||
|
||||
The * dereferences a pointer to gain access to the value
|
||||
|
||||
```go
|
||||
fmt.Println(*myStringPtr) // read myString through the pointer
|
||||
*myStringPtr = "world" // set myString through the pointer
|
||||
```
|
||||
|
||||
Unlike C, Go has no [pointer arithmetic](https://www.tutorialspoint.com/cprogramming/c_pointer_arithmetic.htm)
|
||||
|
||||
## Just because you can doesn't mean you should
|
||||
|
||||
We're doing this exercise to understand that pointers **can** be used in this way. That said, pointers can be *very* dangerous. It's generally a better idea to have your functions accept non-pointers and return new values rather than mutating pointer inputs.
|
||||
|
||||
## Assignment
|
||||
|
||||
Complete the `removeProfanity` function.
|
||||
|
||||
It should use the [strings.ReplaceAll](https://pkg.go.dev/strings#ReplaceAll) function to replace all instances of the following words in the input `message` with asterisks.
|
||||
|
||||
* "dang" -> "****"
|
||||
* "shoot" -> "*****"
|
||||
* "heck" -> "****"
|
||||
|
||||
It should *mutate* the value in the pointer and return nothing.
|
||||
|
||||
Do *not* alter the function signature.
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"question": "What is the value of *y after the code on the left executes?",
|
||||
"answers": [
|
||||
"100",
|
||||
"a memory address pointing to x",
|
||||
"nil",
|
||||
"50"
|
||||
]
|
||||
}
|
||||
13
course/11-pointers/exercises/3-pointers_quiz/readme.md
Normal file
13
course/11-pointers/exercises/3-pointers_quiz/readme.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Pointers Quiz
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
var x int = 50
|
||||
var y *int = &x
|
||||
*y = 100
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"question": "What is the value of x after the code on the left executes?",
|
||||
"answers": [
|
||||
"100",
|
||||
"a memory address pointing to x",
|
||||
"50",
|
||||
"nil"
|
||||
]
|
||||
}
|
||||
13
course/11-pointers/exercises/3b-pointers_quiz/readme.md
Normal file
13
course/11-pointers/exercises/3b-pointers_quiz/readme.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Pointers Quiz
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
var x int = 50
|
||||
var y *int = &x
|
||||
*y = 100
|
||||
}
|
||||
```
|
||||
51
course/11-pointers/exercises/4-nil_dereference/code.go
Normal file
51
course/11-pointers/exercises/4-nil_dereference/code.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func removeProfanity(message *string) {
|
||||
// ?
|
||||
messageVal := *message
|
||||
messageVal = strings.ReplaceAll(messageVal, "dang", "****")
|
||||
messageVal = strings.ReplaceAll(messageVal, "shoot", "*****")
|
||||
messageVal = strings.ReplaceAll(messageVal, "heck", "****")
|
||||
*message = messageVal
|
||||
}
|
||||
|
||||
// don't touch below this line
|
||||
|
||||
func test(messages []string) {
|
||||
for _, message := range messages {
|
||||
if message == "" {
|
||||
removeProfanity(nil)
|
||||
fmt.Println("nil message detected")
|
||||
} else {
|
||||
removeProfanity(&message)
|
||||
fmt.Println(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
messages := []string{
|
||||
"well shoot, this is awful",
|
||||
"",
|
||||
"dang robots",
|
||||
"dang them to heck",
|
||||
"",
|
||||
}
|
||||
|
||||
messages2 := []string{
|
||||
"well shoot",
|
||||
"",
|
||||
"Allan is going straight to heck",
|
||||
"dang... that's a tough break",
|
||||
"",
|
||||
}
|
||||
|
||||
test(messages)
|
||||
test(messages2)
|
||||
|
||||
}
|
||||
53
course/11-pointers/exercises/4-nil_dereference/complete.go
Normal file
53
course/11-pointers/exercises/4-nil_dereference/complete.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func removeProfanity(message *string) {
|
||||
if message == nil {
|
||||
return
|
||||
}
|
||||
messageVal := *message
|
||||
messageVal = strings.ReplaceAll(messageVal, "dang", "****")
|
||||
messageVal = strings.ReplaceAll(messageVal, "shoot", "*****")
|
||||
messageVal = strings.ReplaceAll(messageVal, "heck", "****")
|
||||
*message = messageVal
|
||||
}
|
||||
|
||||
// don't touch below this line
|
||||
|
||||
func test(messages []string) {
|
||||
for _, message := range messages {
|
||||
if message == "" {
|
||||
removeProfanity(nil)
|
||||
fmt.Println("nil message detected")
|
||||
} else {
|
||||
removeProfanity(&message)
|
||||
fmt.Println(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
messages := []string{
|
||||
"well shoot, this is awful",
|
||||
"",
|
||||
"dang robots",
|
||||
"dang them to heck",
|
||||
"",
|
||||
}
|
||||
|
||||
messages2 := []string{
|
||||
"well shoot",
|
||||
"",
|
||||
"Allan is going straight to heck",
|
||||
"dang... that's a tough break",
|
||||
"",
|
||||
}
|
||||
|
||||
test(messages)
|
||||
test(messages2)
|
||||
|
||||
}
|
||||
10
course/11-pointers/exercises/4-nil_dereference/expected.txt
Normal file
10
course/11-pointers/exercises/4-nil_dereference/expected.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
well *****, this is awful
|
||||
nil message detected
|
||||
**** robots
|
||||
**** them to ****
|
||||
nil message detected
|
||||
well *****
|
||||
nil message detected
|
||||
Allan is going straight to ****
|
||||
****... that's a tough break
|
||||
nil message detected
|
||||
9
course/11-pointers/exercises/4-nil_dereference/readme.md
Normal file
9
course/11-pointers/exercises/4-nil_dereference/readme.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Nil Pointers
|
||||
|
||||
Pointers can be very dangerous.
|
||||
|
||||
If a pointer points to nothing (the zero value of the pointer type) then dereferencing it will cause a runtime error (a [panic](https://gobyexample.com/panic)) that crashes the program. Generally speaking, whenever you're dealing with pointers you should check if it's `nil` before trying to dereference it.
|
||||
|
||||
## Assignment
|
||||
|
||||
Let's make our profanity checker *safe*. Update the `removeProfanity` function. If `message` is `nil`, `return` early to avoid a [panic](https://gobyexample.com/panic). After all, there are no bad words to remove.
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"question": "Which is more widely used in Go?",
|
||||
"answers": [
|
||||
"Pointer receivers",
|
||||
"Value receivers"
|
||||
]
|
||||
}
|
||||
47
course/11-pointers/exercises/5-pointer_receiver/readme.md
Normal file
47
course/11-pointers/exercises/5-pointer_receiver/readme.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# Pointer Receivers
|
||||
|
||||
A receiver type on a method can be a pointer.
|
||||
|
||||
Methods with pointer receivers can modify the value to which the receiver points. Since methods often need to modify their receiver, pointer receivers are *more common* than value receivers.
|
||||
|
||||
## Pointer receiver
|
||||
|
||||
```go
|
||||
type car struct {
|
||||
color string
|
||||
}
|
||||
|
||||
func (c *car) setColor(color string) {
|
||||
c.color = color
|
||||
}
|
||||
|
||||
func main() {
|
||||
c := car{
|
||||
color: "white",
|
||||
}
|
||||
c.setColor("blue")
|
||||
fmt.Println(c.color)
|
||||
// prints "blue"
|
||||
}
|
||||
```
|
||||
|
||||
## Non-pointer receiver
|
||||
|
||||
```go
|
||||
type car struct {
|
||||
color string
|
||||
}
|
||||
|
||||
func (c car) setColor(color string) {
|
||||
c.color = color
|
||||
}
|
||||
|
||||
func main() {
|
||||
c := car{
|
||||
color: "white",
|
||||
}
|
||||
c.setColor("blue")
|
||||
fmt.Println(c.color)
|
||||
// prints "white"
|
||||
}
|
||||
```
|
||||
49
course/11-pointers/exercises/6-pointer_receiver_code/code.go
Normal file
49
course/11-pointers/exercises/6-pointer_receiver_code/code.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func (e email) setMessage(newMessage string) {
|
||||
e.message = newMessage
|
||||
}
|
||||
|
||||
// don't edit below this line
|
||||
|
||||
type email struct {
|
||||
message string
|
||||
fromAddress string
|
||||
toAddress string
|
||||
}
|
||||
|
||||
func test(e *email, newMessage string) {
|
||||
fmt.Println("-- before --")
|
||||
e.print()
|
||||
fmt.Println("-- end before --")
|
||||
e.setMessage("this is my second draft")
|
||||
fmt.Println("-- after --")
|
||||
e.print()
|
||||
fmt.Println("-- end after --")
|
||||
fmt.Println("==========================")
|
||||
}
|
||||
|
||||
func (e email) print() {
|
||||
fmt.Println("message:", e.message)
|
||||
fmt.Println("fromAddress:", e.fromAddress)
|
||||
fmt.Println("toAddress:", e.toAddress)
|
||||
}
|
||||
|
||||
func main() {
|
||||
test(&email{
|
||||
message: "this is my first draft",
|
||||
fromAddress: "sandra@mailio-test.com",
|
||||
toAddress: "bullock@mailio-test.com",
|
||||
}, "this is my second draft")
|
||||
|
||||
test(&email{
|
||||
message: "this is my third draft",
|
||||
fromAddress: "sandra@mailio-test.com",
|
||||
toAddress: "bullock@mailio-test.com",
|
||||
}, "this is my fourth draft")
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func (e *email) setMessage(newMessage string) {
|
||||
e.message = newMessage
|
||||
}
|
||||
|
||||
// don't edit below this line
|
||||
|
||||
type email struct {
|
||||
message string
|
||||
fromAddress string
|
||||
toAddress string
|
||||
}
|
||||
|
||||
func test(e *email, newMessage string) {
|
||||
fmt.Println("-- before --")
|
||||
e.print()
|
||||
fmt.Println("-- end before --")
|
||||
e.setMessage("this is my second draft")
|
||||
fmt.Println("-- after --")
|
||||
e.print()
|
||||
fmt.Println("-- end after --")
|
||||
fmt.Println("==========================")
|
||||
}
|
||||
|
||||
func (e email) print() {
|
||||
fmt.Println("message:", e.message)
|
||||
fmt.Println("fromAddress:", e.fromAddress)
|
||||
fmt.Println("toAddress:", e.toAddress)
|
||||
}
|
||||
|
||||
func main() {
|
||||
test(&email{
|
||||
message: "this is my first draft",
|
||||
fromAddress: "sandra@mailio-test.com",
|
||||
toAddress: "bullock@mailio-test.com",
|
||||
}, "this is my second draft")
|
||||
|
||||
test(&email{
|
||||
message: "this is my third draft",
|
||||
fromAddress: "sandra@mailio-test.com",
|
||||
toAddress: "bullock@mailio-test.com",
|
||||
}, "this is my fourth draft")
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
-- before --
|
||||
message: this is my first draft
|
||||
fromAddress: sandra@mailio-test.com
|
||||
toAddress: bullock@mailio-test.com
|
||||
-- end before --
|
||||
-- after --
|
||||
message: this is my second draft
|
||||
fromAddress: sandra@mailio-test.com
|
||||
toAddress: bullock@mailio-test.com
|
||||
-- end after --
|
||||
==========================
|
||||
-- before --
|
||||
message: this is my third draft
|
||||
fromAddress: sandra@mailio-test.com
|
||||
toAddress: bullock@mailio-test.com
|
||||
-- end before --
|
||||
-- after --
|
||||
message: this is my second draft
|
||||
fromAddress: sandra@mailio-test.com
|
||||
toAddress: bullock@mailio-test.com
|
||||
-- end after --
|
||||
==========================
|
||||
@@ -0,0 +1,33 @@
|
||||
# Pointer Receiver Code
|
||||
|
||||
Methods with pointer receivers don't require that a pointer is used to call the method. The pointer will automatically be derived from the value.
|
||||
|
||||
```go
|
||||
type circle struct {
|
||||
x int
|
||||
y int
|
||||
radius int
|
||||
}
|
||||
|
||||
func (c *circle) grow(){
|
||||
c.radius *= 2
|
||||
}
|
||||
|
||||
func main(){
|
||||
c := circle{
|
||||
x: 1,
|
||||
y: 2,
|
||||
radius: 4,
|
||||
}
|
||||
|
||||
// notice c is not a pointer in the calling function
|
||||
// but the method still gains access to a pointer to c
|
||||
c.grow()
|
||||
fmt.Println(c.radius)
|
||||
// prints 8
|
||||
}
|
||||
```
|
||||
|
||||
## Assignment
|
||||
|
||||
Fix the bug in the code so that `setMessage` sets the `message` field of the given email structure, and the new value persists outside the scope of the `setMessage` method.
|
||||
Reference in New Issue
Block a user