栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

4.Go编程快速入门学习

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

4.Go编程快速入门学习

0x00 Go语言基础之指针

    • 1.指针地址

    • 2.指针类型

    • 3.指针取值

    • 4.指针特性

    • 5.内存地址分配

0x01 Go语言基础之函数

  • 1.函数定义

  • 2.函数调用

  • 3.函数参数

    • 固定参数

    • 可变参数

  • 4.函数返回

    • 单返回值

    • 多返回值

    • 返回值命名

    • 返回值补充

  • 5.函数中变量作用域

    • 全局变量

    • 局部变量

  • 6.函数类型与变量

    • 定义函数类型

    • 函数类型变量

  • 7.高阶函数

    • 函数作为参数

    • 函数作为返回值

  • 8.函数补充

    • 递归函数

    • 匿名函数

    • 闭包

    • defer 语句

    • 函数总结示例


0x00 Go语言基础之指针

描述: Go 语言中的指针区别于C/C++中的指针,Go语言中的指针不能进行偏移和运算是安全指针。

Go 语言中三个重要概念: 指针地址、指针类型以及指针取值。

简单回顾: 任何程序数据载入内存后,在内存都有他们的地址这就是指针。而为了保存一个数据在内存中的地址,我们就需要指针变量。

比如,“永远不要高估自己”这句话是我的座右铭,我想把它写入程序中,程序一启动这句话是要加载到内存(假设内存地址0x123456),我在程序中把这段话赋值给变量A,把内存地址赋值给变量B。这时候变量B就是一个指针变量, 通过变量A和变量B都能找到我的座右铭。

Go语言中的指针操作非常简单,我们只需要记住两个符号:&(取地址) 和 *(根据地址取值)。

1.指针地址

描述: 每个变量在运行时都拥有一个地址,该地址代表变量在内存中的位置。

Go语言中使用&字符放在变量前面对变量进行“取地址”操作。

取变量指针(地址)的语法如下:

ptr := &v    // v的类型为T

// # 参数
// v:代表被取地址的变量,类型为T
// ptr:用于接收地址的变量,ptr的类型就为*T,称做T的指针类型。*代表指针。
2.指针类型

描述: Go语言中的值类型(int、float、bool、string、array、struct)都有对应的指针类型,如:*int、*int64、*string等。

简单示例:

func main() {
	a := 10
	b := &a
	fmt.Printf("a:%d ptr:%pn", a, &a)             // a:10 ptr:0xc00001a078 (指针地址)
	fmt.Printf("*b:%d ptr:%p type:%Tn",*b, b, b)  // b:10 ptr:0xc00001a078 type:*int (指针类型)
	fmt.Printf("&b ptr:%p ",b)                     // &b ptr:0xc00000e018
}

为了更好的理解指针地址,我们来看一下b := &a的图示:

3.指针取值

描述: 在对普通变量使用&操作符取地址后会获得这个变量的指针,然后可以对指针使用*操作,也就是指针取值,代码如下。

func main() {
	//指针取值
	a := 10
	b := &a // 取变量a的地址,将指针保存到b中
	fmt.Printf("type of b:%Tn", b)
	c := *b // 指针取值(根据指针去内存取值)
	fmt.Printf("type of c:%Tn", c)
	fmt.Printf("value of c:%vn", c)
}

输出结果:

type of b:*int
type of c:int
value of c:10
4.指针特性

描述: 通过上面的指标变量、类型、取值的学习,我们了解到取地址操作符&和取值操作符*是一对互补操作符,其中&取出地址,*根据地址取出地址指向的值。

Tips : 变量、指针地址、指针变量、取地址、取值的相互关系和特性如下:

  • 1.对变量进行取地址(&)操作,可以获得这个变量的指针变量(指针地址)。

  • 2.对指针变量进行取值(*)操作,可以获得指针变量指向的原变量的值。

例如:我们可以在局部函数中修改全局变量的值采用指针传值:

