Go 自学:变量、函数、结构体、接口、错误处理
1. 打印变量数据类型
package mainimport "fmt"func main() {penniesPerText := 2.0fmt.Printf("The type of penniesPerText is %T\n", penniesPerText)
}
输出为:
The type of penniesPerText is float64
2. 同时给多个变量赋值
package mainimport "fmt"func main() {averageOpenRate, displayMessage := .23, "is the average open rate of your message."fmt.Println(averageOpenRate, displayMessage)
}
3. 条件句
package mainimport "fmt"func main() {messageLen := 10maxMessageLen := 20fmt.Println("Trying to send message of length:", messageLen, "and a max length of:", maxMessageLen)if messageLen <= maxMessageLen {fmt.Println("Message sent")} else {fmt.Println("Message not sent")}
}
输出为:
Trying to send message of length: 10 and a max length of: 20
Message sent
4. 忽略返回值
注意:Go不允许存在未经使用的变量。使用“_”忽略函数返回值。
package mainimport "fmt"func main() {firstName, _ := getNames()fmt.Println("Welcome to Earth,", firstName)}func getNames() (string, string) {return "John", "Doe"
}
5. STRUCTS
我们使用struct去建立一个key-value的结构。
package mainimport "fmt"type messageToSend struct {phoneNumber intmessage string
}func test(m messageToSend) {fmt.Printf("Sending message: '%s' to: %v\n", m.message, m.phoneNumber)
}func main() {test(messageToSend{phoneNumber: 148255510981,message: "Thanks for signing up",})}
6. Embedded STRUCTS
embedded struct可以实现类似继承的效果。
package mainimport "fmt"type sender struct {rateLimit intuser
}type user struct {name stringnumber int
}func test(s sender) {fmt.Println("Sender name: ", s.name)fmt.Println("Sender number: ", s.number)fmt.Println("Sender rate limit: ", s.rateLimit)
}func main() {test(sender{rateLimit: 10000,user: user{name: "Deborah",number: 18055558790,},})
}
7. STRUCTS method
package mainimport "fmt"type authenticationInfo struct {username stringpassword string
}func (authI authenticationInfo) getBasicAuth() string {return fmt.Sprintf("Authorization: Basic %s:%s", authI.username, authI.password)
}func test(authInfo authenticationInfo) {fmt.Println(authInfo.getBasicAuth())
}func main() {test(authenticationInfo{username: "Bing",password: "98725",})
}
8. Interface接口
接口可以让我们将不同的类型绑定到一组公共的方法上,从而实现多态和灵活的设计。
package mainimport ("fmt""time"
)func sendMessage(msg message) {fmt.Println(msg.getMessage())
}type message interface {getMessage() string
}type birthdayMessage struct {birthdayTime time.TimerecipientName string
}func (bm birthdayMessage) getMessage() string {return fmt.Sprintf("Hi %s, it is your birthday on %s", bm.recipientName, bm.birthdayTime)
}type sendingReport struct {reportName stringnumberOfSends int
}func (sr sendingReport) getMessage() string {return fmt.Sprintf("Your '%s' report is ready. You've sent %v messages.", sr.reportName, sr.numberOfSends)
}func test(m message) {sendMessage(m)
}func main() {test(sendingReport{reportName: "First Report",numberOfSends: 10,})test(birthdayMessage{recipientName: "John Doe",birthdayTime: time.Date(1994, 03, 21, 0, 0, 0, 0, time.UTC),})
}
输出为:
Your ‘First Report’ report is ready. You’ve sent 10 messages.
Hi John Doe, it is your birthday on 1994-03-21 00:00:00 +0000 UTC
Interface接口的另一个例子
package mainimport ("fmt"
)type employee interface {getName() stringgetSalary() int
}type contractor struct {name stringhourlyPay inthoursPerYear int
}func (c contractor) getName() string {return c.name
}func (c contractor) getSalary() int {return c.hourlyPay * c.hoursPerYear
}type fullTime struct {name stringsalary int
}func (f fullTime) getName() string {return f.name
}func (f fullTime) getSalary() int {return f.salary
}func test(e employee) {fmt.Println(e.getName(), e.getSalary())
}func main() {test(fullTime{name: "Jack",salary: 50000,})test(contractor{name: "Bob",hourlyPay: 100,hoursPerYear: 73,})
}
输出为:
Jack 50000
Bob 7300
9. 实现多个Interface
package mainimport ("fmt"
)type expense interface {cost() float64
}type printer interface {print()
}type email struct {isSubscribed boolbody string
}func (e email) cost() float64 {if !e.isSubscribed {return 0.05 * float64(len(e.body))}return 0.01 * float64(len(e.body))
}func (e email) print() {fmt.Println(e.body)
}func test(e expense, p printer) {fmt.Printf("Printing with cost: %f\n", e.cost())p.print()fmt.Println("================================")
}func main() {e := email{isSubscribed: true,body: "hello there",}test(e, e)e = email{isSubscribed: false,body: "I want my money back",}test(e, e)
}
10. Type assertions类型断言
通过这一行代码“em, ok := e.(email)”,检查输入是否为email。
通过这一行代码“s, ok := e.(sms)”,检查输入是否为sms。
package mainimport ("fmt"
)type expense interface {cost() float64
}func getExpenseReport(e expense) (string, float64) {em, ok := e.(email)if ok {return em.toAddress, em.cost()}s, ok := e.(sms)if ok {return s.toPhoneNumber, s.cost()}return "", 0.0
}type email struct {isSubscribed boolbody stringtoAddress string
}type sms struct {isSubscribed boolbody stringtoPhoneNumber string
}func (e email) cost() float64 {if !e.isSubscribed {return float64(len(e.body)) * .05}return float64(len(e.body)) * .01
}func (s sms) cost() float64 {if !s.isSubscribed {return float64(len(s.body)) * .1}return float64(len(s.body)) * .03
}func test(e expense) {fmt.Println(getExpenseReport(e))
}func main() {test(email{isSubscribed: true,body: "hello there",toAddress: "john@dose.com",})test(sms{isSubscribed: false,body: "This meeting could have been an email",toPhoneNumber: "+155555509832",})
}
11. Type Switches
可以利用switch语法改写以上代码,令程序可以根据不同输入类型,有不一样的输出。
func getExpenseReport(e expense) (string, float64) {switch v := e.(type) {case email:return v.toAddress, v.cost()case sms:return v.toPhoneNumber, v.cost()default:return "", 0.0}
}
12. 如何处理error
package mainimport ("fmt"
)func sendSMSToCouple(msgToCustomer, msgToSpouse string) (float64, error) {costForCustomer, err := sendSMS(msgToCustomer)if err != nil {return 0.0, err}costForSpouse, err := sendSMS(msgToSpouse)if err != nil {return 0.0, err}return costForCustomer + costForSpouse, nil
}func sendSMS(message string) (float64, error) {const maxTextLen = 25const costPerchar = .0002if 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() {msgToCustomer_1 := "Thank you."msgToSpouse_1 := "Enjoy!"test(msgToCustomer_1, msgToSpouse_1)msgToCustomer_1 = "We loved having you in."msgToSpouse_1 = "We hope the rest of your evening is absolutely interesting."test(msgToCustomer_1, msgToSpouse_1)
}