Go_秒懂函数、参数、可变参数、匿名函数、回调函数、内置函数

函数是将具有独立功能的代码块组成一个整体,使其具有特殊功能的代码集。它将复杂的算法过程分解为若干个小任务,隐藏相关细节,使得程序结构更加清晰,易于维护。通过接收输入参数完成一段算法指令,输出或存储相关结果。因此,函数还是代码复用和测试的基本单元。

关键字func用于定义函数

  • 函数必须先定义,后调用,定义的过程为函数定义

  • 函数创建后并不是直接可以运行的,需要手动使用后,才执行,该过程为函数调用

函数定义:

func 函数名(参数1 数据类型,参数2 数据类型...)(返回值1 返回值类型...){语句体return 返回值
}

函数调用:

函数调用时,参数的数量与数据类型必须与函数定义中的相匹配。

普通格式调用:

 函数名(形参列表)

函数值格式调用:

 变量 := 函数名(形参列表)

函数表达式格式调用:

 变量 := 类名.函数名(形参列表)

函数的返回值通常会使用变量接收,否则该返回值无意义。

 package functionimport "fmt"func Function(a int, b int) int {   // 定义函数function,两个形参分别是a、b,返回值类型是intreturn a + b
}func main() {// 普通格式调用Function(1, 2)  // 调用function,传入实参为1,2赋值给a、b// 函数值格式调用f := Function(1, 2)fmt.Println(f)
}————————————————————————————分界线————————————————————————————package mainimport (function "go_basics/func"
)func main() {// 函数表达式格式调用function.Function(1, 2)
}

函数只能判断是否为nil,不支持其他比较操作。

func main() {fmt.Println(function01 == nil)fmt.Println(function01 == function02) // 无效运算: function01 == function02 (在 func() 中未定义运算符 ==)
}
func function01() {}
func function02() {}

函数中的变量是局部的,函数外不生效。

func main() int {num := 1return num
}num // 报错,找不到num

参数:

基本类型和数组默认都是值传递,实参将自己的地址值拷贝一份给形参。如果参数是引用类型,那么就会改变实参的值。

形参和实参:

形参是指函数定义中的参数,实参则是函数调用时所传递的参数。形参相当于函数局部变量,而实参则是函数外部对象,可以是常量、变量、表达式或函数等。

形参:

形参就是函数定义中的参数,顾名思义就是只有一个形式,没有具体的数值,等同于变量定义格式。

例:

// num只是一个形式,num并没有赋值
func function(num int) {}

实参:

函数调用中的参数,顾名思义就是有实际的参数数值,等同于使用变量或常量。

例:

func main() {num := 10function(num) // 这里的num就已经赋值了
}func function(num int) {}

传递的形参即使在函数中操作,也不会影响原来的数据值。

 func main() {var a = 1var b = 2function(a, b)fmt.Println("a=",a, "b=",b)
}func function(a, b int) {a, b = b, afmt.Println("a=",a, "b=",b)
}

输出:

a=1,b=2
a=2,b=1

参数列表中,相邻的同数据类型参数可以合并数据类型,调用时必须按参数顺序传递指定类型的实参,就算以“_”命名也不能忽略。

func main() {function(1, 2, "abc") // 报错;'function' 调用中的实参不足,给bool变量赋值就可以了
}func function(x, y int, s string, _ bool) *int {return nil
}

参数可视作函数的局部变量,因此不能在函数内部再定义同名变量。

func main(x, y int) int {x := 100  // 错误:':=' 的左侧没有新变量var y int // 错误:此函数中重新声明了 'y'return x + y
}

不管是指针、引用类型,还是其他类型参数,都是值拷贝传递,无非是拷贝目标对象,还是拷贝指针自身而已。在函数调用时,会为形参和返回值分配内存空间,并将实参数据拷贝到形参内存。

func main() {a := 0x100p := &afmt.Println("p的内存地址:", &p, "\tp的值:", p)function(p)
}func function(x *int) {fmt.Println("x的内存地址:", &x, "\tx的值:", x)
}

输出:

p的内存地址: 0x1400011c018     p的值: 0x14000122008
x的内存地址: 0x1400011c028     x的值: 0x14000122008

如果希望函数内的变量能修改函数外的变量(指的是默认以值传递的方式的数据类型),可以传入变量的地址&,函数内以指针的方式操作变量。