func modify1(x int) {
	x = 100
}

func modify2(x *int) {
	*x = 100
}

func main() {
	a := 10
	modify1(a)
	fmt.Println(a) // 10
	modify2(&a)
	fmt.Println(a) // 100
}
5.内存地址分配

描述: 在Go语言中对于引用类型的变量,我们在使用的时候不仅要声明它,还要为它分配内存空间,否则我们的值就没办法存储。而对于值类型的声明不需要分配内存空间,是因为它们在声明的时候已经默认分配好了内存空间。
Tips :Go语言中new和make是内建的两个函数,他主要用来分配内存。

例如:执行下述例子中的代码会引发panic错误

func main() {
  // 声明
	var a *int
  // 定义
	*a = 100

	fmt.Println(*a)

	var b map[string]int
	b["沙河娜扎"] = 100
	fmt.Println(b)
}

New 函数
描述: new是Go语言的一置的函数它的函数签名如下:

func new(Type) *Type

其中,

  • Type 表示类型,new 函数只接受一个参数,这个参数是一个类型

  • *Type 表示类型指针,new 函数返回一个指向该类型内存地址的指针。

Tips :New 函数不太常用但由它可以得到一个类型的指针,并且该指针对应的值应该为该类型的零值。

func main() {
  // 只是声明了一个指针变量a但是没有初始化
	a := new(int)
	b := new(bool)
	fmt.Printf("%Tn", a) // *int
	fmt.Printf("%Tn", b) // *bool
	fmt.Println(*a)       // 0
	fmt.Println(*b)       // false
}

Tips : 指针作为引用类型需要初始化后才会拥有内存空间才可以给它赋值,所以需要按照下述方式使用内置的new函数对a进行初始化之后就可正常对其赋值了。

func main() {
	var a *int
	a = new(int)
	*a = 10
	fmt.Println(*a)
}

make 函数
描述: make也是用于内存分配的,区别于new,它只用于slice、map以及chan的内存创建,而且它返回的类型就是这三个类型本身,而不是他们的指针类型,因为这三种类型就是引用类型,所以就没有必要返回他们的指针了。

函数签名如下:

func make(t Type, size ...IntegerType) Type

Tips : Type 主要是 slice、map 以及channel类型,并且必须使用make进行初始化后,才能对它进行操作。

例如:

func main() {
  // 只是声明变量b是一个map类型的变量
	var b map[string]int
  //使用make函数进行初始化操作之后
	b = make(map[string]int, 10)
  //才能对其进行键值对赋值:
	b["WeiyiGeek"] = 100
	fmt.Println(b)
}

总结:new 函数与 make函数的区别

  • 二者都是用来做内存分配的。

  • make只用于slice、map以及channel的初始化,返回的还是这三个引用类型本身;

  • new用于类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针。

示例演示:

// 转入int类型的参数
func normal(x int) {
	x = 65535
  fmt.Printf("Func Param &x ptr : %p n", &x)
}

// 传入的参数为指针类型
func pointer(x *int) {
	*x = 65535
	fmt.Printf("Func Param x ptr : %p n", x)
}

func demo1() {
	// 1.2获得变量a的内存地址
	a := 1024
	b := &a
	fmt.Printf("a : %d , a ptr: %p, b ptr : %v , *b = %d n", a, &a, b, *b)
	fmt.Printf("b type: %T, &b ptr : %p n", b, &b)
	fmt.Println()
	// 2.针对变量a的内存地址进行重赋值(此时会覆盖变量a的原值)
	*b = 2048
	fmt.Printf("Change -> a : %d , a ptr: %p, b ptr : %v , *b = %d n", a, &a, b, *b)
	fmt.Printf("b type: %T, &b ptr : %p nn", b, &b)

	// 3.指针传值
	c := 4096
	normal(c)
	fmt.Println("After Normal Function c : ", c)
	pointer(&c)
	fmt.Printf("After Pointer Function c : %v, c ptr: %p nn", c, &c)

	// 4.new 内存地址申请
	var a4 *int
	/
}

