Go 函数

声明

func name(parameter-list) (result-list) {
   
    body
}

4种方法声明拥有2个int型参数和1个int型返回值的函数

func add(x int, y int) int   {
   return x + y}
func sub(x, y int) (z int)   {
    z = x - y; return}
func first(x int, _ int) int {
    return x }		// _表示该参数没被使用
func zero(int, int) int      {
    return 0 }

fmt.Printf("%T\n", add)   // "func(int, int) int"
fmt.Printf("%T\n", sub)   // "func(int, int) int"
fmt.Printf("%T\n", first) // "func(int, int) int"
fmt.Printf("%T\n", zero)  // "func(int, int) int"

实参通过值的方式传递,因此函数的形参是实参的拷贝。对形参进行修改不会影响实参。但是,如果实参包括引用类型,如指针,slice(切片)、map、function、channel等类型,实参可能会由于函数的间接引用被修改。

package main
import (
	"fmt"
)

// slice
func SliceTest(str []string) {
   
	for k,_ :=range str{
   
	   str[k] = "1" // 外部slice会发生改变,说明str为传地址
	}
	fmt.Println(str)	// [1 1 1 1 1]
	str = append(str, "abc") // 外部slice不会发生变化,因为append返回的是新slice
	fmt.Println(str)	// [1 1 1 1 1 abc]
	fmt.Printf("str address = %p\n", str)	// str address = 0xc000046050
	fmt.Printf("str2 address = %p\n", str2)	// str2 address = 0xc0000580a0
	str = str2	// 如果单纯的地址赋值地址,那么改变的是局部变量,因为地址,只是个十六进制数
	fmt.Printf("str address = %p\n", str)	// str address = 0xc0000580a0
 }

 // map 传址
func mapf(m map[string]int) {
   
	m["eee"] = 5

}
 
 func main() {
   
	list := make([]string, 30)
	// 待处理的字符串列表
	list = []string{
   
	   "go scanner",
	   "go parser",
	   "go compiler",
	   "go printer",
	   "go formater",
	}
	fmt.Println(list)	// [go scanner go parser go compiler go printer go formater]
	SliceTest(list)		
	fmt.Println(list)	// [1 1 1 1 1]

	// map
	m := make(map[string]int)
	m["123"] = 2
	m["abc"] = 1
	mapf(m)
	fmt.Println(m)	// map[123:2 abc:1 eee:5]
 }

多返回值

如果一个函数将所有的返回值都显示的变量名,那么该函数的return语句可以省略操作数

package main
import (
	"fmt"
)

func f(x, y int) (add, minus int) {
   
	add = x + y
	minus = x - y
	return		// return add, minus
}
func main() {
   
	add, minus := f(10, 2)
	fmt.Println(add, minus)		// 12, 8
}

错误机制

很多内置函数带返回值err
err == nil意味着函数运行成功,non-nil表示失败

五种应对错误的措施

1. 对于内置函数调用错误,向上传播

err直接反给调用者,向上传播

resp, err := http.Get(url)
if err != nil{
   
    return nil, err
}

2. 对于偶然错误,重新尝试

如果错误的发生是偶然性的,或由不可预知的问题导致的。一个明智的选择是重新尝试失败的操作。在重试时,我们需要限制重试的时间间隔或重试的次数,防止无限制的重试。

// WaitForServer attempts to contact the server of a URL.
// It tries for one minute using exponential back-off.
// It reports an error if all attempts fail.
func WaitForServer(url string) error {
   
    const timeout = 1 * time.Minute
    deadline := time.Now().Add(timeout)
    for tries := 0; time.Now().Before(deadline); tries++ {
   
        _, err := http.Head(url)
        if err == nil {
   
            return nil // success
        }
        log.Printf("server not responding (%s);retrying…", err)
        time.Sleep(time.Second << uint(tries)) // exponential back-off
    }
    return fmt.Errorf("server %s failed to respond after %s", url, timeout)
}

3. 错误发生后程序无法继续运行。则结束程序

输出错误信息并结束程序

// (In function main.)
// 一、
if err := WaitForServer(url); err != nil {
   
    fmt.Fprintf(os.Stderr, "Site is down: %v\n", err)
    os.Exit(1)
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值