func main() {num := 20function(&num)fmt.Println("main() num:", num)
}func function(num *int) {*num = *num + 10fmt.Println("function() num:", *num)
}

输出:

function() num: 30
main() num: 30

Go不支持函数重载。

func function(n1 int)         {}
func function(n1 int, n2 int) {} // 此包中重新声明的 'function'

函数也是一种数据类型,可以赋值给一个变量,那么这个变量就是一个函数类型的变量,通过该变量可以对函数调用。

func main() {z := function // 直接把函数赋值给一个变量fmt.Printf("变量z的数据类型为:%T\n,函数function的数据类型为:%T\n,", z, function)num := z(1, 2) // 因为是赋值给变量了,所以可以直接使用变量调用相当于原函数名本身,把返回值赋值给num再输出fmt.Println("num=", num)
}func function(x, y int) int {return x + y
}

输出:

变量z的数据类型为:func(int, int) int
函数function的数据类型为:func(int, int) int
num= 3

既然函数是一种数据类型,那么函数也可以作为形参,并且调用。

func main() {num := function(getSum, 20, 30)fmt.Println(num) //50
}func getSum(x, y int) int {return x + y
}// funcTest func(int, int) int是第一个参数
func function(funcTest func(int, int) int, num1, num2 int) int {return funcTest(num1, num2)
}

图解:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yF1wpNRm-1671382906199)(/Users/itzhuzhu/Library/Application Support/typora-user-images/image-20221219000230020.png)]

可变参数:

顾名思义函数中参个数是可以变化的,写函数时如果不确定形参长度,可以使用可变参数传递,可变变参本质上就是一个切片,它只能接收相同类型的参数值,且必须放在参数列表的最后。

查看可变参数类型

func main() {function("abc", 1, 2, 3, 4)
}func function(s string, a ...int) {fmt.Printf("%T, %v\n", a, a)
}

输出:

[]int, [1 2 3 4]

可变参数的使用:

func main() {function01(1, 2, 3, 4, 5)function02(111, 2, 3, 4, 5)}func function01(num ...int) {for i := 0; i < len(num); i++ {fmt.Println(num[i])}
}// 如果可变参数和其它参数一起作为形参时,可变参数需要放在后面
func function02(a int, num ...int) {for i := 0; i < len(num); i++ {fmt.Println(num[i])}fmt.Println(a)
}

变参是切片,那么参数复制的仅是切片自身,不包括底层数组,因此我们可以修改原数据。

func main() {a := []int{10, 20, 30}function(a...)fmt.Println(a)
}func function(a ...int) {for i := range a {a[i] += 100}
}

输出:

[10 20 30]

返回值

  • Go支持多个返回值,如果没有定义返回值,但是写了return,那么就相当于终止了函数,跳出循环的意思。
  • 返回值不想接收时候可以使用下划线忽略_
  • 返回值只有一个时可以不写括号,有多个似必须写括号。

没定义返回值但写了return就会终止,return后面的代码是不会执行的。

func main() {function(1, 2) // 结果为空
}func function(x, y int) {returnz := x + yfmt.Println(z)
}

函数后面只有返回值类型没有给返回值命名。

func main() {f := function(1, 2)fmt.Println(f)
}func function(x, y int) int {sum := x + yreturn sum
}

命名返回值

func main() {f := function(1, 2)fmt.Println(f) // 3
}// 要在参数后面加上返回值和返回值的数据类型,不需要在函数里再定义返回值
func function(x, y int) (sum int) {sum = x + yreturn // 函数返回值那里已经命名了,在函数中可以省略返回值名,直接return,相当于return sum
}

函数返回多个返回值:

func main() {x, y := function()fmt.Println("x = ", x, "\ty = ", y)
}func function() (int, int) {x := 1y := 2// 返回两个变量的值return x, y
}

有返回值的函数,必须有明确的return终止语句。

func function(x int) int {if x > 0 {return -1} else if x < 0 {return -1}
} // 错误:函数末尾缺少 'return' 语句func function(x int) int {for {break}
} // 错误:函数末尾缺少 'return' 语句

相同类型的多返回值可用作调用实参,或直接返回

func main() {log(test()) //多返回值直接用作实参。
}func log(x int, err error) {fmt.Println(x, err)
}func test() (int, error) {return div(5, 0) //多返回值直接用作return结果。
}func div(x, y int) (int, error) {if y == 0 {return 0, errors.New("error...")}return x / y, nil
}