func main() {
  recursion()
}

Tips : 递归函数对于解决数学上的问题是非常有用的,就像计算阶乘,生成斐波那契数列等。

示例1.n的阶乘计算

func factorial(n uint64) (ret uint64) {
	if n <= 1 {
		return 1
	}
	return n * factorial(n-1)
}
func demo1() {
	fmt.Println("5 的阶乘 : ", factorial(5))
}

执行结果:

5 的阶乘 :  120

示例2.利用递归求斐波那契数列

// 方式1
func Fibonacci(count uint64) (ret uint64) {
	if count == 0 {
		return 0
	}
	if count == 1 || count == 2 {
		return 1
	}
	ret = Fibonacci(count-1) + Fibonacci(count-2)
	return
}

func demo3() {
	count := 10
	fmt.Printf("%v 个斐波那契数列:", count)
	for i := 1; i < count; i++ {
		fmt.Printf("%v ", Fibonacci(uint64(i)))
	}
}

// 方式2.值得学习
// fib returns a function that returns successive Fibonacci numbers.
func fib() func() int {
	a, b := 0, 1
	return func() int {
		a, b = b, a+b
		return a
	}
}

func main() {
	f := fib()
	fmt.Println(f(), f(), f(), f(), f())
}

执行结果:

10 个斐波那契数列:1 1 2 3 5 8 13 21 34
匿名函数

描述: 函数当然还可以作为返回值,但是在Go语言中函数内部不能再像之前那样定义函数了,只能定义匿名函数。

Q: 什么是匿名函数?

答: 匿名函数就是没有函数名的函数,在很多编程语言中都有这样的特性。
匿名函数多用于实现回调函数和闭包。

Tips : 匿名函数因为没有函数名,所以没办法像普通函数那样调用,所以匿名函数需要保存到某个变量或者作为立即执行函数:

func main() {
	// 方式1.将匿名函数保存到变量
	add := func(x, y int) {
		fmt.Println(x + y)
	}
	add(10, 20) // 通过变量调用匿名函数

	//方式2.自执行函数:匿名函数定义完加()直接执行
	func(x, y int) {
		fmt.Println(x + y)
	}(10, 20)
}
闭包

描述: 闭包指的是一个函数和与其相关的引用环境组合而成的实体。简单来说,闭包=函数+外遍变量的引用, 例如在第三方包里只能传递一个不带参数的函数,此时我们可以通过闭包的方式创建一个带参数处理的流程,并返回一个不带参数的函数。

Tips : 非常注意引用的外部外部变量在其生命周期内都是存在的(即下次调用还能使用该变量值)。

闭包基础示例1:

func adder() func(int) int {
	var x int  // 在f的生命周期内,变量x也一直有效
	return func(y int) int {
		x += y
		return x
	}
}
func main() {
	var f = adder()
	fmt.Println(f(10)) //x=0,y=10 ->  x = 10
	fmt.Println(f(20)) //x=10,y=20 -> x = 30
	fmt.Println(f(30)) //x=30,y=30 -> x = 60

	f1 := adder()
	fmt.Println(f1(40)) //40
	fmt.Println(f1(50)) //90
}

闭包基础示例2:

package main

import (
	"fmt"
	"math"
)

// 1.假设这是个第三方包
func f1(f func()) {
	fmt.Printf("# This is f1 func , Param is f func() : %T n", f)
	f() // 调用传入的函数
}

// 2.自己实现的函数
func f2(x, y int) {
	fmt.Printf("# This is f2 func , Param is x,y: %v %vn", x, y)
	fmt.Printf("x ^ y = %v n", math.Pow(float64(x), float64(y)))
}

// 要求 f1(f2) 可以执行,此时由于f1 中的传递的函数参数并无参数,所以默认调用执行一定会报错。
// 此时我们需要一个中间商利用闭包和匿名函数来实现,返回一个不带参数的函数。

