政协网站法治建设版块,番禺人才招聘网,wordpress幻灯片主题设置,苏州十大软件公司招聘由于go不是一门面向对象的语言#xff0c;因此在有一些特性上和java是有一些区别的#xff0c;比如go中就没有类这样的概念。下面来介绍一下go的一些特性。
结构体
结构体类似与java中的类#xff0c;但又不完全一样。在类中#xff0c;可以定义字段和方法#xff0c;但…由于go不是一门面向对象的语言因此在有一些特性上和java是有一些区别的比如go中就没有类这样的概念。下面来介绍一下go的一些特性。
结构体
结构体类似与java中的类但又不完全一样。在类中可以定义字段和方法但是在结构体中是不可以定义方法或者函数的。
定义结构体
下面是一段定义结构体的代码
package demotype People struct {age intname string
}其中type关键字的作用是表明后面一个东西是一个类型是什么类型呢struct类型。这个类型叫什么名字呢People。
当然了还可以在People中定义一个结构体
package demotype People struct {age intname string
}type Student struct {people PeoplestudentId int
}Student结构体中有一个People结构体除此之外还包含了一个StudentId字段。这个例子也多少有那么一点继承的味道吧。
使用
使用结构体的方式也很简单
package demo
import fmtfunc useStruct() {var people Peoplepeople.age 10people.name peoplefmt.Println(people.name)var p1 People{age: 0,name: ,}fmt.Println(p1)
} 上面people的类型是People如果在一个方法内对传入的people做修改外面的是不会受到影响的。如果需要直接访问它本身的话则需要使用指针结构体指向结构体的指针。需要注意的是只有初始化后才能进行访问否则会nil。下面两种声明方式是等价的
var p1 new(People)
fmt.Println(p1)var p2 People{}
fmt.Println(p2)函数和方法
在go中函数和方法是两个不同的概念这也是与java不同的一点。函数可以类比于java中的静态方法不需要创建一个类就可以直接调用可以说是相对。对于go来说一个函数不属于任何结构体和类型是没有接收者的。与之相对的方法就是比函数多出来一个接收者。
函数
package demofunc add(a, b) int {return a b;
}func Add(a, b) int {return a b;
}比如上述代码中add和Add就是作为一个函数的身份出现的。需要注意的是go中没有访问限定符只是根据函数名首字母的大小写来确定该函数是否能被其他包来使用。比如add方法不能别其他包来引用而Add方法就可以。使用时只需要调用demo.Add(a, b)就可以了包名.函数名。
在java中要想将一个函数作为参数只能传一个接口然后去实现它。在go中可以直接将一个函数作为另一个函数的参数进行传递。
package demofunc twoTimes(a, b int) int {return a b
}func threeTimes(f func(int, int) int, c int) int {return f(c, c) c
}还可以使用别名进行简化
package demofunc twoTimes(a, b int) int {return a b
}type tTs func(int, int) intfunc threeTimes(f tTs, c int) int {return f(c, c) c
}方法
函数有点独立的感觉那有时候我们需要让函数和结构体关联起来要怎么做呢这时候就需要使用方法了。方法是和其接收者——一个结构体绑定在一起的
package demotype People struct {age intname string
}func (p People) getName() string {return p.name
} 可以这样说这个getName成了People的函数了
package demofunc useGetName() {var p new(People)p.getName()
}需要注意的是上面getName方法接受的是People的一个副本函数里面的操作不会对原有的p有任何影响。如果想要影响它就需要使用接收者的指针了。 在调用方法的时候传递的接收者本质上都是副本只不过一个是这个值副本一是指向这个值指针的副本。指针具有指向原有值的特性所以修改了指针指向的值也就修改了原有的值。我们可以简单的理解为值接收者使用的是值的副本来调用方法而指针接收者使用实际的值来调用方法。 package demo
func useGetName() {var p new(People)p.setName(abc)fmt.Println(p) // {0 }p.setPName(abc)fmt.Println(p) // {0 abc}
}func (p *People) setName(name string) {p.name name
}func (p *People) setPName(name string) {p.name name
}多值返回
在java中想要返回多个值只能使用一个类进行包装再返回而在go中可以直接返回多个值。在标准库中经常见到一个函数返回两个值一个是结果另一个是错误信息。
func main() {file, err : os.Open(/usr/tmp)if err ! nil {log.Fatal(err)return}fmt.Println(file)
}如果有不想使用的值那么用_来进行忽略
file, _ : os.Open(/usr/tmp)定义一个多值返回的函数
package demofunc getPeopleInfo(p People) (string, int) {return p.name, p.age
}接口
go中的接口也是一组方法的定义只要一个类型实现了这个接口的所有方法那么它就是实现了这个接口。只要这个接口声明的方法被全部实现那么这个接口就可以用了。
package mainimport fmtfunc main() {s : new(student)s.name studentc : sfmt.Println(c.onClass())
}type student struct {name string
}type teacher struct {name string
}type classRoom interface {onClass() string
}func (s student) onClass() string {return s.name
}func (t teacher) onClass() string {return t.name
}当然了一个类型可以实现多个接口一个接口也可以被多个类型实现。接口呢就是说这是一个有这么多方法的一个类型。至于方法是怎么实现的并不关心。具体的实现是交给结构体和方法去做的。只要能做出来满足这个接口定义的就全部都可以称之为这个接口类型。
空接口interface{}可以是任意类型在go1.18之后的泛型any本质上就是空接口的别名type any。