【Go 语言教程】Go语言函数说明

作者: 万能的华哥Dean | 来源:发表于2019-03-23 15:33 被阅读13次

在程序设计中,模块设计是最小的设计单元,模块设计可以对应面相对象设计中的类设计,也可以对应到函数(方法)设计。所以编程中很多时候函数作为模块设计的最小单元。函数设计也有很多方法和规定,以及设计原则。那么go语言的函数设计都有些什么原则和要求呢,让我们一起来看一看。

1 入口函数

作为编译型的编程语言,go语言和其他流行的语言(C/C++, JAVA等)都有程序入口,就是所谓的入口函数main。go语言程序作为一个可执行程序需要至少有一个且仅为一个main方法。main方法是go语言程序编译后执行的第一个方法(当然特殊方法init除外)。main方法的写法也往往仿照C/C++或者Java的参数模式,如代表命令行的argv参数数组和参数个数的argc,在go语言中使用组件os.args带代替和逻辑编写。命令行参数的数组下标以0开始。flag也是操作命令行中常用的模块。所以常见的入口方法命令行参数获取方式如下:

import (
    "flag"
    "fmt"
        "os"
)
 
func main() {
     // 打印os.args的内容
     fmt.Println("args=", os.Args)
    // 获取参数值
    bVal := flag.Bool("bVal", false, "if flag is true")
    id := flag.Int("id", 0, "id")
    port := flag.String("port", ":8080", "the port")
    var name string
    // 换种方式获取参数值
    flag.StringVar(&name, "name", "dean", "name")
    // 转换
    flag.Parse()
    // 打印出来读取的命令行参数值
    fmt.Println("bVal:", *bVal)
    fmt.Println("id:", *id)
    fmt.Println("port:", *port)
    fmt.Println("name:", name)
}
执行结果
./flag -bVal=true -id 1001 -name kate

args= [./flag -bVal=true -id 1001 -name kate]
bVal: true
id: 1001
port: :8080
name: kate

2 函数定义

go语言的函数定义方式和C/C++,Java等是不太一样的。定义格式如下:

func func_name(params list) return_types {
    // 函数体
}

其中
func代表方法的声明
func_name代表函数的方法名字
params list代表参数列表,组成格式为:var type 变量名和类型
return_types代表返回的类型列表:如bool或者(bool, int)等
函数体部分放置方法的实现逻辑代码

3 例子代码

以下将上面的main方法获取命令行参数进行方法的封装,源码如下:

package main

import (
        "fmt"
        "flag"
)

func ShowFlags() {
    // 获取参数值
    bVal := flag.Bool("bVal", false, "if flag is true")
    id := flag.Int("id", 0, "id")
    port := flag.String("port", ":8080", "the port")
    var name string
    // 换种方式获取参数值
    flag.StringVar(&name, "name", "dean", "name")
    // 转换
    flag.Parse()
    // 打印出来读取的命令行参数值
    fmt.Println("bVal:", *bVal)
    fmt.Println("id:", *id)
    fmt.Println("port:", *port)
    fmt.Println("name:", name)
}

func ShowArgs(args []string) bool {
         if len(args) <= 0 {
                return false 
         }
     // 打印os.args的内容
     fmt.Println("args=", args)
         return true
}
//执行结果如下 ./flag
args= [./flag]
Show Flags  true
bVal: false
id: 0
port: :8080
name: dean

4 函数的调用

当定义了一个函数,那么就定义了一个功能的模块集合,函数实现了这个模块的功能,并带有输入参数和返回参数。那么函数的调用也比较简单,代码如下:

package main
 
import (
    "fmt"
        "os"
)
 
func main() {
        // 打印os.args的内容
        ret := ShowArgs(os.Args)
        fmt.Println("Show Flags ", ret)
        // 获取参数值
        ShowFlags()
}

其中有带参数的函数调用ShowArgs(os.Args),也有不带参数的函数调用ShowFlags()。函数的调用有先后顺序,也代表了程序的执行顺序,函数调用遵循栈的先进后出。

5 多返回值函数

函数的定义除了正常的有返回和单一的返回值(C/C++,Java等语言就是如此,只能有一个返回值)。但是go原因是可以定义带多个返回值的函数的,这个也给编程带来了便利,因为很多时间一个返回值往往并不能满足我们队业务模块定义的需要,而且多返回值不管是在进行类似业务逻辑:如果true就做什么事情(需要什么数据),需要返回2个数据对象,又或者进行分别处理。代码如下;

package main

import "fmt"

func SwapNumber(left, right int) (int, int) {
   return right, left
}

func main() {
    a := 2
    b := 3
    // 交换前
    fmt.Println(a, b)
    a, b = SwapNumber(a, b)
    // 交换后
    fmt.Println(a, b)
} 

如果你对于C/C++语言对于交换2个数的实现熟悉,可以好好观察,go语言在进行这个操作的时候的便捷性。没有任何的第三个变量(或者中间变量),对吧。

// 执行结果 ./swap
2 3
3 2

6 函数参数说明