func f3(f func(int, int), x, y int) func() {
	tmp := func() {
		f(x, y) // 此处实际为了执行f2函数
	}
	return tmp // 返回一个不带参数的函数,为返回给f1函数
}

func main() {
	ret := f3(f2, 2, 10) // 此时函数并为执行只是将匿名函数进行返回。先执行 f3(fun,x,y int)
	f1(ret)              // 当传入f1中时ret()函数便会进行执行。再执行 f1() ,最后执行 f2(x,y int)
}

执行结果:

# This is f1 func , Param is f func() : func() 
# This is f2 func , Param is x,y: 2 10
x ^ y = 1024

Tips : 变量f是一个函数并且它引用了其外部作用域中的x变量,此时f就是一个闭包。并且在f的生命周期内,变量x也一直有效。

闭包进阶示例1:相比较于上面这种方式该种是将x变量放入函数参数之中,在进行函数调用时赋值。

func adder2(x int) func(int) int {
	return func(y int) int {
		x += y
		return x
	}
}
func main() {
	var f = adder2(10) // `在f的生命周期内,变量x也一直有效。`
	fmt.Println(f(10)) //20
	fmt.Println(f(20)) //40
	fmt.Println(f(30)) //70

	f1 := adder2(20)
	fmt.Println(f1(40)) //60
	fmt.Println(f1(50)) //110
}

闭包进阶示例2:判断文件名称是否以指定的后缀结尾,是则返回原文件名称,否则返回文件名称+指定后缀的文件。

func makeSuffixFunc(suffix string) func(string) string {
	return func(name string) string {
    // 判断name变量中的字符串是否已suffix结尾
		if !strings.HasSuffix(name, suffix) {
			return name + suffix
		}
		return name
	}
}

func main() {
	jpgFunc := makeSuffixFunc(".jpg")
	txtFunc := makeSuffixFunc(".txt")
	fmt.Println(jpgFunc("test")) //test.jpg
	fmt.Println(txtFunc("test")) //test.txt
}

闭包进阶示例3:该示例中函数同时返回add,sub两个函数.

func calc(base int) (func(int) int, func(int) int) {
	add := func(i int) int {
		base += i
		return base
	}

	sub := func(i int) int {
		base -= i
		return base
	}
	return add, sub
}

func main() {
	f1, f2 := calc(10)
	fmt.Println(f1(1), f2(2)) //11 9
	fmt.Println(f1(3), f2(4)) //12 8
	fmt.Println(f1(5), f2(6)) //13 7
}

Important : 闭包其实并不复杂,只要牢记闭包=函数+引用环境。

defer 语句

描述: Go语言中的defer语句会将其后面跟随的语句进行延迟处理。在defer归属的函数即将返回时,将延迟处理的语句按defer定义的逆序进行执行(压栈-后进先出),也就是说,先被defer的语句最后被执行,最后被defer的语句,最先被执行。

(1) defer 执行时机
描述: 在Go语言的函数中return语句在底层并不是原子操作,它分为给返回值赋值和RET指令两步。而defer语句执行的时机就在返回值赋值操作后,RET指令执行前。

具体如下图所示:

(2) 简单例子

示例1: defer 延迟特性演示

func main() {
	fmt.Println("start")
	defer fmt.Println(1)
	defer fmt.Println(2)
	defer fmt.Println(3)
	fmt.Println("end")
}

// 输出结果:
start
end
3
2
1

示例2.探究程序执行开始时间以及最后函数返回前的时间

func funcTime() int {
	fmt.Println("函数开始时间: ", time.Now().Local())
	var x = 0
	defer fmt.Println("init x = ", x) // 注意点: 此处已经将x=0值赋值了,只是没有被输出。// 最终输出
	for i := 0; i <= 100; i++ {
		x += i
	}
	defer fmt.Println("函数返回前时间: ", time.Now().Local()) // 再输出
	defer fmt.Println("ret x = ", x)                   // 后进先出 -> 先输出
	return x
}

