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,51 @@
package main
import (
"fmt"
)
func sendSMSToCouple(msgToCustomer, msgToSpouse string) (float64, error) {
// ?
}
// don't edit below this line
func sendSMS(message string) (float64, error) {
const maxTextLen = 25
const costPerChar = .0002
if len(message) > maxTextLen {
return 0.0, fmt.Errorf("can't send texts over %v characters", maxTextLen)
}
return costPerChar * float64(len(message)), nil
}
func test(msgToCustomer, msgToSpouse string) {
defer fmt.Println("========")
fmt.Println("Message for customer:", msgToCustomer)
fmt.Println("Message for spouse:", msgToSpouse)
totalCost, err := sendSMSToCouple(msgToCustomer, msgToSpouse)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Printf("Total cost: $%.4f\n", totalCost)
}
func main() {
test(
"Thanks for coming in to our flower shop today!",
"We hope you enjoyed your gift.",
)
test(
"Thanks for joining us!",
"Have a good day.",
)
test(
"Thank you.",
"Enjoy!",
)
test(
"We loved having you in!",
"We hope the rest of your evening is absolutely fantastic.",
)
}

View File

@@ -0,0 +1,60 @@
package main
import (
"fmt"
)
func sendSMSToCouple(msgToCustomer, msgToSpouse string) (float64, error) {
cost, err := sendSMS(msgToCustomer)
if err != nil {
return 0.0, err
}
costSpouse, err := sendSMS(msgToSpouse)
if err != nil {
return 0, err
}
return costSpouse + cost, nil
}
// don't edit below this line
func sendSMS(message string) (float64, error) {
const maxTextLen = 25
const costPerChar = .0002
if len(message) > maxTextLen {
return 0.0, fmt.Errorf("can't send texts over %v characters", maxTextLen)
}
return costPerChar * float64(len(message)), nil
}
func test(msgToCustomer, msgToSpouse string) {
defer fmt.Println("========")
fmt.Println("Message for customer:", msgToCustomer)
fmt.Println("Message for spouse:", msgToSpouse)
totalCost, err := sendSMSToCouple(msgToCustomer, msgToSpouse)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Printf("Total cost: $%.4f\n", totalCost)
}
func main() {
test(
"Thanks for coming in to our flower shop today!",
"We hope you enjoyed your gift.",
)
test(
"Thanks for joining us!",
"Have a good day.",
)
test(
"Thank you.",
"Enjoy!",
)
test(
"We loved having you in!",
"We hope the rest of your evening is absolutely fantastic.",
)
}

View File

@@ -0,0 +1,16 @@
Message for customer: Thanks for coming in to our flower shop today!
Message for spouse: We hope you enjoyed your gift.
Error: can't send texts over 25 characters
========
Message for customer: Thanks for joining us!
Message for spouse: Have a good day.
Total cost: $0.0076
========
Message for customer: Thank you.
Message for spouse: Enjoy!
Total cost: $0.0032
========
Message for customer: We loved having you in!
Message for spouse: We hope the rest of your evening is absolutely fantastic.
Error: can't send texts over 25 characters
========

View File

