写在开头
之前写过关于go语言基础的入门语法,对于完全没有接触过go语言的同学,可以先看看这个Go 语言入门基础语法(1)|青训营 - 掘金 (juejin.cn)。 以下将介绍关于更进一步的go语言的内容。
1 函数
1.1 返回值
之前一篇笔记简单介绍过函数,函数可以给返回值命名,可以通过返回值名直接对应到函数内部的变量。
func add(a, b int) (c int) {
c=a+b
return
}
由于函数的这个特性,在返回值命名后,可以通过名字来修改返回值。
func get(i int)(c int){
c=3
return
}
func main() {
for i:=0 ;i<3;i++{
fmt.Println(get(i))//全部输出3
}
}
1.2 defer语句
可以通过defer语句在return语句之后修改返回值,defer语句会在当前函数return之后才会执行,也就是只有在函数在执行结束之后才会执行defer里的语句。defer语句后跟的函数,先被defer的后执行,这里满足先进后出,类似于将先访问的函数压入栈,最后逆序执行。
如下实例中,defer语句当函数结束后执行,defer的顺序为123,输出顺序为321.
func main() {
x:=0
for i:=0 ;i<3;i++{
x++
defer fmt.Print(x," ")//输出为3 2 1
}
2 方法
方法是面向对象编程时用到的,而但是Go语言的方法却是关联到类型的,在编译阶段就完成了方法的静态绑定,对该对象进行操作时,可以直接通过方法完成。
函数形式
type FF struct{
a int
b string
}
func geta(f *FF){
fmt.Println("输出a",f.a)//输出“输出a 10”
}
func main() {
f1:=FF{10,"f1"}
geta(&f1)
}
方法形式
func (f *FF)geta(){
fmt.Println("输出a",f.a)
}
func main() {
f1:=FF{10,"f1"}
f1.geta()
}
输出是相同的,但此时我们已经将geta方法变为结构体FF的专属方法,进入了面向对象编程的行列,方法和函数同样,名字必须是唯一的,不支持重载
3 接口
3.1 接口定义
与Java类似,Go 语言把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。
//定义一个接口
type Book interface {
write()
read()
}
//以下结构体可以分别设置自己的属性
type A struct {
name string
}
type B struct{
id int
}
func (a A) read(){
fmt.Println("该书的名称为",a.name)
}
func (b B) read(){
fmt.Println("该书的id为",b.id)
}
func (a *A) write(){
a.name="East"
}
func (b *B) write(){
b.id=2023
}
func show(book Book){
book.write()
book.read()
}
func main() {
show(new(A))
show(new(B))
}
在上述实例中,定义了一个接口Book,结构体A和B分别代表书的名称和id,使用不同的结构体对接口进行实现,再利用接口对象作为形参,分别将不同类型对象传入函数show中。
在进行接口使用的的时候,会将接口位置的动态类型改为所指向的类型,book.write()和book.read()分别调用了不同类型的方法,实现了多态。
3.2 接口实现
多态的实现有两种方式,分别为值接受型和指针接受型
- 值接受型
没有办法修改接受者本身的属性,只进行值传递,例如上述示例的read方法。 - 指针接受型
传递地址,可以修改指向对象的属性,例如上述示例的write方法。