// 输出结果:
函数开始时间:  2021-08-15 18:28:58.37787611 +0800 CST
ret x =  5050
函数返回前时间:  2021-08-15 18:28:58.377991344 +0800 CST
init x =  0

Tips : 由于defer语句延迟调用的特性,所以defer语句能非常方便的处理资源释放问题。比如:资源清理、文件关闭、解锁及记录时间等。

(3) 经典面试案例
示例1:

package main

import "fmt"

// 函数返回值无命名
func f1() int {
	x := 5 // 局部变量
	defer func() {
		x++
	}()
	return x // 1.返回值 x = 5, 2.defer 语句执行后修改的是 x = 6,3.RET指令最后返回的值是 5 (由于无返回值命令则就是return已赋予的值5)
}

// 函数返回值命名 y 进行返回
func f2() (x int) {
	defer func() {
		x++
	}()
	return 5 // 1.返回值 x = 5, 2.defer 语句执行后修改的是 x = 6,3.RET指令最后返回的x值是 6 (由于存在返回值命名x则就是return x 值6)
}

// 函数返回值命名 y 进行返回
func f3() (y int) {
	x := 5 // 局部变量
	defer func() {
		x++ // 修改 x 变量的值 x + 1
	}()
	return x // 1.返回值 x = y = 5, 2.defer 语句执行后修改的是 x ,3.RET指令最后返回的y值还是 5
}

// 匿名函数无返回值
func f4() (x int) {
	defer func(x int) {
		x++ // 改变得是函数中局部变量x,非外部x变量。
	}(x)
	return 5 // 1.返回值 x = 5, 2.defer 语句执行后 x 副本 = 6 , 3.RET指令最后返回的值还是 5
}

// 匿名函数中返回值
func f5() (x int) {
	defer func(x int) int {
		x++ // 改变得是函数中局部变量x,非外部x变量。
		return x
	}(x)
	return 5 // 1.返回值 x = 5, 2.defer 语句执行后 x 副本 = 6 , 3.RET指令最后返回的值还是 5
}

// 传入一个指针到匿名函数中(方式1)
func f6() (x int) {
	defer func(x *int) {
		*x++
	}(&x)
	return 5 // 1.返回值 x = 5, 2.由于defer语句,传入x指针地址到匿名函数中 x = 6, 3.RET指令最后返回的值 6
}

// 传入一个指针到匿名函数中(方式2)
func f7() (x int) {
	defer func(x *int) int {
		(*x)++
		return *x
	}(&x)
	return 5 // 1.返回值x = 5, 2.由于defer语句,传入x指针地址到匿名函数中 x = 6, 3.RET指令最后返回值 6
}

func main() {
	fmt.Println("f1() = ", f1())
	fmt.Println("f2() = ", f2())
	fmt.Println("f3() = ", f3())
	fmt.Println("f4() = ", f4())
	fmt.Println("f5() = ", f5())
	fmt.Println("f6() = ", f6())
	fmt.Println("f7() = ", f7())
}

// 执行结果:
f1() =  5
f2() =  6
f3() =  5
f4() =  5
f5() =  5
f6() =  6
f7() =  6

示例2.问下面代码的输出结果是?(提示:defer注册要延迟执行的函数时该函数所有的参数都需要确定其值)

func calc(index string, a, b int) int {
  ret := a + b
  fmt.Println(index, a, b, ret)
  return ret
}

func main() {
  x := 1
  y := 2
  defer calc("AA", x, calc("A", x, y))
  // calc("A", x, y) =>calc("A", 1, 2) = 3  {"A" , 1, 2, 3}
  // defer calc("AA", 1, 3) = 4 {"AA", 1, 3, 4}
  x = 10
  defer calc("BB", x, calc("B", x, y))
  // calc("B", x, y) = calc("B", 10, 2) = 12  {"B" , 10, 2, 12}
  // defer calc("BB", 10, 12) = 22 {"BB",10,12,22}
  y = 20
}

