This commit is contained in:
wagslane
2023-05-01 15:25:27 -06:00
parent f8912668b8
commit 9be3074de6
868 changed files with 58698 additions and 2 deletions

View File

@@ -0,0 +1,28 @@
package main
import "fmt"
type messageToSend struct {
}
// don't edit below this line
func test(m messageToSend) {
fmt.Printf("Sending message: '%s' to: %v\n", m.message, m.phoneNumber)
fmt.Println("====================================")
}
func main() {
test(messageToSend{
phoneNumber: 148255510981,
message: "Thanks for signing up",
})
test(messageToSend{
phoneNumber: 148255510982,
message: "Love to have you aboard!",
})
test(messageToSend{
phoneNumber: 148255510983,
message: "We're so excited to have you",
})
}

View File

@@ -0,0 +1,30 @@
package main
import "fmt"
type messageToSend struct {
phoneNumber int
message string
}
// don't edit below this line
func test(m messageToSend) {
fmt.Printf("Sending message: '%s' to: %v\n", m.message, m.phoneNumber)
fmt.Println("====================================")
}
func main() {
test(messageToSend{
phoneNumber: 148255510981,
message: "Thanks for signing up",
})
test(messageToSend{
phoneNumber: 148255510982,
message: "Love to have you aboard!",
})
test(messageToSend{
phoneNumber: 148255510983,
message: "We're so excited to have you",
})
}

View File

@@ -0,0 +1,6 @@
Sending message: 'Thanks for signing up' to: 148255510981
====================================
Sending message: 'Love to have you aboard!' to: 148255510982
====================================
Sending message: 'We're so excited to have you' to: 148255510983
====================================

View File

@@ -0,0 +1,23 @@
# Structs in Go
We use structs in Go to represent structured data. It's often convenient to group different types of variables together. For example, if we want to represent a car we could do the following:
```go
type car struct {
Make string
Model string
Height int
Width int
}
```
This creates a new struct type called `car`. All cars have a `Make`, `Model`, `Height` and `Width`.
In Go, you will often use a struct to represent information that you would have used a dictionary for in Python, or an object literal for in JavaScript.
## Assignment
Complete the `messageToSend` struct definition. It needs two fields:
* `phoneNumber` - an integer
* `message` - a string.

View File

@@ -0,0 +1,86 @@
package main
import (
"fmt"
)
type messageToSend struct {
message string
sender user
recipient user
}
type user struct {
name string
number int
}
func canSendMessage(mToSend messageToSend) bool {
// ?
return true
}
// don't touch below this line
func test(mToSend messageToSend) {
fmt.Printf(`sending "%s" from %s (%v) to %s (%v)...`,
mToSend.message,
mToSend.sender.name,
mToSend.sender.number,
mToSend.recipient.name,
mToSend.recipient.number,
)
fmt.Println()
if canSendMessage(mToSend) {
fmt.Println("...sent!")
} else {
fmt.Println("...can't send message")
}
fmt.Println("====================================")
}
func main() {
test(messageToSend{
message: "you have an appointment tommorow",
sender: user{
name: "Brenda Halafax",
number: 16545550987,
},
recipient: user{
name: "Sally Sue",
number: 19035558973,
},
})
test(messageToSend{
message: "you have an event tommorow",
sender: user{
number: 16545550987,
},
recipient: user{
name: "Suzie Sall",
number: 0,
},
})
test(messageToSend{
message: "you have an party tommorow",
sender: user{
name: "Njorn Halafax",
number: 16545550987,
},
recipient: user{
name: "Sally Sue",
number: 19035558973,
},
})
test(messageToSend{
message: "you have a birthday tommorow",
sender: user{
name: "Eli Halafax",
number: 0,
},
recipient: user{
name: "Whitaker Sue",
number: 19035558973,
},
})
}

View File

@@ -0,0 +1,97 @@
package main
import (
"fmt"
)
type messageToSend struct {
message string
sender user
recipient user
}
type user struct {
name string
number int
}
func canSendMessage(mToSend messageToSend) bool {
if mToSend.recipient.number == 0 {
return false
}
if mToSend.sender.number == 0 {
return false
}
if mToSend.recipient.name == "" {
return false
}
if mToSend.sender.name == "" {
return false
}
return true
}
// don't touch below this line
func test(mToSend messageToSend) {
fmt.Printf(`sending "%s" from %s (%v) to %s (%v)...`,
mToSend.message,
mToSend.sender.name,
mToSend.sender.number,
mToSend.recipient.name,
mToSend.recipient.number,
)
fmt.Println()
if canSendMessage(mToSend) {
fmt.Println("...sent!")
} else {
fmt.Println("...can't send message")
}
fmt.Println("====================================")
}
func main() {
test(messageToSend{
message: "you have an appointment tommorow",
sender: user{
name: "Brenda Halafax",
number: 16545550987,
},
recipient: user{
name: "Sally Sue",
number: 19035558973,
},
})
test(messageToSend{
message: "you have an event tommorow",
sender: user{
number: 16545550987,
},
recipient: user{
name: "Suzie Sall",
number: 0,
},
})
test(messageToSend{
message: "you have an party tommorow",
sender: user{
name: "Njorn Halafax",
number: 16545550987,
},
recipient: user{
name: "Sally Sue",
number: 19035558973,
},
})
test(messageToSend{
message: "you have a birthday tommorow",
sender: user{
name: "Eli Halafax",
number: 0,
},
recipient: user{
name: "Whitaker Sue",
number: 19035558973,
},
})
}