匿名函数:

匿名函数就是没有名字的函数,如果某个函数只使用一次,就可以使用匿名函数,匿名函数也可以实现多次调用。

匿名函数除没有名字外,其他和普通函数完全相同。最大的区别是,我们可在函数内部定义匿名函数,形成类似嵌套函数的效果。匿名函数可直接调用,保存到变量,作为参数或返回值

作用:

  1. 匿名函数只有在被调用的时候才会开辟空间,执行完毕就会被销毁,可以节省内存
  2. 减少重名的风险
  3. 可以实现闭包

格式:

func(形参)(返回值) {函数体
}(实参) // 在定义的时候就已经传入了参数

无返回值匿名函数

func main() {func(s string) {fmt.Println(s)}("我是实参,上面的s是形参,我会被打印不")
}

输出:

我是实参,上面的s是形参,我会被打印不

有返回值匿名函数:把匿名函数赋值给一个变量,再通过变量调用函数

func main() {num := func(x, y int) int {return x + y}fmt.Println(num(1, 2))
}

全局匿名函数:把匿名函数赋值一个全局变量,那么这个匿名函数,就成为一个全局匿名函数,可以在程序有效。

var num = func(x, y int) int { // 匿名函数把结果赋值给num,然后调用num传入参数就可以了return x + y
}func main() {fmt.Println(num(1, 2))
}

如果定义了匿名函数但是没有使用会报错,在结尾传入参数就可以