// 执行结果:
{"A" , 1, 2, 3}
{"B" , 10, 2, 12}
{"BB", 10, 12, 22}
{"AA", 1, 3, 4}

Tips : 当遇到defer语句时其中的函数中调用的变量值是外部变量时,是离该defer语句最近的外部变量其赋予的值(存在于一个变量多次赋值的场景)。

函数总结示例
package main

import (
	"errors"
	"fmt"
	"strings"
	"time"
)

// 函数:将一段代码封装到代码块之中
// 1.无参函数
func f1() {
	fmt.Println("Hello World, Let's Go")
}

// 2.有参函数
func f2(name string) {
	fmt.Println("Hello", name)
}

// 3.函数返回值
func f3(i int, j int) int {
	sum := i + j
	return sum
}

// 4.函数多命名返回值与参数类型简写
func f4(x, y int) (sum, sub int) {
	sum = x + y
	sub = x - y
	return
}

// 5.可变参数
func f5(title string, value ...int) string {
	return fmt.Sprintf("Title : %v , Value : %v n", title, value)
}

// 6.变量作用域之全局变量

const PATH = "/home/weiyigeek"

var author = "WeiyiGeek"

func f6() {
	fmt.Println("author:", author, ",Home PATH:", PATH)
}

// 7.变量作用域之局部变量
func f7(x, y int) {
	localAuthor := "WeiyiGeek" // 局部变量外部无法引用
	fmt.Println("localAuthor = ", localAuthor, ",x = ", x, ",y = ", y)
	// 语句块定义的变量
	if x > 0 {
		z := 1024
		fmt.Println(z)
	}
	for i := 0; i < 10; i++ {
		fmt.Print(i, " ")
	}
	// fmt.Println(z,i)  //此处无法使用变量z 和 i
	fmt.Println()
}

// 8.函数类型与变量
type calc func(int, int) int

func sum(x, y int) int {
	return x + y
}
func sub(x, y int) int {
	return x - y
}
func f8() {
	// 方式1
	var c calc
	c = sum
	fmt.Printf("type of c:%T , c(1,2) :%v n", c, c(1, 2)) // type of c:main.calculation  (区别点)

	// 方式2
	d := sub
	fmt.Printf("type of d:%T , d(1,2) :%v n", d, d(1, 2)) // type of d:func(int, int) int (区别点)

}

// 9.函数作为参数值或者作为返回值
func mul(x, y int) int {
	return x * y
}
func div(x, y int) int {
	return x / y
}

// 函数作为参数值
func calculation(x, y int, op func(int, int) int) int {
	return op(x, y)
}

// 函数作为返回值
func ops(s string) (func(int, int) int, error) {
	switch s {
	case "+":
		return sum, nil
	case "-":
		return sub, nil
	case "*":
		return mul, nil
	case "/":
		return div, nil
	default:
		err := errors.New("无法识别的操作符")
		return nil, err
	}
}

func f9() {
	// 演示1
	fmt.Printf("Type : %T , calculation (10 , 20, mul) = %v n", calculation(10, 20, mul), calculation(10, 20, mul))

	// 演示2
	value, _ := ops("/")
	fmt.Printf("Type : %T , ops('/') ->  div(100,10) = %v nn", value(100, 10), value(100, 10))
}

// 10.匿名函数
func f10() {
	// 方式1
	muls := func(x, y int) int {
		fmt.Println("匿名函数1 之 x , y =", x, y)
		return x * y
	}
	ret := muls(3, 2)
	fmt.Println("匿名函数1 返回结果: ", ret)

	// 方式2
	func(x, y int) {
		fmt.Println("匿名函数2 之 x , y =", x*y)
	}(3, 2)

}

// 11.闭包
func adder1() func(int) int {
	var x int
	return func(y int) int {
		x += y
		return x
	}
}