View File

@@ -0,0 +1,12 @@
sending "you have an appointment tommorow" from Brenda Halafax (16545550987) to Sally Sue (19035558973)...
...sent!
====================================
sending "you have an event tommorow" from (16545550987) to Suzie Sall (0)...
...can't send message
====================================
sending "you have an party tommorow" from Njorn Halafax (16545550987) to Sally Sue (19035558973)...
...sent!
====================================
sending "you have a birthday tommorow" from Eli Halafax (0) to Whitaker Sue (19035558973)...
...can't send message
====================================

View File

@@ -0,0 +1,34 @@
# Nested structs in Go
Structs can be nested to represent more complex entities:
```go
type car struct {
Make string
Model string
Height int
Width int
FrontWheel Wheel
BackWheel Wheel
}
type Wheel struct {
Radius int
Material string
}
```
The fields of a struct can be accessed using the dot `.` operator.
```go
myCar := car{}
myCar.FrontWheel.Radius = 5
```
## Assignment
Textio has a bug, we've been sending texts with information missing! Before we send text messages in Textio, we should check to make sure the required fields have non-zero values.
Notice that the `user` struct is a nested struct within the `messageToSend` struct. Both `sender` and `recipient` are `user` struct types.
Complete the `canSendMessage` function. It should return `true` only if the `sender` and `recipient` fields each contain a `name` and a `number`. If any of the default zero values are present, return `false` instead.

View File

@@ -0,0 +1,9 @@
{
"question": "What is a good reason to use an anonymous struct?",
"answers": [
"It is only being used once",
"You're worried about user privacy",
"You're worried about security",
"You need your code to be faster"
]
}

View File