go语言的函数参数分为传值和引用传递2种,章节5中的交换2个数就是值传递,值传递就是就是咱们常说的copy(复制)一份传递(赋值)给下一个变量。引用传递则表达的是咱们认识的传地址(也就是指向变量的地址)。默认的go语言的参数传递是值传递,不会影响到原始的变量的值。也就是说在函数调用过程中,对于实参是没有任何影响的。

7 函数的用法

写过其他语言的代码都比较清楚,函数的用法也是出了正常的调用,计算,执行等之外。可以这么认为定义的函数可以作为抽象的值,在语句中赋值给变量或者新的函数(传参),还有就是C/C++中没有的匿名函数方法的定义。匿名函数定义和普通函数定义类似,只是匿名函数直接出现在代码逻辑中,不需要单独将函数方法块独立放在方法定义之外,而是直接写方法体,如下:

// 定义
func(a, b int, z float) bool {
    return a*b < int(z)
} 
// 用途,直接复制给变量
f := func(x,y int) int {
    return x*y
}

// 花括号后面直接加括号表示方法调用
func(a, b int) {
    fmt.Println(a, b)
}(2, 3)

其实匿名方法,就是不带方法名字的函数定义。

8 函数的作用域

我们知道go语言的包概念(package)是对应着不同的作用域,而在不同的包内,如果要调用非包内的(或者其它模块)的实现方法,那么是可以直接调用么?答案当然是不行的。这里顺便分享个设计概念,就是包设计,当设计一个包的时候需要定义那些接口是需要对外部开放的,哪些是包内实现的,不需要对外开放的。设计的时候就可以想好,而包内对外开放的接口就是必须要以大写字母开头的定义,外部才是可见的。对于小写字母开头的方法实现,外部是不可见的。所以函数的作用域就是和函数定义的名字的首字母大小写有管理。
当然函数内部的定义的作用域可见度只包含于函数内部。出了函数花括号,一定是不可见的。

9 经验分享

一个函数的设计好坏,和函数的名字,传参,以及返回参数都有密切的管理。
好的函数设计有一个可以简单的单词,但是却可以表达这个函数是做什么功能的;同时一个好的函数设计对于传参和返回值也是比较讲究的,原则是要精简和方便,比如以下代码:

// 2个数相加
Add(a, b int) int 
// 显示用户信息
ShowUserInfo(Persion)

// 不好2个数相加的设计
aaa(a, b int) int 
// 不好的显示用户信息的设计
printui(Persion)

一个好的函数设计(或者说一段好的代码)有这样一些原则,可以分享给你,你可以先记在脑海,以后的代码实践中慢慢思考和琢磨。

  • 可读性良好
  • 可以方便调试
  • 可以方便进行测试
  • 易于维护
  • 可以很容易扩展
  • 有效的(效率高)

关于本专栏——Go 语言教程,专栏致力于为希望可以系统地,一条一条地,一步一步的学习Go语言的朋友提供一个可以持续阅读的地方,当然也希望可以通过我的实践经验以及相应的基础,可以给你一些学习之外的想法和总结,以及提高。如果真的有帮助,哪怕一点点,可以把这个一点点的提高分享给我,欢迎跟我勾搭联系。

相关文章

  • 【Go 语言教程】Go语言函数说明

    在程序设计中,模块设计是最小的设计单元,模块设计可以对应面相对象设计中的类设计,也可以对应到函数(方法)设计。所以...

  • (四)go语言函数&参数传递

    go语言函数 基本语法 例子 go语言参数传递

  • cgo

    cgo cgo是用来在Go语言中调用C语言的工具 Go语言调用C语言 简单C语言函数 在Go语言中需要通过impo...

  • go语言学习资料

    菜鸟教程-Go 语言教程 https://www.runoob.com/go/go-tutorial.html老男...

  • Go语言代码风格

    Go语言代码说明 Go 语言[https://haicoder.net/golang/golang-tutoria...

  • 04-枚举常量

    Go语言枚举 c语言中的枚举 Go语言枚举 iota迭代器 Go语言输出函数 fmt.Printf("格式化字符串...

  • Golang学习笔记-1.4 数据类型

    本文系第四篇Golang语言学习教程在Go语言中,数据类型用于声明函数和变量。Go语言按类别有以下几种数据分类 b...

  • 潍坊go语言培训

    潍坊go语言培训潍坊go语言培训潍坊go语言培训潍坊go语言培训潍坊go语言培训潍坊go语言培训潍坊go语言培训潍...

  • A Tour of Go - Go语言之旅

    Hello,世界 这是Go语言官方的一个简明入门教程,可以帮助我们快速入门Go语言:Go语言之旅[https://...

  • 01 Go极简教程 目录

    极简教程的初衷是给已有其他语言基础的人阅读尽可能少的内容学习Go语言 Go极简教程 目录 Go极简教程 环境安装及...

网友评论

    本文标题:【Go 语言教程】Go语言函数说明

    本文链接:https://www.haomeiwen.com/subject/zqkdvqtx.html