func main() {func(x int) { // 报错:func 已评估但未使用fmt.Println(x)}
}

闭包

  • 闭包(closure)是在函数和其引用环境的组合体(匿名函数引用了匿名函数外部的数据,如变量、常量、函数等。)
  • 闭包让我们不用传递参数就可读取或修改环境状态,传入一次就可以反复使用

ClosePackage返回的匿名函数会引用匿名函数外部的变量x,这种现象就称作闭包,不管是变量,还是其它数据,只要是匿名函数引用了外部的数据,那么就会称为闭包,因为变量x只初始化一次,所以连续调用时候结果就会累计

func main() {num := ClosePackage()fmt.Println(num(1)) // 传入一个值为1,这个1会赋给匿名函数中的yfmt.Println(num(2))fmt.Println(num(3))
}func ClosePackage() func(int) int { // 定义一个函数,无形参,返回值是一个函数var x int = 1return func(y int) int { // ClosePackage函数的返回值是一个匿名函数x = y + 1 // 在这里使用匿名函数外的变量xreturn x}
}

输出:

2
3
4

通过输出指针,闭包直接引用了原环境变量。所以说闭包是函数和引用环境组合体更加确切

func main() {f := ClosePackage(0x100)f()
}func ClosePackage(x int) func() {println(&x)return func() {println(&x, x)}
}

输出:

0xc82000a100
0xc82000a100 256

闭包应用:

func main() {f := FileTest(".pdf")fmt.Println(f("Go语言学习笔记"))fmt.Println(f("Go语言学习笔记.韩顺平"))fmt.Println(f(".pdf"))
}func FileTest(FileName string) func(string) string {return func(name string) string {// 判断传入的name开头是否有指定的后缀(FileName),不等于就加上后缀,如果等于就返回nameif !strings.HasPrefix(name, FileName) {return name + FileName}return name}
}

输出:

Go语言学习笔记.pdf
Go语言学习笔记.韩顺平.pdf
.pdf

内置函数

make:为切片,map、通道类型分配内存并初始化对象。

len:计算数组、切片、map、通道的长度。

cap:计算数组、切片、通道的容量。

delete:删除 map 中对应的键值对。

append:将数据添加到切片的末尾。

copy:将原切片的数据复制到新切片中。

new:除切片、map、通道类型以外的类型分配内存并初始化对象,返回的类型为指针。

complex:生成一个复数。

real:获取复数的实部。

imag:获取复数的虚部

print:将信息打印到标准输出,没有换行。

println:将信息打印到标准输出并换行。

close:关闭通道。

panic:触发程序异常。

recover:捕捉 panic 的异常信息。

len:用来计算长度的,string、arr、slice、map、channel都可以

func main() {s := "itzhuhzu"fmt.Println("长度为:",len(s))
}

new:用来分配值内存的,int、float32、struct返回值是指针

func main() {num := 100fmt.Printf("num的类型:%T,num的值:%v,num的内存地址:%v\n", num, num, &num)num2 := new(int)*num2 = 100fmt.Printf("num2的类型:%T,num2的值:%v,num2的内存地址:%v,num2指向地址存储的数据:%v", num2, num2, &num2, *num2)
}

输出:

num的类型:int,num的值:100,num的内存地址:0x1400012c008
num2的类型:*int,num2的值:0x1400012c020,num2的内存地址:0x14000126020,num2指向地址存储的数据:100

直接定义变量的流程是:

开辟内存空间 -> 将数据存储到内存空间

适用new定义变量的流程是:

开启指针内存空间 -> 指向数据的内存地址

make:用来分配引用类型内存的,slice、map、channel


defer

defer用于向当前函数注册稍后执行的函数调用。这些调用被称作延迟调用,它们直到当前函数执行结束前才被执行,常用于资源释放、错误处理等操作

func main() {defer fmt.Println("第1个defer")defer fmt.Println("第2个defer")defer fmt.Println("第3个defer")fmt.Println("第1个输出")fmt.Println("第2个输出")fmt.Println("第3个输出")
}

输出:defer的结果是倒叙的,原因是:进入main函数发现了defer,就把defer抓走放在了一个独立的栈中等待执行(压栈),然后继续执行下面的,直到所有的程序执行完,才执行defer(弹栈),而栈内存是先进后出(就像弹夹一样,先放的子弹是最后才打出去的),所以是先输出了第3个defer

第1个输出
第2个输出
第3个输出
第3个defer
第2个defer
第1个defer

循环处理多个日志文件,defer导致文件关闭时机延长

func main() {for i := 0; i < 10000; i++ {path := fmt.Sprintf("./log/%d.txt", i)f, err := os.Open(path)if err != nil {log.Println(err)continue}defer f.Close()// 这个关闭操作在main函数结束时才会执行,而不是当前循环。// 延长了逻辑结束时间和f生命周期,平白多消耗了内存等资源。 // 编译器也会提醒:可能发生资源泄漏,在 'for' 循环中调用 'defer' }
}

应该直接调用,或重构为函数,让循环和处理算法分离

func main() {//日志处理算法。do := func(n int) {path := fmt.Sprintf("./log/%d.txt", n)f, err := os.Open(path)if err != nil {log.Println(err)return}defer f.Close() 	// 该延迟调用在此匿名函数结束时执行,而非main}for i := 0; i < 10000; i++ {do(i)}
}

init

init 函数最主要的作用,就是完成一些初始化的工作,每一个源文件都可以包含一个init函数,该函数会在main函数执行前被调用

var name = "itzhuzhu"
var age = 24func main() {fmt.Println("main方法执行")
}func init() {fmt.Println("init方法执行")fmt.Println("name=", name, "age=", age)
}

输出:

init方法执行
name= itzhuzhu age= 24
main方法执行

如果一个文件同时包含全局变量定义,init函数和main 函数,则执行的流程是 全局变量定义 > init > main

var num = test()func test() int {fmt.Println("test方法执行")return 2022
}
func init() {fmt.Println("init方法执行")
}
func main() {fmt.Println("main方法执行")
}

输出:

test方法执行
init方法执行
main方法执行

如果 main.go引用了utils.go,但是两个文件都含有定义变量、init、main,执行的流程是怎么样的?

  1. 先执行utils.go
  2. 再执行utils.go下的变量 > init > main
  3. 再回去执行main.go下的变量 > init > main

如果是mian.go文件中的一个函数引用了utils.go下的函数,则流程是

  1. 先执行mian.go,然后走到引用utils.go的代码才会进入utils.go文件中执行

递归

  • 递归指的是一个函数在函数体内调用了自己
  • 当一个函数执行完毕,或者遇到 return,就会返回给调用者,同时当函数执行完毕或者返回时,该函数本身也会被系统销毁

递归注意事项:

  1. 递归一定要有出口。否则内存溢出(出口:什么时候不再调用自己)
  2. 递归虽然有出口,但是递归的次数也不宜过多, 否则内存溢出

演示:

func main() {test(4)
}func test(n int) {if n > 2 {n--test(n)}fmt.Println(n)
}

输出:

2
2
3

递归案例过程分析:

// main调用test,现在N=4
func test(4 int) {if 4 > 2 {4--test(3)}fmt.Println(3)
}func test(3 int) {if 3 > 2 {3--test(2)}fmt.Println(2) 
}func test(2 int) {if 2 > 2 {不成立,if执行完以后,就会把n的值返回给调用者,会往上面传}fmt.Println(2)
}// 这段代码是在栈中完成的,栈的特点是先进后出,所以打印的结果是2、2、3

斐波那契数

给你一个整数n,请使用递归的方式,求出它的斐波那契数是多少?

斐波那契数:1,1,2,3,5,8,13…,从第三个数开始是前两个的和

func main() {res := test(6)fmt.Println(res)
}func test(n int) (result int) {if n == 1 || n == 2 {return 1} else {return test(n-1) + test(n-2)}
}

递归求阶乘:

var s = 1func main() {recursion(5)fmt.Println(s)
}func recursion(num int) {if num == 1 {return // 终止函数的意思}s *= numrecursion(num - 1)
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/572121.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NE2018届校招内推笔试——数据挖掘

【单选题|2分/题】 1、在只有两类的情况下&#xff0c;二维特征向量通过共享相同的协方差矩阵的正态分布生成&#xff0c;其中协方差矩阵为&#xff1a; 均值向量分别为&#xff1a;&#xff0c;则根据贝叶斯分类&#xff0c;样本分类为&#xff1a;&#xff08;&#xff09; A…

Go_数组遍历、最大值、求和、多维数组

数组&#xff1a; 数组就是用来存储数据的容器&#xff0c;存储多个数据时数据类型要一致。如果想要保存任意类型数据&#xff0c;需要声明为接口类型数组数组定义完成后&#xff0c;可以对数组进行赋值操作。数组是通过下标来进行操作的&#xff0c;下标的范围是从0开始到数组…

全局变量和环境变量的区别

全局变量:启动脚本了.在各线程,以及主程序中.可以互相传递值.每次启动脚本,初始值都一样.环境变量:启动脚本了.在各线程,以及主程序中.可以互相传递值.每次启动脚本,初始值是上次停止脚本时的值. 例子:Global 全局变量Dimenv 环境变量全局变量 全局变量 1环境变量 环境变量 …

不满足依赖关系

今晚上脑残&#xff0c;替换了实体&#xff0c;把报错的也都替换完成了&#xff0c;但是运行报错&#xff1a; 大概的意思就是说不满足XXXXXX依赖关系&#xff0c;但是找了半天都没有找到&#xff0c;最后是mapper的实体类全路径替换的时候&#xff0c;脑残在后面加上了.java。…

Go_切片(初始化、遍历、截取、修改、append、copy、切片作为函数参数、切片求和、切片求最大值)

切片&#xff1a; 切片的长度是不固定的&#xff0c;可以追加数据&#xff0c;可以理解是一个动态数组&#xff0c;切片的底层是一个结构体切片类型&#xff08;slice&#xff09;本身并不是动态数组或数组指针。它内部通过指针引用底层数组&#xff0c;设定相关属性将操作限定…

Golang——递归的使用

递归指的是函数定义中调用函数本身的现象&#xff08;自己调自己&#xff09;把一个复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算 递归注意事项&#xff1a; 递归一定要有出口。否则内存溢出(出口…

阿里巴巴Java开发手册——速读记录

本随笔基于阿里巴巴Java开发手册V1.2&#xff0c;陆陆续续记录一些现阶段能理解的&#xff0c;有启发的内容&#xff0c;并将持续更新 最佳实践——插件使用已经发布为随笔&#xff01;http://www.cnblogs.com/jiangbei/p/7668654.html 一、编程规范 1.命名规范 &#xff08;1&…

Go_map集合初始化、键值操作、map作为函数参数的使用

map&#xff1a; map是key-value的数据结构&#xff0c;类似于Java的集合&#xff0c;又称为字典&#xff0c;像新华字典就是key:value类型展示的map是无序的&#xff0c;其中key是不允许重复的&#xff0c;key不存在相当于添加&#xff0c;存在相当于修改map的key必须可以进行…

Angular 小试牛刀[1]:Getting Started

首先&#xff0c;Angular2 与 Angular1.x 版本没有多大关系&#xff0c;甚至可以说是两个完全不一样的框架&#xff0c;故 Angular 指的是 Angular2 及以上的版本。而 Angular 与 TypeScript 的完美结合&#xff0c;对于一个 .NET 开发者来说&#xff0c;实在是找不到不用它的理…

Go_指针的使用、数组指针和指针数组、指针与切片、指针与结构体、多级指针

指针&#xff1a; 指针是一个特殊的变量&#xff0c;因为它存储的数据是另一个变量的内存地址&#xff0c;指针本身也是有内存地址的指针的数据类型有int、float、bool、string、数组、结构体指针的作用就是可以通过变量/对象的内存地址去操作变量/对象 注意&#xff1a; 取址运…

linux驱动编写(Kconfig文件和Makefile文件)

在Linux编写驱动的过程中&#xff0c;有两个文件是我们必须要了解和知晓的。这其中&#xff0c;一个是Kconfig文件&#xff0c;另外一个是Makefile文件。如果大家比较熟悉的话&#xff0c;那么肯定对内核编译需要的.config文件不陌生&#xff0c;在.config文件中&#xff0c;我…

Go_结构体与数组、切片、map、方法、作为函数参数、type、Tag

结构体&#xff1a; 结构体是由一系列具有相同类型或不同类型的数据构成的数据集合结构体可以很好的管理数据&#xff0c;使用结构体可以提高程序的易读性&#xff0c;类似于Java的类一样结构体内成员名必须唯一&#xff0c;可用_补位&#xff0c;支持使用自身类型的指针成员。…

vue项目中如何引入ElementUI

1.在cmd中输入命令&#xff1a; npm i element-ui -S 2.在src/main.js文件中增加代码&#xff1a; import ElementUI from element-ui import element-ui/lib/theme-default/index.cssVue.use(ElementUI) 转载于:https://www.cnblogs.com/xuemei/p/7372332.html

Golang——深浅拷贝

浅拷贝&#xff1a;只是拷贝了内存地址&#xff0c;会指向原来的内存&#xff0c;指向原来的内存地址&#xff0c;操作的时候会互相影响 go中的赋值、函数传参、函数返回值都是浅拷贝 深拷贝&#xff1a;会把变量的数据都拷贝一份&#xff0c;包括地址&#xff0c;新的内存地址…

[Java][web]利用Spring随时随地获得Request和Session

利用Spring随时随地获得Request和Session 一、准备工作&#xff1a; 在web.xml中加入 <listener> <listener-class> org.springframework.web.context.request.RequestContextListener</listener-class> </listener>二、用法&#xff1a;…

Golang实现通讯录小案例

代码&#xff1a; package mainimport "fmt"func main() {for {menu()} }type User struct {userName string/**key&#xff1a;表示电话的类型value&#xff1a;电话号码*/addressPhone map[string]string }// 定义切片 var userList make([]User, 0)func menu() …

MySql5.6版修改用户登录密码

1、使用 mysqladmin 方式: 打开命令提示符界面, 执行命令: mysqladmin -u root -p password 新密码 执行后提示输入旧密码完成密码修改, 当旧密码为空时直接按回车键确认即可。 2、UPDATE user 语句&#xff08;我自己用的就是这个方法&#xff09; 这种方式必须是先用root帐户…

Go_面向对象(抽象、封装、继承)

抽象 抽象是一种编程思维方式&#xff0c;是从多个事物中提取共性 例&#xff1a;产品经理和程序员都有工作的方法&#xff0c;但是工作内容不同&#xff0c;可以把工作抽象出来定义为一个方法&#xff0c;具体细节由调用者补充 银行存取款案例&#xff1a; 账号结构体取款方法…

Go_接口、多态、接口继承与转换、空接口、类型断言

接口 接口用于定义对象的行为&#xff0c;接口只指定对象应该做什么&#xff0c;实现这种行为由对象来决定。接口只是把所有具有共性的方法定义在一起&#xff0c;任何类型实现了接口中所有的方法&#xff0c;就是实现了这个接口。接口存在的意义就是用来定义规范&#xff0c;…

Discrete Logging POJ - 2417(BSGS)

Discrete Logging POJ - 2417 题意&#xff1a;给P&#xff0c;B&#xff0c;N&#xff0c;求最小的L使得 BL≡N (mod P)&#xff0c;其中P是素数。 Baby Step Giant Step 1 #include <cstdio>2 #include <cstring>3 #include <iostream>4 #include <cma…