Go语言 函数,工程管理
Go语言 函数,工程管理
1、无参无返回值函数的使用
package main
import "fmt"
func main() {
// 无参无返回值函数的调用:函数名()
func1()
}
// 无参无返回值函数的定义
func func1() {
str1 := "mysql -uroot -p123456 -S /data/3306/mysql.socket"
fmt.Println("mysql数据库本地登录命令是#", str1)
}
2、普通参数列表
package main
import "fmt"
// 有参无返回值函数的定义,普通参数列表
// 定义函数时,在函数名后面()定义的参数叫形参
// 参数传递,只能由实参传递传递给形参,不能反过来,单向传递
func func1(a int) {
fmt.Println("a =", a)
}
func func2(a int, b int) {
fmt.Printf("a = %d, b = %d\n", a, b)
}
func func3(a, b int) {
fmt.Printf("a = %d, b = %d\n", a, b)
}
func func4(a int, b string, c float64) {
}
func func5(a, b string, c float64, d, e int) {
}
func func6(a string, b string, c float64, d int, e int) {
}
func main() {
// 有参无返回值函数调用:函数名(所需参数)
// 调用函数传递的参数叫实参
func1(666)
func2(666, 777)
}
3、不定参数类型 args ...type
package main
import "fmt"
func func1(a int, b int) { // 固定参数
fmt.Printf("a = %d, b = %d\n", a, b)
}
// ...int类型这样的类型,...type不定参数类型
// 注意:不定参数,一定只能放在形参中的最后一个参数
func func2(args ...int) { // 传递的实参可以是0个或多个
fmt.Println("len(args) =", len(args)) // 获取用户传递参数的个数
for i := 0; i < len(args); i++ {
fmt.Printf("args[%d] = %d\n", i, args[i])
}
}
// 返回2个值,第一个是下标,第二个是下标所对应的数
func func3(args ...int) {
for i, data := range args {
fmt.Printf("args[%d] = %d\n", i, data)
}
}
// 固定参数一定要传参,不定参数根据需求传参
func func4(a int, args ...int) {
fmt.Println("a =", a)
for i, data := range args {
fmt.Printf("args[%d] = %d\n", i, data)
}
}
// 注意:不定参数一定要放在形参中的最后一个参数位置。
// func func5(args ...int, a int) {
// }
func main() {
func1(666, 777)
fmt.Println("--------------------------")
func2(111, 222, 333, 444, 555)
fmt.Println("--------------------------")
func3(10, 11, 12, 13, 14, 15)
fmt.Println("--------------------------")
func4(9, 10, 11, 12, 13, 14, 15)
fmt.Println("--------------------------")
func4(9)
}
4、不定参数传参
package main
import "fmt"
func func1(tmp ...int) {
for _, data := range tmp {
fmt.Println("data =", data)
}
}
func func2(tmp ...int) {
for _, data := range tmp {
fmt.Println("data =", data)
}
}
func test(args ...int) {
// 全部元素传递给func1
// func1(args...)
// 只想把后2个参数传递给两外一个函数使用
func2(args[:2]...) // args[0]~args[2] 不包括数字args[2],传递过去
fmt.Println("-----------------")
func2(args[2:]...) // 从args[2]开始 包括本身,把后面所有元素传递过去
}
func main() {
test(1, 2, 3, 4)
}
5、一个返回值
package main
import "fmt"
// 无参有返回值:只有一个返回值
// 有返回值的函数需要通过return中断函数,通过return返回
func func1() int {
return 666
}
// 给返回值起一个变量名,Go推荐写法
func func2() (result int) {
return 666
}
// 给返回值起一个变量名,Go推荐写法
// 常用写法
func func3() (result int) {
result = 666
return result
}
func main() {
// 无参有返回值函数调用
var a int
a = func1()
fmt.Println("a =", a)
b := func2()
fmt.Println("b =", b)
c := func3()
fmt.Println("c =", c)
}
6、有多个返回值
package main
import "fmt"
// 有多个返回值
func func1() (int, int, int) {
return 3306, 3307, 3308
}
// Go官方推荐写法
func func2() (a int, b int, c int) {
a, b, c = 3306, 3307, 3308
return
}
func func3() (a, b, c int) {
a, b, c = 3306, 3307, 3308
return
}
func main() {
// 函数调用
a, b, c := func3()
fmt.Printf("a = %d, b = %d, c = %d\n", a, b, c)
}
7、有参有返回值
package main
import "fmt"
func func1(a, b int) (max, min int) {
if a > b {
max = a
min = b
} else {
max = b
min = a
}
return // 有返回值的函数,必须通过return返回
}
func main() {
max, min := func1(10, 20)
fmt.Printf("max = %d, min = %d\n", max, min)
}
8、普通函数的调用流程
package main
import "fmt"
func funcc(c int) {
fmt.Println("c =", c)
}
func funcb(b int) {
funcc(b - 1)
fmt.Println("b =", b)
}
func funca(a int) {
funcb(a - 1)
fmt.Println("a =", a)
}
func main() {
funca(3) // 调用函数
fmt.Println("--------------> main")
}
9、函数递归调用的流程
package main
import "fmt"
func test(a int) { // 函数终止调用的条件,非常重要
if a == 1 {
fmt.Println("a =", a)
return // 终止函数调用
}
// 函数调用自身
test(a - 1)
fmt.Println("a =", a)
}
func main() {
test(3)
fmt.Println("---------------> main")
}
10、数字累加
package main
import "fmt"
// 实现1加到100
func test01() (sum int) {
for i := 1; i <= 100; i++ {
sum += i
}
return
}
func test02(i int) int {
if i == 1 {
return 1
}
return i + test02(i-1)
}
func test03(i int) int {
if i == 100 {
return 100
}
return i + test03(i+1)
}
func main() {
var sum int
sum = test01()
fmt.Println("sum =", sum)
sum = test02(100)
fmt.Println("sum =", sum)
sum = test03(1)
fmt.Println("sum =", sum)
}
11、函数类型
package main
import "fmt"
func add(a, b int) int {
return a + b
}
func minus(a, b int) int {
return a - b
}
// 函数也是一种数据类型,通过type给一个函数类型起名
// FuncType它是一个函数类型
type functype func(int, int) int // 没有函数名字,没有{}
func main() {
var result int
result = add(1, 1) // 传统调用方式
fmt.Println("result1 =", result)
// 声明一个函数类型的变量,变量名叫ftest
var ftest functype
ftest = add // 是变量就可以赋值
result = ftest(10, 20) // 等价于add(10, 20)
fmt.Println("result2 =", result)
ftest = minus
result = ftest(10, 5) // 等价于minus(10, 5)
fmt.Println("result3 =", result)
}
12、回调函数
package main
import "fmt"
type functype func(int, int) int
// 加法
func add(a, b int) int {
return a + b
}
// 减法
func minus(a, b int) int {
return a - b
}
// 乘法
func mul(a, b int) int {
return a * b
}
// 回调函数,函数有一个参数是函数类型,这个函数就是回调函数。
// 计算器,可以进行四则远算
// 多态,多种形态,调用同一个接口,不同的表现,可以实现不同表现,加减乘除
// 现有想法,后面再实现功能
func calc(a, b int, ftest functype) (result int) {
fmt.Println("calc")
result = ftest(a, b) // 这个函数还没有实现
// result = add(a, b) // add()必须先定义后,才能调用
return
}
func main() {
a := calc(1, 2, add)
fmt.Println("a =", a)
}
13、匿名函数和闭包
package main
import "fmt"
func main() {
a := 10
name := "zhouwanchun"
// 匿名函数,没有函数名字,函数定义,还没有调用
f1 := func() { // 自动推导类型
fmt.Println("a =", a)
fmt.Println("name =", name)
}
f1()
fmt.Println("-----------------------------")
// 给一个函数类型起别名
type FuncType func() // 函数没有参数,没有返回值
// 声明变量
var f2 FuncType
f2 = f1
f2()
fmt.Println("-----------------------------")
// 定义匿名函数,同时调用
func() {
fmt.Printf("a = %d, name = %s\n", a, name)
}() // 后面的()代表调用此匿名函数
fmt.Println("-----------------------------")
// 带参数的匿名函数
f3 := func(i, j int) {
fmt.Printf("i = %d, j = %d\n", i, j)
}
f3(1, 2)
fmt.Println("-----------------------------")
// 定义匿名函数,同时调用
func(i, j int) {
fmt.Printf("i = %d, j = %d\n", i, j)
}(10, 20)
fmt.Println("-----------------------------")
// 匿名函数,有参有返回值
x, y := func(i, j int) (max, min int) {
if i > j {
max = i
min = j
} else {
max = j
min = i
}
return
}(10, 20)
fmt.Printf("x = %d, y = %d\n", x, y)
}
14、闭包捕获外部变量的特点
package main
import "fmt"
func main() {
a := 100
name := "zhouwanchun"
fmt.Printf("外部:a = %d, name = %s\n", a, name)
func() {
// 闭包以引用方式捕获外部变量
a = 666
name = "eric"
fmt.Printf("内部:a = %d, name = %s\n", a, name)
}() // ()代表直接调用
fmt.Printf("外部:a = %d, name = %s\n", a, name)
}
15、闭包的特点
package main
import "fmt"
// 函数的返回值是一个匿名函数,返回一个函数类型
func test01() func() int {
var x int // 没有初始化,值为0
return func() int {
x++
return x * x
}
}
func test02() int {
// 函数被调用时,x才分配空间,才初始化为0
var x int // 没有初始化,值为0
x++
return x * x // 函数调用完毕,x自动释放
}
func main() {
// 返回值为一个匿名函数,返回一个函数类型,通过f来调用返回的匿名函数,f来调用闭包函数。
// 它不关心这些捕获了的变量和常量是否已经超出了作用域。
// 所以只有闭包还在使用它,这些变量就还会存在。
f := test01()
fmt.Println(f())
fmt.Println(f())
fmt.Println(f())
fmt.Println(f())
fmt.Println(f())
fmt.Println(f())
fmt.Println(f())
fmt.Println(f())
fmt.Println(f())
fmt.Println("--------------------")
fmt.Println(test02())
fmt.Println(test02())
fmt.Println(test02())
fmt.Println(test02())
fmt.Println(test02())
fmt.Println(test02())
fmt.Println(test02())
}
16、defer的使用
package main
import "fmt"
func main() {
// defer 延迟调用,main函数结束前调用
defer fmt.Println("show databases ;")
fmt.Println("mysql -uroot -p123456 -S /data/3306/mysql.sock")
}
17、多个defer的执行顺序
package main
import "fmt"
func test(x int) {
result := 100 / x
fmt.Println("result =", result)
}
func main() {
defer fmt.Println("show databases ;")
defer fmt.Println("mysql -uroot -p123456 -S /data/3306/mysql.sock")
// 调用一个函数,导致内存出问题
defer test(2)
defer fmt.Println("先执行我")
}
18、defer和匿名函数结合使用
package main
import "fmt"
func main() {
a := 10
b := 20
defer func(a, b int) {
fmt.Printf("a = %d, b = %d\n", a, b)
}(a, b) // ()代表调用此匿名函数,把参数传递过去,已经先传递参数,只是没有调用
defer func(a, b int) {
fmt.Printf("a = %d, b = %d\n", a, b)
}(30, 40) // ()代表调用此匿名函数,把参数传递过去,已经先传递参数,只是没有调用
a = 111
b = 222
fmt.Printf("外部:a = %d, b = %d\n", a, b)
c := 10
d := 20
defer func() {
fmt.Printf("c = %d, b = %d\n", c, d)
}() // ()代表调用此匿名函数
c = 111
d = 222
fmt.Printf("外部:c = %d, d = %d\n", c, d)
}
19、获取命令行参数
package main
import "fmt"
import "os"
func main() {
// 接收用户传递的参数,都是以字符串方式传递
list := os.Args
n := len(list)
fmt.Println("n =", n)
// xxx.exe a b
for i := 0; i < n; i++ {
fmt.Printf("list[%d] = %s\n", i, list[i])
}
for i, data := range list {
fmt.Printf("list[%d] = %s\n", i, data)
}
}
// F:\go\day01>go build 1_zhouwanchun.go
// F:\go\day01>1_zhouwanchun.exe a b c
// F:\go\day01>1_zhouwanchun.exe a b c
// n = 4
// list[0] = 1_zhouwanchun.exe
// list[1] = a
// list[2] = b
// list[3] = c
// list[0] = 1_zhouwanchun.exe
// list[1] = a
// list[2] = b
// list[3] = c
20、局部变量
package main
import "fmt"
func test() {
a := 10
fmt.Println("a = ", a)
}
func main() {
// 定义在{}里面的变量就是局部变量,只能在{}里面有效
// 执行到定义变量那句话,才开始分配空间,离开作用域自动释放
// 作用域,变量其作用的范围
a := 111
{
a = 10
fmt.Println("a = ", a)
}
// a = 222
if flag := 3; flag == 3 {
fmt.Println("flag = ", flag)
}
// flag = 4
}
21、全局变量
package main
import "fmt"
func test() {
fmt.Println("test a =", a)
}
// 定义在函数外部的变量是全局变量
// 全局变量在任何地方都能使用
var a int
func main() {
a = 10
fmt.Println("a =", a)
test()
}
22、不同作用域同名变量
package main
import "fmt"
var a byte // 全局变量
func main() {
fmt.Printf("a的类型是%T\n", a) // uint8
var a int // 局部变量
// 不同作用域,允许定义同名变量
// 使用变量的原则,就近原则
fmt.Printf("a的类型是%T\n", a) // int
{
var a float32
fmt.Printf("a的类型是%T\n", a) // float32
}
test()
}
func test() {
fmt.Printf("a的类型是%T\n", a) // uint8 就是byte
}
23、导入包
package main
// 忽略此包
import _ "fmt"
func main() {
}
// 给包名起别名
import io "fmt"
func main() {
io.Println("this is a test.")
}
// .操作
import . "fmt" // 调用函数,无需通过包名
import . "os"
func main() {
Println("this is a test.")
Println("os.Args =", Args)
}
// 方式1
import "fmt" // 导入包,必须使用,否则编译不过
import "os"
// 方式2
import (
"fmt"
"os"
)
func main() {
fmt.Println("this is a test.")
fmt.Println("os.Args =", os.Args)
}
24、Go的工程管理
// 同级目录
1.分文件编程,多个源文件,必须放在src目录
2.设置GOPATH环境变量:为src所在的上一级绝对路径
3.同一个目录,包名必须一样
4.go env查看go相关的环境路径
5.同一个目录,调用别的文件的函数,直接调用即可,无需包名引用
[root@linux-node2 ~]# tree src
src
├── main.go
└── test.go
0 directories, 2 files
src
main.go
package main
func main() {
test()
}
test.go
package main
import "fmt"
func test() {
fmt.Println("this is a test.")
}
// 不同目录
1.不同目录,包名就不一样
2.调用不同包里面的函数,格式:包名.函数名()
3.调用别的包的函数,这个包的函数名字如果首字母是小写,无法让别人调用。要想别人能调用,必须首字母大写。
4.只要你导入一个包,Golang就会先执行被导入包的init()函数,然后在执行你的主程序main()函数
执行循序:被导出包的init()函数--->本身初始化init()函数--->main()入口函数
[root@linux-node2 ~]# tree src
src
├── calc
│ └── calc.go
└── main.go
1 directory, 2 files
src
calc
calc.go
package calc
import "fmt"
func init() {
fmt.Println("this is calc init.")
}
func Add(a, b int) int {
return a + b
}
main.go
package main
import (
"fmt"
"calc"
)
func init() {
fmt.Println("this is main init.")
}
func main() {
a := calc.Add(10, 20)
fmt.Println("a =", a)
}
原来是go build
src/main.exe 可执行程序
src: 放源代码
如果有多个文件或多个包
1.配置GOPATH环境变量,配置src同级目录的绝对路径
如:C:\Users\zhouwanchun\Desktop\code\go\src\
2.自动生成bin或pkg目录,需要使用go install命令(了解)
除了要配置GOPATH=环境变量,还要配置GOBIN=环境变量
src : 放源代码
bin : 放可执行程序
pkg : 放平台相关的库
Go语言 函数,工程管理的更多相关文章
- go语言入门(5)工程管理
在工程中不会简单到只有一个源代码文件,且源文件之间会有相互的依赖关系,早期Go语言使用makefile作为工程管理的临时方案,后来的Go命令行工具的革命性之处在于彻底消除了工程文件的概念,完全用目录结 ...
- go语言20小时从入门到精通(六、工程管理)
在实际的开发工作中,直接调用编译器进行编译和链接的场景是少而又少,因为在工程中不会简单到只有一个源代码文件,且源文件之间会有相互的依赖关系.如果这样一个文件一个文件逐步编译,那不亚于一场灾难. Go语 ...
- go语言基础之工程管理和工作区介绍
1.工程管理 在实际的开发工作中,直接调用编译器进行编译和链接的场景是少而又少,因为在工程中不会简单到只有一个源代码文件,且源文件之间会有相互的依赖关系.如果这样一个文件一个文件逐步编译,那不亚于一场 ...
- Golang编程的工程管理
Golang编程的工程管理 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.
- JVM内存管理------JAVA语言的内存管理概述
引言 内存管理一直是JAVA语言自豪与骄傲的资本,它让JAVA程序员基本上可以彻底忽略与内存管理相关的细节,只专注于业务逻辑.不过世界上不存在十全十美的好事,在带来了便利的同时,也因此引入了很多令人抓 ...
- 使用BLADE构建c++工程管理
使用BLADE构建c++工程管理 字数764 阅读2753 评论2 喜欢4 一. c++工程依赖管理 之前在百度一直使用comake2构建c++项目,十分方便.免去了手写Makefile的痛苦,很多项 ...
- C语言的内存管理
C语言的内存管理 转载:http://blog.csdn.net/wind19/article/details/5964090 对于一个C语言程序而言,内存空间主要由五个部分组成代码段(.text ...
- 动态修改 C 语言函数的实现
Objective-C 作为基于 Runtime 的语言,它有非常强大的动态特性,可以在运行期间自省.进行方法调剂.为类增加属性.修改消息转发链路,在代码运行期间通过 Runtime 几乎可以修改 O ...
- C语言堆内存管理上出现的问题,内存泄露,野指针使用,非法释放指针
C语言堆内存管理上出现的问题,内存泄露,野指针使用,非法释放指针 (1)开辟的内存没有释放,造成内存泄露 (2)野指针被使用或释放 (3)非法释放指针 (1)开辟的内存没有释放.造成内存泄露,以下的样 ...
随机推荐
- dockerfile创建php容器(安装memcached、redis、gd、xdebug扩展)
dockerfile创建php容器(含有memcached.redis.gd.xdebug扩展) 代码如下: FROM php:7.2-fpm COPY redis-3.1.6.tgz /home/r ...
- monkey如何获取app包名
别人学习网址:http://www.51testing.com/html/58/15092658-2984032.html 使用aapt aapt是sdk自带的一个工具,在sdk\builds- ...
- WPF 控件总结
内容控件:1.Button:当Button.IsCancel="True"时,点击按钮,对话框关闭.当Button.IsDefault="True",按回车触发 ...
- jdk源码剖析三:锁Synchronized
一.Synchronized作用 (1)确保线程互斥的访问同步代码 (2)保证共享变量的修改能够及时可见 (3)有效解决重排序问题.(Synchronized同步中的代码JVM不会轻易优化重排序) 二 ...
- Jmeter之函数助手
本文转载自:心的开始 Emily0120 JMeter函数是一些能够转化在测试树中取样器或者其他配置元件的域的特殊值.一个函数的调用就像这样:${_functionName(var1,var2,va ...
- Zookeeper 三台主机 Ha集群的搭建
前期准备1.修改Linux主机名 2.修改IP 3.修改主机名和IP的映射关系 /etc/hosts ######注意######如果你们公司是租用的服务器或是使用的云主机(如华为用主机.阿里云主机等 ...
- HanLP代码与词典分离方案与流程
之前在spark环境中一直用的是portable版本,词条数量不是很够,且有心想把jieba,swcs词典加进来, 其他像ik,ansi-seg等分词词典由于没有词性并没有加进来. 本次修改主要是采用 ...
- NLB网路负载均衡管理
相对于ARR来说,ARR算是应用级别的负载均衡方案,而NLB则是服务器级别的负载均衡方案.ARR只能做请求入口的消息分发服务,这样如果我们的消息分发服务器给挂掉,那么做再多的应用服务集群也都枉然. A ...
- messageBox 的几种显示方式
1.最简单的,只显示提示信息 MessageBox.Show("Hello~~~~"); 2. 可以给消息框加上标题. MessageBox.Show("There ar ...
- URL中传递参数给视图函数
1. 采用在url中使用变量的方式: 在path的第一个参数中,使用<参数名>的方式可以传递参数.然后在视图函数中也要写一个参数,视图函数中的参数必须和url中的参数名称保持一致,不然就找 ...