zoukankan      html  css  js  c++  java
  • Golang理解-函数声明

    普通函数声明

    普通函数的声明形式

     
    func 函数名(参数列表) (返回参数列表) {
    		函数体 
    }
    

    参数类型简写

    1. 同种类型的返回值

    如果返回值是同种类型,则用括号将多个返回值类型括起来,用逗号分隔每个返回值类型

    使用return语句时,值列表的顺序需要和函数声明的返回值类型一致

    纯类型的返回值对于代码的可读性不是很友好,特别是在同类型的返回值出现时,无法区分每个返回参数的意义

    func subAndSum(x, y int) (int, int) {
        sub := x - y
        sum := x + y
        return sub, sum
    }
    
    2. 带有变量名的返回值
    func namedRetValues() (a, b int) {
    		a = 1
    		b = 2
    		return
    }
    

    函数声明时将返回值命名为a,b; 因此可以在函数体中直接对函数的返回值进行赋值. 在命名的返回值方式的函数中,在函数结束前需要显示的使用return语句进行返回

    同一种类型返回值和命名返回值两种形式只能二选一,混用时将会发生编译错误;例如:

    func namedRetValues() (a, b int, int)
    

    函数调用

    函数调用格式: 返回值变量列表 = 函数名(参数列表)

    多个返回值列表使用逗号分隔; 例如:

    a, b := namedRetValues()
    

    实例:将秒解析为时间单位

    package main
    
    // 将秒解析为时间单位
    
    import (
    		"fmt"
    )
    
    const (
        // 定义每分钟的秒数
        SecondsPerMinute = 60
        // 定义每小时的秒数
        SecondsPerHour = SecondsPerMinute * 60
        // 定义没天的秒数
        SecondsPerDay = SecondsPerHour * 24
    )
    
    // 将传入的秒解析为3种时间单位
    func resolveTime(seconds int) (day, hour, minute int) {
        day = seconds / SecondsPerDay
        hour = seconds / SecondsPerHour
        minute = seconds / SecondsPerMinute
        // 显示return返回
        return
    }
    
    func main() {
        // 直接将返回值作为打印参数
        fmt.Println(resolveTime(1000))
        // 只获取小时和分钟
        _, hour, minute := resolveTime(18000)
        fmt.Println(hour, minute)
        // 只获取天
        day, _, _ := resolveTime(90000)
        fmt.Println(day)
    }
    

    函数参数传递

    Go语言中传入和返回参数在调用和返回时都是值传递

    这里需要注意的是指针,切片和map等引用类型对象指向的内容在参数传递中不会发生复制,而是将指针进行复制,类似创建一次引用.

    实例: 测试golang中函数参数传递为值传递; 引用类型参数为一次引用创建

    package main
    /*
    		示例: 测试golang中函数参数传递为值传递; 引用类型参数为一次引用创建
    */
    
    import (
    		"fmt"
    )
    
    // 用于测试值传递效果的结构体
    type Data struct {
        complax []int  		// 测试切片在参数传递中的效果, 切片是一种动态类型,内部以指针存在
        instance InnerData 	// 实例分配的innerData
        ptr *InnerData 		// 将ptr声明为InnerData的指针类型
    }
    
    // 代表各种结构体字段; 声明一个内嵌的结构innerData
    type InnerData struct {
    		a int
    }
    
    // 值传递的测试函数; 
    // 该函数的参数和返回值都是Data类型,在调用中,Data的内存会被复制后传入函数,当函数返回时,又将返回值复制一次,赋值给函数返回值的接收变量
    func passByByValue(inFunc Data) Data {
        // 输出参数的成员情况
        fmt.Printf("in func value: %+v
    ", inFunc)
        // 打印inFunc的指针
        fmt.Printf("in func ptr: %p
    ", &inFunc)	 // 值传递,需要使用&符号取地址; 拥有相同地址且类型相同的变量,表示同一块内存区域
    
        return inFunc 	// 将传入的变量作为返回值返回,返回的过程中将发生值复制
    }
    
    // 测试流程,准备一个Data格式的数据结构并填充所有成员,通过调用测试函数,传入Data结构数据,并获取返回值,对比输入和
    // 输出后的Data结构数据变化,特别是指针变化情况以及输入和输出整块数据是否被复制
    
    func main() {
        // 准备传入函数的数据结构
        in := Data{
            complax: []int{1, 2, 3},
            instance: InnerData{
              5,
            },
            ptr: &InnerData{1},
    		}
    
        // 输入结构的成员情况
        fmt.Printf("in value: %+v
    ", in)
    
        // 输入结构的指针地址
        fmt.Printf("in ptr: %p
    ", &in)
    
        // 传入结构体,返回同类型的结构体
        out := passByByValue(in)
    
        // 输出结构的成员情况
        fmt.Printf("out value: %+v
    ", out)
        // 输出结构的指针地址
        fmt.Printf("out ptr: %p
    ", &out)
    }
    

    总结

    1. 所有的Data结构的指针地址发生了变化,意味着所有结构都是一块新的内存,无论是将Data结构传入函数内部,还是通过返回值传回Data都会发生复制行为
    2. 所有的Data结构中的成员值都没有发生变化,原值传递,意味着所有参数都是值传递
    3. Data结构的ptr成员在传递过程中保持一致,表示指针在函数参数值传递中传递的只是指针值,不会复制指针指向的部分
  • 相关阅读:
    C#和sqlserver中生成新的32位GUID
    IIS7下swfupload上传大文件出现404错误
    jQuery 判断是否为数字的方法 及 转换数字函数
    js数组与字符串的相互转换方法
    jquery 中如何将数组转化为json字符串,然后再转化回来?
    Firemonkey Android 虚拟机
    Eclipse apk 签名
    win10 修改hosts
    eclipse 预览Android界面报错
    夜神模拟器
  • 原文地址:https://www.cnblogs.com/vinsent/p/11221369.html
Copyright © 2011-2022 走看看