Return multiple values
// Sample program to show how functions can return multiple values while using
// named and struct types.
package main
import (
"encoding/json"
"fmt"
)
// user is a struct type that declares user information.
type user struct {
Id int
Name string
}
// retrieveUser retrieves the user document for the specified
// user and returns a pointer to a user type value.
// retrieveUser检索指定的用户文档。
//用户返回一个指向用户类型值的指针。
func retrieveUser(name string) (*user, error) {
// Make a call to get the user in a json response.
r, err := getUser(name)
if err != nil {
return nil, err
}
// Unmarshal the json document into a value of
// the user struct type.
var u user
err = json.Unmarshal([]byte(r), &u)
return &u, err
}
// GetUser simulates a web call that returns a json
// document for the specified user.
// GetUser模拟返回json的web调用。
//指定用户的文件。
func getUser(name string) (string, error) {
response := `{"id":1432, "name":"sally"}`
return response, nil
}
func main() {
// Retrieve the user profile.
u, err := retrieveUser("sally")
if err != nil {
fmt.Println(err)
return
}
// Display the user profile.
fmt.Printf("%+v\n", *u)
}
/*
{Id:1432 Name:sally}
*/
Blank identifier 空白标识符
// Sample program to show how we can use the blank identifier to
// ignore return values.
// 示例程序演示如何使用空白标识符。
// 忽略返回值。
package main
import (
"encoding/json"
"errors"
"fmt"
)
// user is a struct type that declares user information.
type user struct {
ID int
Name string
}
// updateStats provIDes update stats.
type updateStats struct {
Modified int
Duration float64
Success bool
Message string
}
func main() {
// Declare and initialize a value of type user.
u := user{
ID: 1432,
Name: "Betty",
}
// Update the user Name. Don‘t care about the update stats. 更新用户名。不要在意更新stats。
if _, err := updateUser(&u); err != nil {
fmt.Println(err)
return
}
// Display the update was Successful.
fmt.Println("Updated user record for ID", u.ID)
}
// updateUser updates the specified user document.
func updateUser(u *user) (*updateStats, error) {
// response simulates a JSON response.
response := `{"Modified":1, "Duration":0.005, "Success" : true, "Message": "updated"}`
// Unmarshal the json document into a value of
// the userStats struct type.
var us updateStats
if err := json.Unmarshal([]byte(response), &us); err != nil {
return nil, err
}
// Check the update status to verify the update
// was Successful.
if us.Success != true {
return nil, errors.New(us.Message)
}
return &us, nil
}
/*
Updated user record for ID 1432
*/
Redeclarations
// From Spec:
// a short variable declaration may redeclare variables provided they
// were originally declared earlier in the same block with the same
// type, and at least one of the non-blank variables is new.
// Sample program to show some of the mechanics behind the
// short variable declaration operator redeclares.
//从规范:
//一个简短的变量声明可以重新声明提供的变量。
//最初是在同一块区域以相同的方式声明的。
//类型,至少其中一个非空变量是新的。
//示例程序展示了一些背后的机制。
//短期变量声明操作符声明。
package main
import "fmt"
// user is a struct type that declares user information.
type user struct {
id int
name string
}
func main() {
// Declare the error variable.
var err1 error
// The short variable declaration operator will
// declare u and redeclare err1.
u, err1 := getUser()
if err1 != nil {
return
}
fmt.Println(u) // &{1432 Tomcat}
// The short variable declaration operator will
// redeclare u and declare err2.
u, err2 := getUser()
if err2 != nil {
return
}
fmt.Println(u)
// &{1432 Tomcat}
}
// getUser returns a pointer of type user.
func getUser() (*user, error) {
return &user{1432, "Tomcat"}, nil
}
Anonymous Functions/Closures 匿名和defer
// Sample program to show how anonymous functions and closures work.
package main
import "fmt"
func main() {
var n int
// Declare an anonymous function and call it.
func() {
fmt.Println("Direct:", n)
}()
/*
Direct: 0
*/
// Declare an anonymous function and assign it to a variable.
f := func() {
fmt.Println("Variable:", n)
}
// Call the anonymous function through the variable.
f()
/*
Variable: 0
*/
// Defer the call to the anonymous function till after main returns. 在主返回之后,将调用延迟到匿名函数。
defer func() {
fmt.Println("Defer 1:", n)
}()
// Set the value of n to 3 before the return.
n = 3
// Call the anonymous function through the variable.
f()
// Defer the call to the anonymous function till after main returns.
defer func() {
fmt.Println("Defer 2:", n)
}()
}
/* 说明后进先执行 从下往上
Direct: 0
Variable: 0
Variable: 3
Defer 2: 3
Defer 1: 3
*/
恢复?
// Sample program to show how to recover from panics.
package main
import (
"fmt"
"runtime"
)
func main() {
// Call the testPanic function to run the test.
if err := testPanic(); err != nil {
fmt.Println("Error:", err)
}
}
// testPanic simulates a function that encounters a panic to
// test our catchPanic function.
func testPanic() (err error) {
// Schedule the catchPanic function to be called when
// the testPanic function returns.
defer catchPanic(&err)
fmt.Println("Start Test")
// Mimic a traditional error from a function.
err = mimicError("1")
// Trying to dereference a nil pointer will cause the
// runtime to panic.
var p *int
*p = 10
fmt.Println("End Test")
return err
}
// catchPanic catches panics and processes the error.
func catchPanic(err *error) {
// Check if a panic occurred.
if r := recover(); r != nil {
fmt.Println("PANIC Deferred")
// Capture the stack trace.
buf := make([]byte, 10000)
runtime.Stack(buf, false)
fmt.Println("Stack Trace:", string(buf))
// If the caller wants the error back provide it.
if err != nil {
*err = fmt.Errorf("%v", r)
}
}
}
// mimicError is a function that simulates an error for
// testing the code.
func mimicError(key string) error {
return fmt.Errorf("Mimic Error : %s", key)
}
/*
Start Test
PANIC Deferred
Stack Trace: goroutine 1 [running]:
main.catchPanic(0xc04202bf08)
*/
练习
// Declare a struct type to maintain information about a user. Declare a function
// that creates value of and returns pointers of this type and an error value. Call
// this function from main and display the value.
//
// Make a second call to your function but this time ignore the value and just test
// the error value.
//声明一个结构类型以维护有关用户的信息。声明一个函数
//它会创建并返回该类型的指针和错误值。调用
//该函数从main函数中显示值。
//再次调用你的函数,但这一次忽略值,只测试。
//错误的值。
package main
import "fmt"
// user represents a user in the system.
type user struct {
name string
email string
}
// newUser creates and returns pointers of user type values.
func newUser() (*user, error) {
return &user{"Bill", "bill@ardanlabs.com"}, nil
}
func main() {
// Create a value of type user.
u, err := newUser()
if err != nil {
fmt.Println(err)
return
}
// Display the value.
fmt.Println(*u)
// Call the function and just check the error on the return.
_, err = newUser()
if err != nil {
fmt.Println(err)
return
}
}
/*
{Bill bill@ardanlabs.com}
*/