func adder2(x int) func(int) int {
	return func(y int) int {
		x += y
		return x
	}
}

func makeSuffixFunc(suffix string) func(string) string {
	return func(name string) string {
		if !strings.HasSuffix(name, suffix) {
			return name + suffix
		}
		return name
	}
}

func f11() {
	// 方式1
	var f = adder1()
	fmt.Printf("n闭包 adder1: %vn", f(10)) //x=0,y=10  -> x = 10
	fmt.Println("闭包 adder1:", f(20))       //x=10,y=20 -> x = 30
	fmt.Println("闭包 adder1:", f(30))       //x=30,y=30 -> x = 60

	// 方式2
	g := adder2(10)
	fmt.Printf("闭包 adder2: %vn", g(10)) //x=10,y=10 -> x = 20
	fmt.Println("闭包 adder2:", g(20))     //x=20,y=20 -> x = 40
	fmt.Println("闭包 adder2:", g(30))     //x=40,y=30 -> x = 70

	// 示例3
	testJPG := makeSuffixFunc("jpg")
	fmt.Printf("闭包 makeSuffixFunc : file test = %v , file test.jpg = %v nn", testJPG("test"), testJPG("test.jpg"))
}

// 12.defer 语句使用演示
func funcTime() int {
	fmt.Println("函数开始时间: ", time.Now().Local())
	var x = 0
	defer fmt.Println("init x = ", x) // 注意点: 此处已经将x=0值赋值了,只是没有被输出。// 最终输出
	for i := 0; i <= 100; i++ {
		x += i
	}
	defer fmt.Println("函数返回前时间: ", time.Now().Local()) // 再输出
	defer fmt.Println("ret x = ", x)                   // 后进先出 -> 先输出
	return x
}

func f12() {
	ret := funcTime()
	fmt.Println("defer 示例1:1+2+3+....+99+100 =", ret)
}

func main() {
	f1()

	f2("WeiyiGeek")

	fmt.Println(f3(1, 1))

	x, y := f4(1, 3)
	fmt.Printf("x = %d ,y = %d n", x, y)

	fmt.Println(f5("我是一串数字:", 1, 2, 3, 4))

	f6()

	f7(1, 2)

	f8()

	f9()

	f10()

	f11()

	f12()
}

执行结果:

Hello World, Let''s Go
Hello WeiyiGeek
2
x = 4 ,y = -2 
Title : 我是一串数字: , Value : [1 2 3 4] 

author: WeiyiGeek ,Home PATH: /home/weiyigeek
localAuthor =  WeiyiGeek ,x =  1 ,y =  2
1024
0 1 2 3 4 5 6 7 8 9 
type of c:main.calc , c(1,2) :3 
type of d:func(int, int) int , d(1,2) :-1 
Type : int , calculation (10 , 20, mul) = 200 
Type : int , ops('/') ->  div(100,10) = 10 

匿名函数1 之 x , y = 3 2
匿名函数1 返回结果:  6
匿名函数2 之 x , y = 6

闭包 adder1: 10
闭包 adder1: 30
闭包 adder1: 60
闭包 adder2: 20
闭包 adder2: 40
闭包 adder2: 70
闭包 makeSuffixFunc : file test = testjpg , file test.jpg = test.jpg 

函数开始时间:  2021-08-15 19:35:19.159014152 +0800 CST
ret x =  5050
函数返回前时间:  2021-08-15 19:35:19.159208306 +0800 CST
init x =  0
defer 示例1:1+2+3+....+99


WeiyiGeek Blog - 为了能到远方,脚下的每一步都不能少。
Tips : 本文章来源 Blog 站点或者 WeiyiGeek 公众账号 (技术交流、友链交换请邮我哟),

  • 公众号-WeiyiGeek # 精华文章发布地址(及时发布)

  • 首页-https://weiyigeek.top # 国内有时访问较慢(及时更新)

  • 博客-https://blog.weiyigeek.top # 国内访问快但(更新不及时)

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/893103.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号