@@ -0,0 +1,39 @@
# Anonymous Structs in Go
An anonymous struct is just like a normal struct, but it is defined without a name and therefore cannot be referenced elsewhere in the code.
To create an anonymous struct, just instantiate the instance immediately using a second pair of brackets after declaring the type:
```go
myCar := struct {
Make string
Model string
} {
Make: "tesla",
Model: "model 3"
}
```
You can even nest anonymous structs as fields within other structs:
```go
type car struct {
Make string
Model string
Height int
Width int
// Wheel is a field containing an anonymous struct
Wheel struct {
Radius int
Material string
}
}
```
## When should you use an anonymous struct?
In general, *prefer named structs*. Named structs make it easier to read and understand your code, and they have the nice side-effect of being reusable. I sometimes use anonymous structs when I *know* I won't ever need to use a struct again. For example, sometimes I'll use one to create the shape of some JSON data in HTTP handlers.
If a struct is only meant to be used once, then it makes sense to declare it in such a way that developers down the road wont be tempted to accidentally use it again.
You can read more about [anonymous structs here](https://blog.boot.dev/golang/anonymous-structs-golang/) if you're curious.

View File

@@ -0,0 +1,8 @@
{
"question": "What's one advantage of using an anonymous struct?",
"answers": [
"Anonymous structs prevent you from re-using a struct definition you never intended to re-use",
"Anonymous structs make your code run faster",
"Anonymous structs can be compiled more quickly"
]
}

View File

@@ -0,0 +1,39 @@
# Anonymous Structs in Go
An anonymous struct is just like a normal struct, but it is defined without a name and therefore cannot be referenced elsewhere in the code.
To create an anonymous struct, just instantiate the instance immediately using a second pair of brackets after declaring the type:
```go
myCar := struct {
Make string
Model string
} {
Make: "tesla",
Model: "model 3"
}
```
You can even nest anonymous structs as fields within other structs:
```go
type car struct {
Make string
Model string
Height int
Width int
// Wheel is a field containing an anonymous struct
Wheel struct {
Radius int
Material string
}
}
```
## When should you use an anonymous struct?
In general, *prefer named structs*. Named structs make it easier to read and understand your code, and they have the nice side-effect of being reusable. I sometimes use anonymous structs when I *know* I won't ever need to use a struct again. For example, sometimes I'll use one to create the shape of some JSON data in HTTP handlers.
If a struct is only meant to be used once, then it makes sense to declare it in such a way that developers down the road wont be tempted to accidentally use it again.
You can read more about [anonymous structs here](https://blog.boot.dev/golang/anonymous-structs-golang/) if you're curious.

View File

@@ -0,0 +1,45 @@
package main
import "fmt"
type sender struct {
rateLimit int
}
type user struct {
name string
number int
}
// don't edit below this line
func test(s sender) {
fmt.Println("Sender name:", s.name)
fmt.Println("Sender number:", s.number)
fmt.Println("Sender rateLimit:", s.rateLimit)
fmt.Println("====================================")
}
func main() {
test(sender{
rateLimit: 10000,
user: user{
name: "Deborah",
number: 18055558790,
},
})
test(sender{
rateLimit: 5000,
user: user{
name: "Sarah",
number: 19055558790,
},
})
test(sender{
rateLimit: 1000,
user: user{
name: "Sally",
number: 19055558790,
},
})
}

View File

@@ -0,0 +1,46 @@
package main
import "fmt"
type sender struct {
rateLimit int
user
}
type user struct {
name string
number int
}
// don't edit below this line
func test(s sender) {
fmt.Println("Sender name:", s.name)
fmt.Println("Sender number:", s.number)
fmt.Println("Sender rateLimit:", s.rateLimit)
fmt.Println("====================================")
}
func main() {
test(sender{
rateLimit: 10000,
user: user{
name: "Deborah",
number: 18055558790,
},
})
test(sender{
rateLimit: 5000,
user: user{
name: "Sarah",
number: 19055558790,
},
})
test(sender{
rateLimit: 1000,
user: user{
name: "Sally",
number: 19055558790,
},
})
}

View File

@@ -0,0 +1,12 @@
Sender name: Deborah
Sender number: 18055558790
Sender rateLimit: 10000
====================================
Sender name: Sarah
Sender number: 19055558790
Sender rateLimit: 5000
====================================
Sender name: Sally
Sender number: 19055558790
Sender rateLimit: 1000
====================================

View File

@@ -0,0 +1,46 @@
# Embedded Structs
Go is not an [object-oriented](https://en.wikipedia.org/wiki/Object-oriented_programming) language. However, embedded structs provide a kind of *data-only* inheritance that can be useful at times. Keep in mind, Go doesn't support classes or inheritance in the complete sense, embedded structs are just a way to elevate and share fields between struct definitions.
```go
type car struct {
make string
model string
}
type truck struct {
// "car" is embedded, so the definition of a
// "truck" now also additionally contains all
// of the fields of the car struct
car
bedSize int
}
```
## Embedded vs nested
* An embedded struct's fields are accessed at the top level, unlike nested structs.
* Promoted fields can be accessed like normal fields except that they can't be used in [composite literals](https://golang.org/ref/spec#Composite_literals)
```go
lanesTruck := truck{
bedSize: 10,
car: car{
make: "toyota",
model: "camry",
},
}
fmt.Println(lanesTruck.bedSize)
// embedded fields promoted to the top-level
// instead of lanesTruck.car.make
fmt.Println(lanesTruck.make)
fmt.Println(lanesTruck.model)
```
## Assignment
At Textio, a "user" struct represents an account holder, and a "sender" is just a "user" with some "sender" specific data. A "sender" is a user that has a `rateLimit` field that tells us how many messages they are allowed to send.
Fix the system by using an embedded struct as expected by the test code.

View File

@@ -0,0 +1,32 @@
package main
import "fmt"
type authenticationInfo struct {
username string
password string
}
// ?
// don't touch below this line
func test(authInfo authenticationInfo) {
fmt.Println(authInfo.getBasicAuth())
fmt.Println("====================================")
}
func main() {
test(authenticationInfo{
username: "Google",
password: "12345",
})
test(authenticationInfo{
username: "Bing",
password: "98765",
})
test(authenticationInfo{
username: "DDG",
password: "76921",
})
}

View File

@@ -0,0 +1,34 @@
package main
import "fmt"
type authenticationInfo struct {
username string
password string
}
func (authInfo authenticationInfo) getBasicAuth() string {
return "Authorization: Basic " + authInfo.username + ":" + authInfo.password
}
// don't touch below this line
func test(authInfo authenticationInfo) {
fmt.Println(authInfo.getBasicAuth())
fmt.Println("====================================")
}
func main() {
test(authenticationInfo{
username: "Google",
password: "12345",
})
test(authenticationInfo{
username: "Bing",
password: "98765",
})
test(authenticationInfo{
username: "DDG",
password: "76921",
})
}

View File

@@ -0,0 +1,6 @@
Authorization: Basic Google:12345
====================================
Authorization: Basic Bing:98765
====================================
Authorization: Basic DDG:76921
====================================

View File

@@ -0,0 +1,37 @@
# Struct methods in Go
While Go is **not** object-oriented, it does support methods that can be defined on structs. Methods are just functions that have a receiver. A receiver is a special parameter that syntactically goes *before* the name of the function.
```go
type rect struct {
width int
height int
}
// area has a receiver of (r rect)
func (r rect) area() int {
return r.width * r.height
}
r := rect{
width: 5,
height: 10,
}
fmt.Println(r.area())
// prints 50
```
A receiver is just a special kind of function parameter. Receivers are important because they will, as you'll learn in the exercises to come, allow us to define interfaces that our structs (and other types) can implement.
## Assignment
Let's clean up Textio's authentication logic. We store our user's authentication data inside an `authenticationInfo` struct. We need a method that can take that data and return a basic authorization string.
The format of the string should be:
```
Authorization: Basic USERNAME:PASSWORD
```
Create a method on the `authenticationInfo` struct called `getBasicAuth` that returns the formatted string.