@@ -0,0 +1,40 @@
# The Error Interface
Go programs express errors with `error` values. An Error is any type that implements the simple built-in [error interface](https://blog.golang.org/error-handling-and-go):
```go
type error interface {
Error() string
}
```
When something can go wrong in a function, that function should return an `error` as its last return value. Any code that calls a function that can return an `error` should handle errors by testing whether the error is `nil`.
```go
// Atoi converts a stringified number to an interger
i, err := strconv.Atoi("42b")
if err != nil {
fmt.Println("couldn't convert:", err)
// because "42b" isn't a valid integer, we print:
// couldn't convert: strconv.Atoi: parsing "42b": invalid syntax
// Note:
// 'parsing "42b": invalid syntax' is returned by the .Error() method
return
}
// if we get here, then
// i was converted successfully
```
A `nil` error denotes success; a non-nil error denotes failure.
## Assignment
We offer a product that allows businesses that use Textio to send pairs of messages to couples. It is mostly used by flower shops and movie theaters.
Complete the `sendSMSToCouple` function. It should send 2 messages, first to the customer, then to the customer's spouse.
1. Use `sendSMS()` to send the `msgToCustomer`. If an error is encountered, return `0.0` and the error.
2. Do the same for the `msgToSpouse`
3. If both messages are sent successfully, return the total cost of the messages added together.
*When you return a non-nil error in Go, it's conventional to return the "zero" values of all other return values.*

View File

@@ -0,0 +1,20 @@
package main
func getSMSErrorString(cost float64, recipient string) string {
// ?
}
// don't edit below this line
func test(cost float64, recipient string) {
s := getSMSErrorString(cost, recipient)
fmt.Println(s)
fmt.Println("====================================")
}
func main() {
test(1.4, "+1 (435) 555 0923")
test(2.1, "+2 (702) 555 3452")
test(32.1, "+1 (801) 555 7456")
test(14.4, "+1 (234) 555 6545")
}

View File

@@ -0,0 +1,27 @@
package main
import (
"fmt"
)
func getSMSErrorString(cost float64, recipient string) string {
return fmt.Sprintf("SMS that costs $%.2f to be sent to '%v' can not be sent",
cost,
recipient,
)
}
// don't edit below this line
func test(cost float64, recipient string) {
s := getSMSErrorString(cost, recipient)
fmt.Println(s)
fmt.Println("====================================")
}
func main() {
test(1.4, "+1 (435) 555 0923")
test(2.1, "+2 (702) 555 3452")
test(32.1, "+1 (801) 555 7456")
test(14.4, "+1 (234) 555 6545")
}

View File

@@ -0,0 +1,8 @@
SMS that costs $1.40 to be sent to '+1 (435) 555 0923' can not be sent
====================================
SMS that costs $2.10 to be sent to '+2 (702) 555 3452' can not be sent
====================================
SMS that costs $32.10 to be sent to '+1 (801) 555 7456' can not be sent
====================================
SMS that costs $14.40 to be sent to '+1 (234) 555 6545' can not be sent
====================================

View File

@@ -0,0 +1,47 @@
# Formatting strings review
A convenient way to format strings in Go is by using the standard library's [fmt.Sprintf()](https://pkg.go.dev/fmt#example-Sprintf) function. It's a string interpolation function, similar to JavaScript's built-in template literals. The `%v` substring uses the type's default formatting, which is often what you want.
### Default values
```go
const name = "Kim"
const age = 22
s := fmt.Sprintf("%v is %v years old.", name, age)
// s = "Kim is 22 years old."
```
The equivalent JavaScript code:
```js
const name = 'Kim'
const age = 22
s = `${name} is ${age} years old.`
// s = "Kim is 22 years old."
```
### Rounding floats
```go
fmt.Printf("I am %f years old", 10.523)
// I am 10.523000 years old
// The ".2" rounds the number to 2 decimal places
fmt.Printf("I am %.2f years old", 10.523)
// I am 10.53 years old
```
## Assignment
We need better error logs for our backend developers to help them debug their code.
Complete the `getSMSErrorString()` function. It should return a string with this format:
```
SMS that costs $COST to be sent to 'RECIPIENT' can not be sent
```
* `COST` is the cost of the SMS, always showing the price formatted to 2 decimal places.
* `RECIPIENT` is the stringified representation of the recipient's phone number
*Be sure to include the $ symbol and the single quotes*

View File

@@ -0,0 +1,41 @@
package main
import (
"fmt"
)
type divideError struct {
dividend float64
}
// ?
// don't edit below this line
func divide(dividend, divisor float64) (float64, error) {
if divisor == 0 {
// We convert the `divideError` struct to an `error` type by returning it
// as an error. As an error type, when it's printed its default value
// will be the result of the Error() method
return 0, divideError{dividend: dividend}
}
return dividend / divisor, nil
}
func test(dividend, divisor float64) {
defer fmt.Println("====================================")
fmt.Printf("Dividing %.2f by %.2f ...\n", dividend, divisor)
quotient, err := divide(dividend, divisor)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("Quotient: %.2f\n", quotient)
}
func main() {
test(10, 0)
test(10, 2)
test(15, 30)
test(6, 3)
}

View File

@@ -0,0 +1,43 @@
package main
import (
"fmt"
)
type divideError struct {
dividend float64
}
func (de divideError) Error() string {
return fmt.Sprintf("can not divide %v by zero", de.dividend)
}
// don't edit below this line
func divide(dividend, divisor float64) (float64, error) {
if divisor == 0 {
// We convert the `divideError` struct to an `error` type by returning it
// as an error. As an error type, when it's printed its default value
// will be the result of the Error() method
return 0, divideError{dividend: dividend}
}
return dividend / divisor, nil
}
func test(dividend, divisor float64) {
defer fmt.Println("====================================")
fmt.Printf("Dividing %.2f by %.2f ...\n", dividend, divisor)
quotient, err := divide(dividend, divisor)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("Quotient: %.2f\n", quotient)
}
func main() {
test(10, 0)
test(10, 2)
test(15, 30)
test(6, 3)
}

View File

@@ -0,0 +1,12 @@
Dividing 10.00 by 0.00 ...
can not divide 10 by zero
====================================
Dividing 10.00 by 2.00 ...
Quotient: 5.00
====================================
Dividing 15.00 by 30.00 ...
Quotient: 0.50
====================================
Dividing 6.00 by 3.00 ...
Quotient: 2.00
====================================

View File

@@ -0,0 +1,36 @@
# The Error Interface
Because errors are just interfaces, you can build your own custom types that implement the `error` interface. Here's an example of a `userError` struct that implements the `error` interface:
```go
type userError struct {
name string
}
func (e userError) Error() string {
return fmt.Sprintf("%v has a problem with their account", e.name)
}
```
It can then be used as an error:
```go
func sendSMS(msg, userName string) error {
if !canSendToUser(userName) {
return userError{name: userName}
}
...
}
```
## Assignment
Our users are frequently trying to run custom analytics queries on their message deliverability metrics, and end up writing a bad query that tries to divide a number by zero. It's become such a problem, that we think it would be best to make a specific type of error for division by zero.
Update the code so that the `divideError` type implements the `error` interface. Its `Error()` method should just return a string formatted in the following way:
```
can not divide DIVIDEND by zero
```
Where `DIVIDEND` is the actual dividend of the `divideError`. Use the `%v` [verb](https://pkg.go.dev/fmt#hdr-Printing) to format the dividend as a float.

View File

@@ -0,0 +1,8 @@
{
"question": "What is the underlying type of an error?",
"answers": [
"Interface",
"Struct",
"String"
]
}

View File

@@ -0,0 +1,5 @@
# Errors Quiz
Go programs express errors with `error` values. Error-values are any type that implements the simple built-in [error interface](https://blog.golang.org/error-handling-and-go).
Keep in mind that the way Go handles errors is fairly unique. Most languages treat errors as something special and different. For example, Python raises exception types and JavaScript throws and catches errors. In Go, an `error` is just another value that we handle like any other value - however, we want! There aren't any special keywords for dealing with them.

View File

@@ -0,0 +1,7 @@
{
"question": "Can a type be an error and also fulfill another interface?",
"answers": [
"Yes",
"No"
]
}

View File

@@ -0,0 +1,5 @@
# Errors Quiz
Go programs express errors with `error` values. Error-values are any type that implements the simple built-in [error interface](https://blog.golang.org/error-handling-and-go).
Keep in mind that the way Go handles errors is fairly unique. Most languages treat errors as something special and different. For example, Python raises exception types and JavaScript throws and catches errors. In Go, an `error` is just another value that we handle like any other value - however, we want! There aren't any special keywords for dealing with them.

View File

@@ -0,0 +1,33 @@
package main
import (
"errors"
"fmt"
)
func divide(x, y float64) (float64, error) {
if y == 0 {
// ?
}
return x / y, nil
}
// don't edit below this line
func test(x, y float64) {
defer fmt.Println("====================================")
fmt.Printf("Dividing %.2f by %.2f ...\n", x, y)
quotient, err := divide(x, y)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("Quotient: %.2f\n", quotient)
}
func main() {
test(10, 0)
test(10, 2)
test(15, 30)
test(6, 3)
}

View File

@@ -0,0 +1,33 @@
package main
import (
"errors"
"fmt"
)
func divide(x, y float64) (float64, error) {
if y == 0 {
return 0, errors.New("no dividing by 0")
}
return x / y, nil
}
// don't edit below this line
func test(x, y float64) {
defer fmt.Println("====================================")
fmt.Printf("Dividing %.2f by %.2f ...\n", x, y)
quotient, err := divide(x, y)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("Quotient: %.2f\n", quotient)
}
func main() {
test(10, 0)
test(10, 2)
test(15, 30)
test(6, 3)
}

View File

@@ -0,0 +1,12 @@
Dividing 10.00 by 0.00 ...
no dividing by 0
====================================
Dividing 10.00 by 2.00 ...
Quotient: 5.00
====================================
Dividing 15.00 by 30.00 ...
Quotient: 0.50
====================================
Dividing 6.00 by 3.00 ...
Quotient: 2.00
====================================

View File

@@ -0,0 +1,15 @@
# The Errors Package
The Go standard library provides an "errors" package that makes it easy to deal with errors.
Read the godoc for the [errors.New()](https://pkg.go.dev/errors#New) function, but here's a simple example:
```go
var err error = errors.New("something went wrong")
```
## Assignment
Twilio's software architects may have overcomplicated the requirements from the last coding assignment... oops. All we needed was a new generic error message that returns the string `no dividing by 0` when a user attempts to get us to perform the taboo.
Complete the `divide` function. Use the `errors.New()` function to return an error when `y == 0` that reads "no dividing by 0".