普通函数定义


golang函数基本组成:关键字func函数名参数列表返回值函数体返回语句

• 语法如下

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

• 示例如下

package main

import "fmt"
import
"errors" func Add(a int, b int) (ret int, err error) {
if a < || b < { // 假定只支持两个非负数字的加法
err = errors.New("Should be non-negative numbers!")
return
}
return a + b, nil
} func main() {
fmt.Println(Add(-, ))
fmt.Println(Add(, ))
}

• 注意事项

▪ golang函数支持多返回值,返回时没有被明确赋值的返回值将被设置为默认值

▪ golang函数返回值可以命名,但不是强制规则,给返回值命名可以让让代码更清晰,可读性更强,同时也可以用于文档。

▪ golang函数定义中左花括号的位置被强制规范,如果左花括号放置不规范,golang编译器报告编译错误:syntax error: unexpected semicolon or newline before {。

▪ golang函数定义中如果参数列表中若干个相邻参数的类型相同,则可以在参数列表中省略前面的变量类型声明。

func Add(a, b int) (ret int, err error) {
    // 函数体
}

▪ golang函数定义中如果返回值列表中若干个相邻返回值的类型相同,则可以在返回值列表中省略前面的变量类型声明。

func Add(a, b int) (ret, err int) {
    // 函数体
}

▪ golang函数定义中如果返回值只有一个,那么返回值列表可以简略表示。

func Add(a, b int) int {
    // 函数体
}

固定类型的不定参数函数定义


• 语法如下

func 函数名(args ...Type) (返回值列表) {
    // 函数体
}

形如args ...Type的用法只能作为函数的参数类型,并且必须是最后一个参数

形如args ...Type的用法是一个语法糖(syntactic sugar),即对语言功能没有影响,但可以增加程序的可读性。

形如args ...Type的用法从内部实现上说,其本质上是一个数组切片,即[]type,因此可以用for循环来获得每个传入的参数。

• 示例如下

package main

import "fmt"

func myfunc(prefix string, args ...int) {
fmt.Print(prefix, " : ") for _, arg := range args {
fmt.Print(arg, " ")
} fmt.Println()
} func main() {
myfunc("data1", , , , )
myfunc("data2", , , , , )
}

• 不定参数函数互相调用

▶ 原样传递

▪ 语法如下

func myfunc1(args ...Type) {
// 函数体
} func myfunc2(args ...Type) {
...
myfunc1(args...)
...
}

▪ 示例如下

package main

import "fmt"

func myfunc1(args ...int) {
fmt.Println("myfunc1() invoked") for _, arg := range args {
fmt.Print(arg, " ")
} fmt.Println()
} func myfunc2(args ...int) {
fmt.Println("myfunc2() invoked")
myfunc1(args...)
} func main() {
myfunc2(, , , )
}

▶ 片段传递

▪ 语法如下

func myfunc1(args ...Type) {
// 函数体
} func myfunc2(args ...Type) {
...
myfunc1(args[m:n]...)
...
}

▪ 示例如下

package main

import "fmt"

func myfunc1(args ...int) {
fmt.Println("myfunc1() invoked") for _, arg := range args {
fmt.Print(arg, " ")
} fmt.Println()
} func myfunc2(args ...int) {
fmt.Println("myfunc2() invoked")
myfunc1(args[:]...)
} func main() {
myfunc2(, , , )
}

任意类型的不定参数函数定义


• 语法如下

func 函数名(args ...interface{}) (返回值列表) {
// 函数体
}

形如args ...interface{}的用法只能作为函数的参数类型,并且必须是最后一个参数。

• 示例如下

package main

import "fmt"

func MyPrintf(info string, args ...interface{}) {
fmt.Println(info)
for _, arg := range args {
switch arg.(type) {
case int:
fmt.Println(arg, "is an int value.")
case string:
fmt.Println(arg, "is a string value.")
case int64:
fmt.Println(arg, "is an int64 value.")
default:
fmt.Println(arg, "is an unknown type.")
}
}
} func main() {
var v1 int =
var v2 int64 =
var v3 string = "hello"
var v4 float32 = 1.234 MyPrintf("MyPrintf", v1, v2, v3, v4)
}

匿名函数与闭包


• 匿名函数

 匿名函数是指不需要定义函数名的一种函数实现方式,函数可以像普通变量一样被传递或使用。

▶ 匿名函数赋值给变量

▪ 语法如下

f := func(参数列表) (返回值列表) {
// 函数体
}

▪ 示例如下

package main

import "fmt"

func main() {
f := func(x, y int) int {
return x + y
} fmt.Println("Result =", f(, ))
}

▶ 匿名函数直接调用

▪ 语法如下

 匿名函数定义的花括号后直接跟参数列表表示函数调用。

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

▪ 示例如下

package main

import "fmt"

func main() {
fmt.Println("Result =",
func(x, y int) int {
return x + y
}(, ))
}

• 闭包

▶ 闭包概念

 闭包是可以包含自由变量(未绑定到特定对象)的代码块。这些自由变量不在该代码块内或任何全局上下文中定义,而是在定义代码块的环境中定义。要执行的代码块为自由变量提供绑定的计算环境,即作用域。

 自由变量包含在代码块中,这些自由变量以及其引用的对象将不被释放。闭包的实现确保只要闭包还被使用,那么被闭包引用的变量会一直存在。

 golang的匿名函数就是一个闭包,闭包函数可以存储到变量中作为参数传递给其他函数,最重要的是能够被函数动态创建和返回。

 自由变量的值将被隔离,在闭包外不可修改,只有内部匿名函数才能访问,而无法通过其他途径访问,因此确保了变量的安全性。

▶ 闭包使用

▪ 语法如下

c := func() func(参数类型列表) 返回值类型列表 {
// 自由变量定义
...
return func(参数列表) 返回值列表 {
// 函数定义
}
}()

▪ 示例如下

package main

import (
"fmt"
) func main() {
result := // 闭包定义
c := func() func(int) int {
i :=
return func(j int) int {
i +=
fmt.Printf("i = %d, j = %d\n", i, j)
return i + j
}
}() result = c()
fmt.Printf("i + j= %d\n", result) result = c()
fmt.Printf("i + j= %d\n", result) result = c()
fmt.Printf("i + j= %d\n", result)
}

main函数


 main函数是golang可执行程序的执行起点。

 main函数不能带有参数,命令行传入的参数在os.Args变量中保存。

package main

import (
"fmt"
"os"
) func main() {
for i, v := range os.Args {
fmt.Printf("os.Args[%d] = %s\n", i, v)
}
}

[golang note] 函数定义的更多相关文章

  1. golang笔记——函数与方法

    如果你遇到没有函数体的函数声明,表示该函数不是以Go实现的. package math func Sin(x float64) float //implemented in assembly lang ...

  2. golang的函数

    在golang中, 函数是第一类值(first-class object), 即函数可以赋值与被赋值. 换言之, 函数也可以作为ReceiverType, 定义自己的method. 实例: http. ...

  3. GO语言的进阶之路-Golang高级数据结构定义

    GO语言的进阶之路-Golang高级数据结构定义 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 我们之前学习过Golang的基本数据类型,字符串和byte,以及rune也有所了解, ...

  4. Python学习札记(十一) Function2 函数定义

    参考:定义函数 Note: 先看一段代码实例(Barefoot topo.py): def read_topo(): nb_hosts = 0 nb_switches = 0 links = [] w ...

  5. 5.1 Go函数定义

    1 Go函数定义 Go函数是指:一段具有独立功能的代码,然后可以在程序中其他地方多次调用. Go分为自定义函数,系统函数. 函数可以将一个大的工作拆解成小的任务. 函数对用户隐藏了细节. Golang ...

  6. golang:函数总结

    golang保留的函数 init(), main()是golang的保留函数,有如下特点: main() 只能用在main包中,仅可定义一个,init() 可定义任意包,可重复定义,建议只定义一个 两 ...

  7. 深入理解javascript函数定义与函数作用域

    最近在学习javascript的函数,函数是javascript的一等对象,想要学好javascript,就必须深刻理解函数.本人把思路整理成文章,一是为了加深自己函数的理解,二是给读者提供学习的途径 ...

  8. JavaScript函数定义和调用 变量作用域

     本文是笔者在看廖雪峰老师JavaScript教程时的个人总结   JavaScript中函数定义可以是这样的格式 function 函数名(参数) {     函数体 } 也可以是这样的格式     ...

  9. Scala深入浅出实战经典-----002Scala函数定义、流程控制、异常处理入门实战

    002-Scala函数定义.流程控制.异常处理入门实战 Scala函数定义 语句结束无分号 定义无参函数 def 函数名称(参数名称:参数类型)[:Unit=]{ 函数体 } 老师的代码 我的实际代码 ...

随机推荐

  1. C++ 百炼成钢20

    题目56: 编写C++程序完成以下功能:(1)定义一个Point类,其属性包括点的坐标,提供计算两点之间距离的方法:(2)定义一个圆形类,其属性包括圆心和半径:(3)创建两个圆形对象,提示用户输入圆心 ...

  2. 【BZOJ】1628 && 1683: [Usaco2007 Demo]City skyline 城市地平线(单调栈)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1628 http://www.lydsy.com/JudgeOnline/problem.php?id ...

  3. 【转】Native Thread for Win32 C- Creating Processes(通俗易懂,非常好)

    http://www.bogotobogo.com/cplusplus/multithreading_win32C.php To create a new process, we need to ca ...

  4. VC++ ListCtrl Report使用

    1.在VC++ 6.0中新建基于对话框的MFC应用程序ListCtrl; 2.在主对话框上添加一个List Control至合适的位置及大小: 3.在对话框OnInitDialog中初始化ListCt ...

  5. servlet和jsp中间的交互

    jsp本质上也是一个servlet, 所有的jsp页面最终会编译成一个servlet 1. jsp访问servlet jsp访问servlet比较简单通过get, post的方式直接访问servlet ...

  6. Laravel5.1 搭建博客 --编译前端文件

    上篇文章写了Gulp编译前端文件,这篇记录下在搭建博客中使用Gulp 1 引入bootstrap和js 1.1 首先先在项目本地安装Bower sudo npm install bower 1.2 创 ...

  7. Boatloader的工作流程

    (1)第一节阶段的功能 1.硬件设备的初始化 2.载入u-boot第二阶段的代码到我们的RAM空间 3.设置好栈 4.跳转到第二阶段的代码入口 (2)第二阶段的功能 1.初始化本阶段所使用的硬件设备 ...

  8. Android之MessageQueue、Looper、Handler与消息循环

    在android的activity中有各种各样的事件,而这些事件最终是转换为消息来处理的.android中的消息系统涉及到: *  消息发送 *  消息队列 *  消息循环 *  消息分发 *  消息 ...

  9. 关于python类型创建、反射(自醒)与反序列化

    一.反序列化漏洞与新式类 在pickle和cPickle以及shelve这三个序列化类中,想要构造反序列化漏洞执行命令或者代码,都需要用到新式类. shelve其实底层就是调用的pickle和cPic ...

  10. XStream别名;元素转属性;去除集合属性(剥皮);忽略不需要元素

    city package xstream; public class City { private String name; private String description; public St ...