10.functions

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}
*/

posted on 2018-03-17 18:57  cucy_to  阅读(138)  评论(0编辑  收藏  举报

导航